正式代码

导入

In [1]:
'''Trains a simple convnet on the MNIST dataset.
'''
#导入各种包
from __future__ import print_function
import matplotlib.pyplot as plt
import keras
#导入手写数据集
from keras.datasets import mnist
#导入sequential模型包
# Keras.models 中有两种类型的模型,Sequential 和 Model
# Sequential 单输入单输出, Model 多输入多输出
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
from keras.utils import plot_model
#绘制混淆矩阵
import pandas as pd

#Epoch: 使用训练集的全部数据对模型进行一次完整的训练
#Batch: 使用训练集中的一小部分样本对模型权重进行一次反向传播的参数更新,batch_size
#表示一个batch中所含的样本数量
#Iteration: 完成一次epoch所需的batch个数
batch_size = 128
num_classes = 10
epochs = 12
Using TensorFlow backend.

引入训练样本

特征提取

In [2]:
# input image dimensions
# 与网站(24*24)不同
img_rows, img_cols = 28, 28

# the data, shuffled and split between train and test sets
# 定义一个空的元组,解包
(x_train, y_train), (x_test, test_label) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

# astype 修改数据类型
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
'''x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples'''

# convert class vectors to binary class matrices
# 一种特征提取的方法 one-hot
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(test_label, num_classes)
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples

建立模型

In [3]:
# # 新建一个打印层
'''添加一个类,实时打印训练集结果
后续可以完成,将该新类作为网络中的一个(图像输出)层加入进model中
是否需要更改源代码?
'''
Class PrintLayer(Layer):
    def __init__(self,**kwargs):
        super(PrintLayer, self).__init__(**kwargs)
        #调用该层时执行的方法
    def __call__(self,layer,x):
        # 获取每层的权重或者特征图等需要的信息
        return(x)

model.add(PrintLayer(layer))
        
#建立Sequential 模型
model = Sequential()
#建立二维卷积层
""" 
    参数:
        filters - 建立的滤镜个数
        kernel_size - 滤镜大小
        padding - 填充:当为'same'时,使得图像卷积后的大小保持不变
        input_shape - 输入图形大小
        activation - 设置激活函数
        步长?默认为1
        
keras.layers.convolutional.Conv2D(filters, kernel_size,strides=(1,1), padding='valid', data_format=None,
 dilation_rate=(1,1), activation=None, use_bias=True, kernel_initializer='glorot_uniform',
 bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None,
 kernel_constraint=None, bias_constraint=None)
"""
kernel_size=(3, 3)
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))

model.add(Conv2D(64, (3, 3), activation='relu'))
#建立池化层
""" 
    参数:
        pool_size - 池化层大小
        
"""
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
#建立平坦层
model.add(Flatten())
#建立隐蔽层(全连接层)
model.add(Dense(128, activation='relu'))
#正则化
model.add(Dropout(0.5))
#建立输出层(全连接层)从128->10
model.add(Dense(num_classes, activation='softmax'))

#查看模型摘要
print(model.summary())

#绘制一张模型图
filepath = 'D:\永无止境的事\图像模式识别\作业'
filename = '\model.png'
plot_model(model, to_file=filepath+filename, show_shapes = True)
WARNING:tensorflow:From d:\python\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
WARNING:tensorflow:From d:\python\lib\site-packages\keras\backend\tensorflow_backend.py:3445: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.
Instructions for updating:
Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 12, 12, 64)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               1179776   
_________________________________________________________________
dropout_2 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________
None

定义训练方式

In [4]:
model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

开始训练

In [7]:
H = []
W = []
for epo in range(1,epochs+1):
    history = model.fit(x_train, y_train,
              batch_size=batch_size,
              epochs=epo,
              verbose=1,
              validation_data=(x_test, y_test),
                initial_epoch = epo-1)
    score = model.evaluate(x_test, y_test, verbose=0)
    H.append(history)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])

    # 取某层输入,采用函数模型来取
    conv2d_1_layer_model = Model(inputs = model.input, 
                                 outputs = model.get_layer('conv2d_1').output)
    conv2d_1_output = conv2d_1_layer_model.predict(x_test)

    print (conv2d_1_output.shape)

    # 绘制该层特征图
    Width_1,Height_1,filters_1 = conv2d_1_output.shape[1:]
    #conv_pic = np.zeros((pic_len,Width_1,Height_1,filters_1))

    for _ in range(filters_1):
        # 只绘制一个样本的结果
        show_img = conv2d_1_output[1,:,:,_]
        show_img.shape = [Width_1,Height_1]
        plt.subplot(8,4,_+1)
        plt.imshow(show_img, cmap='gray')
        plt.axis('off')
    plt.show()

    # 绘制该层的权值图
    weight_conv2d_1,bias_conv2d_1 = model.get_layer('conv2d_1').get_weights()
    print(weight_conv2d_1.shape)
    print(bias_conv2d_1.shape)
    W.append(weight_conv2d_1)

    for i in range(filters_1):
        # 只绘制一个样本的结果
        show_img1 = weight_conv2d_1[:,:,:,i]
        show_img1.shape = [kernel_size[0],kernel_size[1]]
        plt.subplot(8,4,i+1)
        plt.imshow(show_img1, cmap='gray')
        plt.axis('off')
    plt.show()

# 添加进History中
history_acc = []
history_val_acc = []
history_loss = []
history_val_loss = []
history_weight = []
for m in range(1,epochs+1):
    history_acc.append(H[m-1].history['acc'])
    history_val_acc.append(H[m-1].history['val_acc'])
    history_loss.append(H[m-1].history['loss'])
    history_val_loss.append(H[m-1].history['val_loss'])
    #history_weight.append = W[m-1].weight_conv2d_1[:,:,:,1]
    
