LeNet-5

深度学习
Published

December 24, 2018

过几天要考试了/(ㄒoㄒ)/~~

还要复习真的不爽.本来两周就可以把NgDL课程撸完,想到明天要交矩阵论作业,今天就去写矩阵作业去了,写了两个小时就不想写了(都不会2333

然后回来撸波代码,用keras写了个LeNet-5网络.

代码

我是TensorFlow 1.12,只要装上KerasTensorflow就可以运行我这个代码.

我这里其他的应该都和原版一样,就是最后的全连接输出层,原版用的是高斯核也就是径向基核,但是我一时没有找到,就用了softmax输出.并且这个网络多训练几次,是可以达到99%正确率的,但是我懒得跑了,我写这个主要以熟悉API为目的 2333

import keras as k
import matplotlib.pyplot as plt
import numpy as np
from keras.callbacks import TensorBoard


def expand(x: np.ndarray):
    '''扩展矩阵 4个像素 都为0'''
    return np.pad(x, ((0, 0), (2, 2), (2, 2)), mode='constant')


if __name__ == "__main__":
    # 读取数据
    (x_train, y_train), (x_test, y_test) = k.datasets.mnist.load_data()

    # 扩充矩阵
    x_train = expand(x_train)
    x_test = expand(x_test)  # [28,28] -> [32,32]

    # 增加通道数 为了卷积匹配
    x_train = np.reshape(x_train, np.append(np.array(x_train.shape), 1))
    x_test = np.reshape(x_test, np.append(np.array(x_test.shape), 1))

    # one hot 编码
    y_train = k.utils.to_categorical(y_train, num_classes=10)
    y_test = k.utils.to_categorical(y_test, num_classes=10)

    # 归一化
    x_train = x_train / 255.0
    x_test = x_test / 255.0

    # 绘图
    # plt.imshow(x_train[0])
    # plt.show()

    # 创建模型
    mod = k.models.Sequential(name='leNet-5')

    '''C1层是一个卷积层输入图片:32*32
    卷积核大小:5*5
    卷积核种类:6
    输出featuremap大小:28*28 (32-5+1)
    神经元数量:28*28*6
    连接数:(5*5+1)*6*28*28'''
    mod.add(k.layers.Convolution2D(filters=6, kernel_size=(5, 5), kernel_initializer=k.initializers.he_normal(1)))

    '''
    S2层是一个下采样层
    输入:28*28
    采样区域:2*2
    采样方式:4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。结果通过sigmoid
    采样种类:6
    输出featureMap大小:14*14(28/2)
    神经元数量:14*14*6
    '''
    mod.add(k.layers.AveragePooling2D(pool_size=(2, 2)))
    mod.add(k.layers.Activation('sigmoid'))

    '''
    C3层也是一个卷积层
    输入:S2中所有6个或者几个特征map组合
    卷积核大小:5*5
    卷积核种类:16
    输出featureMap大小:10*10 (14-5+1)
    '''
    mod.add(k.layers.Conv2D(filters=16, kernel_size=(5, 5), kernel_initializer=k.initializers.he_normal(2)))

    '''
    S4层是一个下采样层
    输入:10*10
    采样区域:2*2
    采样种类:16
    输出featureMap大小:5*5(10/2)
    神经元数量:5*5*16=400
    '''
    mod.add(k.layers.AveragePooling2D(pool_size=(2, 2)))

    '''
    C5层是一个卷积层
    输入:S4层的全部16个单元特征map(与s4全相连)
    卷积核大小:5*5
    卷积核种类:120
    输出featureMap大小:1*1(5-5+1)
    '''
    mod.add(k.layers.Conv2D(filters=120, kernel_size=(5, 5), kernel_initializer=k.initializers.he_normal(3)))

    '''
    F6层全连接层
    输入:c5 120维向量
    激活函数:sigmoid
    '''
    mod.add(k.layers.Flatten())
    mod.add(k.layers.Dense(120))
    mod.add(k.layers.Dense(10))
    mod.add(k.layers.Activation('softmax'))

    mod.compile(optimizer=k.optimizers.adam(),
                loss='categorical_crossentropy',
                metrics=['accuracy'])
    # 训练模型
    his = mod.fit(x=x_train, y=y_train,
                  batch_size=32,
                  epochs=4,
                  validation_split=0.1,
                  callbacks=[TensorBoard(log_dir='./log_dir')])

    '''可视化训练结果  (为什么验证集准确率比训练集还高?'''
    # 绘制验证集,测试集准确率曲线
    plt.plot(his.history['acc'])
    plt.plot(his.history['val_acc'])
    plt.title('Model accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    plt.show()

    # 绘制验证集,训练集 误差曲线
    plt.plot(his.history['loss'])
    plt.plot(his.history['val_loss'])
    plt.title('Model loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    plt.show()

    '''评估测试集'''
    evahis = mod.evaluate(x=x_test, y=y_test)
    print('测试集准确率为{:.3f}%'.format(evahis[1] * 100))

    '''显示模型'''
    k.utils.plot_model(mod, show_shapes=True)

运行结果

输出


   32/10000 [..............................] - ETA: 0s
 1952/10000 [====>.........................] - ETA: 0s
 3776/10000 [==========>...................] - ETA: 0s
 5760/10000 [================>.............] - ETA: 0s
 7872/10000 [======================>.......] - ETA: 0s
 9984/10000 [============================>.] - ETA: 0s
10000/10000 [==============================] - 0s 26us/step
测试集准确率为97.450%

图像

准确率曲线

损失曲线

网络结构