keras实现经典LeNet-5网络识别手写数字集MNIST

LeNet-5是一个很古老也很经典的CNN网络了,结构比较简单,是针对单通道图像构建的模型,当时提出的作者没有详细考虑到用于3通道图像(RGB彩色图像)的识别运用。

完整工程代码点击这里,如果你觉得对你的学习有所帮助的话也欢迎给个star,谢谢~

一、LeNet网络结构

keras实现经典LeNet-5网络识别手写数字集MNIST_第1张图片

第一层为6个5X5卷积核,步长为1*1,不扩展边界,并输入单通道的灰度图像,输入图像尺寸为32x32;
第二层为2X2的最大值池化层,步长为2X2;
第三层为16个5X5卷积核,步长为1*1,不扩展边界;
第四层为2X2的最大值池化层,步长为2X2;
第五层为展平层,把前面输出的二维数据矩阵打开展开成一维数据,和全连接层对接
第六层为全连接层,120个节点;
第七层为全连接层,84个节点;
第八层为输出层,激活函数为softmax。

值得一提的是,LeNet-5网络隐层部分采用的是tanh激活函数,我们目前常用的ReLU函数当时还没有被采用。

常见的激活函数(Sigmoid,tanh双曲正切,ReLU修正线性单元,Leaky ReLU函数)

二、keras实现LeNet-5

当我们熟悉了keras的基本使用后,就可以搭建简单的网络了,按照上面LeNet-5的网络结构进行实现即可。

代码如下:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers import BatchNormalization

num_class=10#类别数目
input_shape=(32,32,1)#输入的数据尺寸

model = Sequential([
    #第一层为6个5X5卷积核,步长为1*1,不扩展边界padding为valid,并输入单通道的灰度图像
    Conv2D(6,(5,5),padding='valid',strides=(1,1),activation='tanh',input_shape=input_shape),#输入图像尺寸为32x32
    BatchNormalization(),#加入批标准化优化模型
    #第二层为2X2的最大值池化层,步长为2X2
    MaxPooling2D(pool_size=(2,2),strides=(2,2)),
    #第三层为16个5X5卷积核,步长为1*1,不扩展边界padding为valid
    Conv2D(16,(5,5),padding='valid',strides=(1,1),activation='tanh'),
    BatchNormalization(),
    #第四层为2X2的最大值池化层,步长为2X2
    MaxPooling2D(pool_size=(2,2),strides=(2,2)),
    #第五层为展平层,把前面输出的二维数据矩阵打开展开成一维数据,和全连接层对接
    Flatten(),
    #第六层为全连接层,120个节点
    Dense(120,activation='tanh'),
    BatchNormalization(),
    #第七层为全连接层,84个节点;
    Dense(84,activation='tanh'),
    BatchNormalization(),
    Dropout(0.5),#加入dropout防止过拟合
    #第八层为输出层,激活函数为softmax。
    Dense(num_class,activation='softmax')
])

#编译模型,定义损失函数loss,采用的优化器optimizer为Adam
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])

三、LeNet-5训练手写数字集MNIST

MNIST数据集点击这里获取。
keras实现经典LeNet-5网络识别手写数字集MNIST_第2张图片

数据集的加载代码:

import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm

data = np.load('mnist.npz')#加载数据

print('训练集规格:',data['x_train'].shape)
print('训练集标签规格:',data['y_train'].shape)
print('测试集规格:',data['x_test'].shape)
print('测试集标签规格:',data['y_test'].shape)

keras实现经典LeNet-5网络识别手写数字集MNIST_第3张图片

这个数据集的规格大小为28x28的单通道灰度图像。

导入模型训练:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.layers import BatchNormalization
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
import cv2
data = np.load('Dataset/mnist.npz')#加载数据

num_class=10#类别数目
input_shape=(32,32,1)#输入的数据尺寸

train_x=[]
train_y=[]
test_x=[]
test_y=[]

print('loading train_data....')
id=0
for val in tqdm(data['x_train']):
    img=cv2.resize(val,(input_shape[0],input_shape[1]))#修改图像尺寸
    train_x.append(img.reshape(input_shape))#修改读入的数据格式
    train_y.append(data['y_train'][id])
    id+=1