# 绘制训练 & 验证的准确率值
# ctrl+/ 批量加注释和删除注释
# plt.plot(history.history['acc'])
# plt.plot(history.history['val_acc'])
plt.plot(history_acc)
plt.plot(history_val_acc)
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# 绘制训练 & 验证的损失值
# plt.plot(history.history['loss'])
# plt.plot(history.history['val_loss'])
plt.plot(history_loss)
plt.plot(history_val_loss)
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# 绘制权值变化图
'''for p in range(kernel_size[0]):
    for q in range(kernel_size[0]):'''
history_weights = [[],[],[],[],[],[],[],[],[]]
i = 0

for p in range(kernel_size[0]):
    for q in range(kernel_size[0]):
        for m in range(epochs):
            history_weights[i].append(W[m][p][q][0,0]) #绘制第一个卷积核的权值变化图
        i = i+1

for j in range(kernel_size[0]**2):
    plt.subplot(3,3,j+1)
    plt.plot(history_weights[j])
    if j == 3:
        plt.ylabel('weight',fontsize='small')
    if j == 7:
        plt.xlabel('Epoch',fontsize='small')
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,wspace=0.35)
plt.show()
    

print('Test loss:', score[0])
print('Test accuracy:', score[1])

# 绘制混淆矩阵
prediction = model.predict_classes(x_test)
pd.crosstab(test_label,prediction,rownames=['label'],colnames=['predict'])
WARNING:tensorflow:From d:\python\lib\site-packages\tensorflow\python\ops\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.
Train on 60000 samples, validate on 10000 samples
Epoch 1/1
60000/60000 [==============================] - 163s 3ms/step - loss: 0.2747 - acc: 0.9155 - val_loss: 0.0560 - val_acc: 0.9838
Test loss: 0.05604229638921097
Test accuracy: 0.9838
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 2/2
60000/60000 [==============================] - 171s 3ms/step - loss: 0.0876 - acc: 0.9740 - val_loss: 0.0395 - val_acc: 0.9865
Test loss: 0.039545669446652755
Test accuracy: 0.9865
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 3/3
60000/60000 [==============================] - 170s 3ms/step - loss: 0.0664 - acc: 0.9799 - val_loss: 0.0347 - val_acc: 0.9878
Test loss: 0.03469231442993041
Test accuracy: 0.9878
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 4/4
60000/60000 [==============================] - 169s 3ms/step - loss: 0.0540 - acc: 0.9835 - val_loss: 0.0310 - val_acc: 0.9893
Test loss: 0.03101704681951087
Test accuracy: 0.9893
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 5/5
60000/60000 [==============================] - 168s 3ms/step - loss: 0.0466 - acc: 0.9861 - val_loss: 0.0288 - val_acc: 0.9899
Test loss: 0.028805384747791686
Test accuracy: 0.9899
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 6/6
60000/60000 [==============================] - 168s 3ms/step - loss: 0.0392 - acc: 0.9879 - val_loss: 0.0283 - val_acc: 0.9908
Test loss: 0.028251371622944863
Test accuracy: 0.9908
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 7/7
60000/60000 [==============================] - 169s 3ms/step - loss: 0.0381 - acc: 0.9885 - val_loss: 0.0249 - val_acc: 0.9915
Test loss: 0.024904604941872823
Test accuracy: 0.9915
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 8/8
60000/60000 [==============================] - 165s 3ms/step - loss: 0.0337 - acc: 0.9902 - val_loss: 0.0273 - val_acc: 0.9900
Test loss: 0.027260986616818264
Test accuracy: 0.99
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 9/9
60000/60000 [==============================] - 166s 3ms/step - loss: 0.0325 - acc: 0.9900 - val_loss: 0.0266 - val_acc: 0.9916
Test loss: 0.026579404972278644
Test accuracy: 0.9916
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 10/10
60000/60000 [==============================] - 193s 3ms/step - loss: 0.0287 - acc: 0.9913 - val_loss: 0.0259 - val_acc: 0.9915
Test loss: 0.025907369350982482
Test accuracy: 0.9915
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 11/11
60000/60000 [==============================] - 190s 3ms/step - loss: 0.0272 - acc: 0.9916 - val_loss: 0.0298 - val_acc: 0.9908
Test loss: 0.029785407224008215
Test accuracy: 0.9908
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Train on 60000 samples, validate on 10000 samples
Epoch 12/12
60000/60000 [==============================] - 172s 3ms/step - loss: 0.0263 - acc: 0.9918 - val_loss: 0.0279 - val_acc: 0.9919
Test loss: 0.027934975895853496
Test accuracy: 0.9919
(10000, 26, 26, 32)
(3, 3, 1, 32)
(32,)
Test loss: 0.027934975895853496
Test accuracy: 0.9919
Out[7]:
predict 0 1 2 3 4 5 6 7 8 9
label
0 977 0 0 0 0 0 2 1 0 0
1 0 1135 0 0 0 0 0 0 0 0
2 1 3 1022 0 1 0 0 5 0 0
3 0 0 2 1004 0 3 0 0 1 0
4 0 0 0 0 978 0 2 0 0 2
5 2 0 0 6 0 883 1 0 0 0
6 4 2 0 0 1 1 949 0 1 0
7 0 3 5 0 0 0 0 1019 1 0
8 3 2 1 1 1 0 0 2 961 3
9 0 2 0 0 6 3 0 5 2 991