基于CNN卷积神经网络手写数字识别模型

环境python3.10

今天介绍如何利用卷积神经网络进行MNIST数据集的手写数字识别,即将手写数字图像images识别为数字标签labels。

卷积神经网络是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之一,在图像处理和识别的方向上取得很大的成就,本文只要进行的是基于CNN卷积神经网络的数字识别模型训练。

 

建模思路如下:

1、数据预处理

2、建立模型

3、训练模型

4、评估师准确率

5、预测

 

代码:

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential,load_model
from keras.layers import Dense,Dropout,Convolution2D,MaxPooling2D,Flatten
from keras.optimizers import Adam
import matplotlib.pyplot as plt
from keras.utils.vis_utils import plot_model
from keras.utils.image_utils import load_img,img_to_array
from keras.applications.vgg16 import preprocess_input
import sys,os
import h5py
from PIL import Image
import random


# 载入数据
(x_train,y_train),(x_test,y_test) = mnist.load_data()

# (60000,28,28)->(60000,28,28,1)  60000个数据,28*28,深度为1
x_train = x_train.reshape(-1,28,28,1)/255.0 #-1能够自动匹配,
x_test = x_test.reshape(-1,28,28,1)/255.0
# 换one hot格式
y_train = np_utils.to_categorical(y_train,num_classes=10)
y_test = np_utils.to_categorical(y_test,num_classes=10)



model_path = 'models/shouxie_CNN.h5'
if os.path.exists(model_path):
    model = load_model(model_path)
else:
    # 定义顺序模型
    model = Sequential()
    
    # 第一个卷积层 input_shape 输入平面 filters 卷积核/滤波器个数 kernel_size 卷积窗口大小 strides 步长 padding padding方式 same/valid activation 激活函数
    model.add(Convolution2D(input_shape = (28,28,1), filters = 32, kernel_size = 5, strides = 1, padding = 'same',activation = 'relu'))
    # 第一个池化层
    model.add(MaxPooling2D(pool_size = 2, strides = 2, padding = 'same',))
    # 第二个卷积层
    model.add(Convolution2D(64,5,strides=1,padding='same',activation = 'relu'))
    #像64,5这样的,按照convolution2D这个函数形参顺序传入
    # 第二个池化层
    model.add(MaxPooling2D(2,2,'same'))
    # 把第二个池化层的输出扁平化为1维
    model.add(Flatten())
    # 第一个全连接层
    model.add(Dense(1024,activation = 'relu'))
    # Dropout
    model.add(Dropout(0.5))
    # 第二个全连接层
    model.add(Dense(10,activation='softmax'))
    
    # 定义优化器
    adam = Adam(lr=1e-4)
    
    # 定义优化器,loss function,训练过程中计算准确率
    model.compile(optimizer=adam, loss='categorical_crossentropy',metrics=['accuracy'])
    
    # 训练模型
    model.fit(x_train,y_train,batch_size=64,epochs=30)
            
    # 评估模型
    loss,accuracy = model.evaluate(x_test,y_test)
    
    print('test loss',loss)
    print('test accuracy',accuracy)
    
    model.save(model_path)


    
# 预测图库
n = 10
fig = plt.figure(figsize=(15, 3))
fig.canvas.manager.set_window_title("mnist图库预测结果:")
pre = model.predict(x_test[:n], n)
for i in range(n):
    plt.subplot(5, 10, i + 1)
    t = x_test[i].reshape(28, 28)
    plt.imshow(t, cmap='binary')
    plt.subplots_adjust(wspace=2)   # 调整子图间的间距,挨太紧了不好看
    plt.title('%d' % pre[i].argmax())
    plt.xticks([])  # 取消x轴刻度
    plt.yticks([])
plt.show()



#预测query/number/下面的图片
dirpath = 'query/number/'
filelist = os.listdir(dirpath)
random.shuffle(filelist)
n = len(filelist)
fig = plt.figure(figsize=(15, 3))
fig.canvas.manager.set_window_title("query/number/下面的图片预测结果:")
for i,filename in enumerate(filelist):
    plt.subplot(5, 10, i + 1)
    filepath = os.path.join(dirpath, filename)
    
    img=Image.open(filepath)
    img = img.convert('L')  #图片灰度化
    test_img=img.resize((28,28))   #修改图片大小
    img_arr=np.array(test_img)    #图片转为 np数组
    img_data = img_arr.reshape(1,28,28,1)
    plt.imshow(img_arr, cmap='binary')

    predict = model.predict(img_data)
    predicte = np.argmax(predict[0])
    plt.subplots_adjust(wspace=2)
    plt.title('%d' % predicte)
    plt.xticks([])  # 取消x轴刻度
    plt.yticks([])
    
plt.show()

 

其中query/number 文件写我截了几张手写图片

 

 

 

执行结果:

 

 

 

query/number文件夹下图片我在预测时打乱了顺序:

 

 

 

结果相当不错

如果有个网站或者app的图形验证码是数字和字母组合的,结果你想想,基本和没有一样,呵呵

 

参考:

https://blog.csdn.net/qq_42100276/article/details/121181137

https://blog.csdn.net/weixin_43242765/article/details/106073904/

posted @ 2023-03-13 16:40  河北大学-徐小波  阅读(109)  评论(0编辑  收藏  举报