zoukankan      html  css  js  c++  java
  • 使用 Keras + CNN 识别 MNIST 手写数字

    导入模块:

    from keras.datasets import mnist
    from keras.utils import np_utils
    import numpy as np
    import matplotlib.pyplot as plt
    from keras.models import Sequential
    from keras.layers import Dense,Dropout,Flatten,Conv2D,MaxPooling2D

    下载手写数据集:

    (x_Train,y_Train),(x_Test,y_Test)=mnist.load_data()
    print(x_Train.shape)
    print(y_Train.shape)
    print(x_Test.shape)
    print(y_Test.shape)


    训练数据60000个,长度和宽度都是28,标签也是6000个。

    测试数据10000个。

    图形化数据集,查看前10个数据集:

    def polt_images_label_prediction(images,labels,idx,num=10):
        fig=plt.gcf()
        fig.set_size_inches(12,14)
        for i in range(num):
            ax=plt.subplot(5,2,1+i)
            ax.imshow(images[idx],cmap='binary')
            title='label='+str(labels[idx])
            ax.set_title(title,fontsize=10)
            ax.set_xticks([])
            ax.set_yticks([])
        plt.show()
    polt_images_label_prediction(x_Train,y_Train,0)

    数据预处理:

    将features以reshape转化为6000*28*28*1的4维矩阵,并将其标准化。

    x_Train4D=x_Train.reshape(x_Train.shape[0],28,28,1).astype('float32')
    x_Test4D = x_Test.reshape(x_Test.shape[0], 28, 28, 1).astype('float32')
    x_Train4D_normalize = x_Train4D / 255
    x_Test4D_normalize = x_Test4D / 255

    数据预处理,对标签进行one-hot编码处理:

    #未转化第一个数是 5
    print(y_Train[:1])
    y_TrainOneHot = np_utils.to_categorical(y_Train)
    #转化  One-Hot Encoding 都是以0 1 表示,5 在第六个位置
    print(y_TrainOneHot[:1])

    建立模型:

    #建立一个 Sequential 线性堆叠模型
    model=Sequential()
    #建立第一个卷积层,input_shape 输入数字图像大小为 28*28*1, filters 卷积核个数 16 个,kernel_size 卷积核大小 3*3
    #padding 是否零填充 same 表示填充, activation 激活函数 relu
    model.add(Conv2D(filters = 16,
              kernel_size = (3, 3),
              padding = 'same',
              input_shape = (28, 28, 1),
              activation = 'relu'))
    #建立第一个池化层 pool_size 池化窗口 2
    model.add(MaxPooling2D(pool_size = (2, 2)))
    #建立第二个卷积层, filters 卷积核个数 36 个,kernel_size 卷积核大小 3*3
    #padding 是否零填充 same 表示填充, activation 激活函数 relu
    model.add(Conv2D(filters = 36,
                    kernel_size = (3, 3),
                    padding = 'same',
                    activation = 'relu'))
    #建立第二个池化层 pool_size 池化窗口 2
    model.add(MaxPooling2D(pool_size = (2, 2)))
    #加入Dropout避免过度拟合
    model.add(Dropout(0.25))
    #建立平坦层,将多维向量转化为一维向量
    model.add(Flatten())
    #建立隐藏层,隐藏层有 128 个神经元, activation 激活函数用 relu
    model.add(Dense(128, activation = 'relu'))
    #加入Dropout避免过度拟合
    model.add(Dropout(0.25))
    #建立输出层,一共有 10 个神经元,因为 0 到 9 一共有 10 个类别, activation 激活函数用 softmax 这个函数用来分类
    model.add(Dense(10, activation = 'softmax'))

    查看模型摘要:

    print(model.summary())

    训练模型:

    #定义训练模型, loss 损失函数用 categorical_crossentropy, optimizer 优化器用 adam, metrics 度量用 accuracy
    model.compile(loss = 'categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
    #开始训练模型, x 是训练数据集, y 是训练数据集的标签, validation_split 是把训练数据集分为 8 份训练数据集 2 份验证集
    #epochs 是迭代次数 20, batch_size 是批量 256, verbose 为 2 显示训练过程
    train_history = model.fit(x = x_Train4D_normalize,
                              y = y_TrainOneHot,
                             validation_split = 0.2,
                             epochs = 20,
                             batch_size = 256,
                             verbose = 2)

    查看训练模型loss和accuracy:

    def show_train_history(train_history, train, validation):
        plt.plot(train_history.history[train])
        plt.plot(train_history.history[validation])
        plt.title('Train History')
        plt.ylabel(train)
        plt.xlabel('Epoch')
        plt.legend(['train', 'validation'], loc = 'upper left')
        plt.show()
    show_train_history(train_history, 'loss', 'val_loss')
    show_train_history(train_history, 'accuracy', 'val_accuracy')

    评估模型,准确率为99.21%。

    scores = model.evaluate(x_Test4D_normalize, y_TestOneHot)
    print(scores[1])

    预测模型:

    #预测测试集第一个数字
    prediction = np.argmax(model.predict(x_Test4D_normalize[:1]))
    print('预测值:', prediction)
    print('真实值:', np.argmax(y_TestOneHot[:1]))


    【分析】

    由训练过程数据以及精度图卡伊看出,当迭代到10次的时候就达到了最高精度,后面的另外10次迭代并没有让精度变得更好。所以把epochs改成10再仿真一次:

    模型评估,准确率为99.11%,比迭代20次时准确率降低了0.1%。


    看网上说,训练模型的时候先用小数据大参数,先让它过拟合,再慢慢调小,filter能用256就不用128,所以我先调一下filter参数看看是否会过拟合。

    学到的一条经验就是在看训练参数的时候不要看准确率这个指标,而是要看损失函数这个指标,毕竟优化的就是loss。

    两层的卷积核个数分别改成了32和64.

     但是并没有过拟合。

     准确率99.16%也并没有什么大的变化。

    所以增大卷和核数量,改为64和128。

     准确率99.14%,这是已经过拟合了吧,毕竟训练的accuracy和测试的val_accuracy分别是99.72%和99.15%差的还挺多的。

    再调大参数试试:

    准确率99.32%。

    感觉纠结与此已然没有太多意义,本身就是想练习一下调参。所以打算把参数改成原来的,并且增加一层卷积层试试:


    #建立第三个卷积层, filters 卷积核个数 64 个,kernel_size 卷积核大小 3*3
    #padding 是否零填充 same 表示填充, activation 激活函数 relu
    model.add(Conv2D(filters = 64,
                    kernel_size = (3, 3),
                    padding = 'same',
                    activation = 'relu'))
    #建立第三个池化层 pool_size 池化窗口 2
    model.add(MaxPooling2D(pool_size = (2, 2)))

    多加一层,10次迭代,结果准确率99.17%:

     


    就算模型只有一层卷积层,准确率也有98.6%。

    ——2019.11.12

    我的前方是万里征途,星辰大海!!
  • 相关阅读:
    Python编码规范12-访问控制--访问控制
    Python编码规范11-命名规范--命名约定
    Python编码规范10-命名规范--命名规范
    Python编码规范09-注释--文档注释
    Python编码规范08-注释--代码注释
    Python编码规范07-基础规范--文件和sockets
    Python编码规范06-基础规范--字符串
    Python编码规范05-基础规范--文档字符串(docstring)
    Python编码规范04-基础规范--空格
    Python编码规范03-基础规范--import语句
  • 原文地址:https://www.cnblogs.com/taoyuxin/p/11773445.html
Copyright © 2011-2022 走看看