print('loading test_data....')
id=0
for val in tqdm(data['x_test']):
    img=cv2.resize(val,(input_shape[0],input_shape[1]))#修改图像尺寸
    test_x.append(img.reshape(input_shape))#修改读入的数据格式
    test_y.append(data['y_test'][id])
    id+=1

train_x=np.array(train_x)/255.0#标准化
train_y=np.array(train_y)
test_x=np.array(test_x)/255.0#标准化
test_y=np.array(test_y)


lb=preprocessing.LabelBinarizer().fit(np.array(range(num_class)))#对标签进行ont_hot编码
train_y=lb.transform(train_y)#因为是多分类任务,必须进行编码处理
test_y=lb.transform(test_y)




model = Sequential([
    #第一层为6个5X5卷积核,步长为1*1,不扩展边界padding为valid,并输入单通道的灰度图像
    Conv2D(6,(5,5),padding='valid',strides=(1,1),activation='tanh',input_shape=input_shape),#输入图像尺寸为32x32
    BatchNormalization(),#加入批标准化优化模型
    #第二层为2X2的最大值池化层,步长为2X2
    MaxPooling2D(pool_size=(2,2),strides=(2,2)),
    #第三层为16个5X5卷积核,步长为1*1,不扩展边界padding为valid
    Conv2D(16,(5,5),padding='valid',strides=(1,1),activation='tanh'),
    BatchNormalization(),
    #第四层为2X2的最大值池化层,步长为2X2
    MaxPooling2D(pool_size=(2,2),strides=(2,2)),
    #第五层为展平层,把前面输出的二维数据矩阵打开展开成一维数据,和全连接层对接
    Flatten(),
    #第六层为全连接层,120个节点
    Dense(120,activation='tanh'),
    BatchNormalization(),
    #第七层为全连接层,84个节点;
    Dense(84,activation='tanh'),
    BatchNormalization(),
    Dropout(0.5),#加入dropout防止过拟合
    #第八层为输出层,激活函数为softmax。
    Dense(num_class,activation='softmax')
])

model.summary()#显示模型结构

#编译模型,定义损失函数loss,采用的优化器optimizer为Adam
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
#开始训练模型
history=model.fit(train_x,train_y,batch_size = 128,epochs=50,validation_data=(test_x, test_y))#训练1000个批次,每个批次数据量为126


#绘制训练过程的acc和loss
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])

plt.legend(['acc', 'val_acc'], loc='upper left')
plt.title('LeNet-5 Acc')
plt.xlabel("Epoch")#横坐标名
plt.ylabel("Accuracy")#纵坐标名

plt.show()
#图像保存方法
plt.savefig('LeNet-5 acc.png')

plt.figure()

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])

plt.legend(['loss', 'val_loss'], loc='upper left')
plt.title('LeNet-5 Loss')
plt.xlabel("Epoch")#横坐标名
plt.ylabel("Loss")#纵坐标名

plt.show()
#图像保存方法
plt.savefig('LeNet-5 loss.png')


模型结构:
Model: “sequential_1”


Layer (type) Output Shape Param #

conv2d_1 (Conv2D) (None, 28, 28, 6) 156


batch_normalization_1 (Batch (None, 28, 28, 6) 24


max_pooling2d_1 (MaxPooling2 (None, 14, 14, 6) 0


conv2d_2 (Conv2D) (None, 10, 10, 16) 2416


batch_normalization_2 (Batch (None, 10, 10, 16) 64


max_pooling2d_2 (MaxPooling2 (None, 5, 5, 16) 0


flatten_1 (Flatten) (None, 400) 0


dense_1 (Dense) (None, 120) 48120


batch_normalization_3 (Batch (None, 120) 480


dense_2 (Dense) (None, 84) 10164


batch_normalization_4 (Batch (None, 84) 336


dropout_1 (Dropout) (None, 84) 0


dense_3 (Dense) (None, 10) 850

Total params: 62,610
Trainable params: 62,158
Non-trainable params: 452


训练结果:
keras实现经典LeNet-5网络识别手写数字集MNIST_第4张图片
keras实现经典LeNet-5网络识别手写数字集MNIST_第5张图片

可以看到精度还是很高的,一直在98%以上。

希望我的分享对你的学习有所帮助,如果有问题请及时指出,谢谢~

你可能感兴趣的:(深度学习,网络,神经网络,深度学习,tensorflow,计算机视觉)