keras学习(三)CNN处理mnist

  这次是通过CNN来处理训练mnist数据集,CNN的结构是根据视频学的最简单的结构,在模型编译后使用model.summary()就可以将模型结构显示出来,如下图。也有另一种方法plot_model(model, to_file = 'model.png',show_shapes = True),这个显示出来的就比上一种好看,这个是直接输出图片,里面是一种有向图,很直接的将模型结构画出来了。

  卷积——>池化——>卷积——>池化——>全连接——>全连接,就这么简单,不过在每个卷积和全连接层后有个激活函数层。
  这次我想着把mnist里面究竟是什么东西搞清楚,所以就有了下面的代码:

def plot_x_y():
    (x_train, y_train), (x_test, y_test) = mnist.load_data()  # x:60000*28*28,y:60000
    # 可视化x_train
    for i in range(10):
        img = Image.fromarray(x_train[i]) #这个代码是将数组转成图片格式,理论上只要是数组形式的数据都可以#可视化。
                                          #因为颜色属性是在0-255之间,所以一般数组里面的值在0-255之间才有颜色显示,如果高于255
                                          #可视化的时候就采取255代替,也就是显示白色;反之小于0就是黑色。
        plt.imshow(img)
        plt.show()
    # 可视化一下y,然后我就没事干,想看一下y,但是因为原本的y是一个一维数组,里面有60000个0-9之间的数字,因此这个看起来没啥意思,
    #所以需要下面的代码将y处理成独热(one hot)标签。
    y_train = np_utils.to_categorical(y_train, num_classes=10)
    for i in range(10):
        if y_train[0][i] == 1: #啊,这一步,因为one hot里面只有0,1,他两颜色太接近,可视化看不出来,所以将 
                               #1变成255,这样显示就是白色,有明显对比了。
            y_train[0][i] = 255
    img = Image.fromarray(y_train[0])
    plt.imshow(img)
    plt.show()

  x里面的图片显示出来就是下面这样子,只显示了前10张图片:

  y可视出来了是这个样子,其实没啥看的,就是好玩,我把它横过来了,正常是竖着的:

  然后就是正规工作了,代码如下:

import numpy as np
import pickle as p
from PIL import Image
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Activation, Convolution2D, MaxPooling2D, Dense, Flatten
from keras.utils import np_utils
from keras.optimizers import Adam
import matplotlib.pyplot as plt
import matplotlib.image as plimg

from keras.utils.vis_utils import plot_model as plt_


(x_train, y_train), (x_test, y_test) = mnist.load_data() #x:60000*28*28,y:60000

x_train = x_train.reshape(-1, 1, 28, 28)  #转成n个(1*28*28)的数据,1为高,
x_test = x_test.reshape(-1, 1, 28, 28) #
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)


#搭建模型
model = Sequential()
###第一层需要写入输入尺寸,后面的不需要,但是在全连接时要写输出层数,卷积层处理完后要加一个激活函数层
#卷积:  输入:1*28*28     输出:32*28*28
model.add(Convolution2D(filters=32,  #卷积核数目,也是输出通道数(高度)
                        kernel_size=(5, 5), #卷积核为5*5
                        padding='same',    #padding,确保长宽不变
                        input_shape=(1, 28, 28)  #输入
                        ))
model.add(Activation('relu'))
###池化通道数不变,长宽减半,卷积长宽不变,高度增加
#池化:  输入:32*28*28     输出:32*14*14
model.add(MaxPooling2D(pool_size=(2, 2),
                       strides=(2, 2),
                       padding='same',
                       ))
#卷积:  输入:32*14*14     输出:64*14*14
model.add(Convolution2D(filters=32,
                        kernel_size=(5, 5),
                        padding='same',
                        ))
model.add(Activation('relu'))
#池化:  输入:64*14*14     输出:64*7*7
model.add(MaxPooling2D(pool_size=(2, 2),
                       strides=(2, 2),
                       padding='same',
                       ))
#全连接:  输入:64*7*7=3136     输出:1024(自己设置)
model.add(Flatten()) #Flatten将64*7*7变成3136
model.add(Dense(1024))
model.add(Activation('relu'))

#全连接:  输入:1024     输出:10
model.add(Dense(10))
model.add(Activation('softmax'))

#编译模型,
adam = Adam(lr=0.0001) #优化器
model.compile(optimizer=adam, 
              loss='categorical_crossentropy',
              metrics=['accuracy'])

model.summary() #将模型结构输出
#训练
print("-------------------train--------------")
model.fit(x_train, y_train, epochs=2, batch_size=100) #因为总数据有60000个,所以batch_size就写100了。 
                                             #epochs设置1/2结果就挺可观了,不需要设置太大了

#测试
print("---------------------test--------------")
loss, accuracy = model.evaluate(x_test, y_test)
print(loss, accuracy)

  下面是训练过程:

  最后测试集的loss和准确度分别有0.17145和0.94919,结果还是挺高的

posted @ 2020-08-02 22:59  Yuzuriha_Inori  阅读(186)  评论(0编辑  收藏  举报