'''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
# 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)
# # 新建一个打印层
'''添加一个类,实时打印训练集结果
后续可以完成,将该新类作为网络中的一个(图像输出)层加入进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)
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
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'])