12-2 Minist 手写字体识别-LeNet-5-函数式模型
【基础要点】
1-加载Minist数据,并变形
2-数据信息图形化显示
3-可视化训练过程
4-可视化预测
5-误差矩阵显示
【代码实现】
1-超参数
1 #输入图像数据信息 2 IMG_WIDTH = 28 3 IMG_HEIGHT =28 4 IMG_CHANNEL = 1 5 6 #第一层卷积层参数 7 CONV_1_DEEP = 32 8 CONV_1_SIZE = 5 9 CONV_1_STEP = 1 10 CONV_1_PADDING = 'same' 11 12 #第二层池化层参数 13 POOL_2_SIZE = 2 14 POOL_2_STEP = 2 15 16 #第三层卷积层参数 17 CONV_3_DEEP = 64 18 CONV_3_SIZE = 5 19 CONV_3_STEP = 1 20 CONV_3_PADDING = 'same' 21 22 #第四层池化参数 23 POOL_4_SIZE = 2 24 POOL_4_STEP = 2 25 26 #第五层全连接层参数 27 DENSE_5_NODES = 120 28 29 #第六层全连接层参数 30 OUTPUT_6_NODES = 10
2-全部代码
1 %matplotlib inline 2 import numpy as np #导入 numpy 3 import matplotlib.pyplot as plt #与 matplotlib 库 4 5 from keras import utils 6 from keras.datasets import mnist #导入Minist数据文件 7 from keras.layers import Input, Conv2D, Activation, MaxPooling2D, Flatten, Dense, Dropout #导入用到的层 8 from keras.models import Model #导入Model 9 10 #from keras.optimizers import SGD #导入SGD 随机梯度下降优化器模块 11 12 # 引入Tensorboard,训练可视化用 13 from keras.callbacks import TensorBoard 14 from keras.utils import plot_model 15 16 #定义超参数 17 #输入图像数据信息 18 IMG_WIDTH = 28 19 IMG_HEIGHT =28 20 IMG_CHANNEL = 1 21 22 #第一层卷积层参数 23 CONV_1_DEEP = 32 24 CONV_1_SIZE = 5 25 CONV_1_STEP = 1 26 CONV_1_PADDING = 'same' 27 CONV_1_ACT = 'relu' 28 29 #第二层池化层参数 30 POOL_2_SIZE = 5 31 POOL_2_STEP = 2 32 33 #第三层卷积层参数 34 CONV_3_DEEP = 64 35 CONV_3_SIZE = 5 36 CONV_3_STEP = 1 37 CONV_3_PADDING = 'same' 38 CONV_3_ACT = 'relu' 39 40 #第四层池化参数 41 POOL_4_SIZE = 5 42 POOL_4_STEP = 2 43 44 #第五层全连接层参数 45 DENSE_5_NODES = 120 46 47 #第六层全连接层参数 48 OUTPUT_NODES = 10 49 50 #下载训练数据和测试数据,并显示数据格式 51 def down_and_show_train_and_test_data(): 52 return mnist.load_data() 53 54 #图形化展示数据 55 def show_img_of_minsit_datas(x,y,width=12,height=6,rows=2,cols=5): 56 fig = plt.gcf() 57 fig.set_size_inches(width, height) 58 length = len(x) 59 if length>rows*cols: 60 length = rows*cols 61 for i in range(length): 62 ax=plt.subplot(rows,cols,i+1) #绘制子图 63 ax.set_title("Label:{}".format(y[i]),fontsize=10) # 设置子图的标题 64 ax.set_xticks([]);ax.set_yticks([]) #不显示x轴和y轴坐标 65 plt.imshow(x[i], cmap='gray', interpolation='none') 66 67 #数据格式变换 68 def reshap_minist_data_to_4(data): 69 #注意,这里要做一次形状变换 70 return data.reshape(-1, 28, 28,1).astype('float32') 71 72 #创建 LeNet-5 模型 73 def creat_model(): 74 inputs = Input((IMG_HEIGHT,IMG_WIDTH,IMG_CHANNEL)) #[*]注意,两个括号 75 conv2d_1 = Conv2D(32, (5, 5), padding ='same',activation='relu',name = 'first_layer')(inputs) 76 maxpool_2 = MaxPooling2D(pool_size=(2,2), strides=2, padding='same')(conv2d_1) 77 conv2d_3 = Conv2D(64, (5, 5), padding = 'same',activation='relu')(maxpool_2) 78 maxpool_4 = MaxPooling2D(pool_size=(2,2), strides=2, padding='same')(conv2d_3) 79 flatten = Flatten()(maxpool_4) #[*]注意,两个括号 80 dense_5 = Dense(120,activation='relu')(flatten) 81 dense_5 = Dropout(0.5)(dense_5) 82 outputs = Dense(10,activation='softmax')(dense_5) 83 84 model = Model(inputs=[inputs], outputs=[outputs]) 85 86 return model 87 88 def main(): 89 (x_train,y_train),(x_test,y_test)=down_and_show_train_and_test_data() #下载数据 90 show_img_of_minsit_datas(x_train,y_train) #显示部分测试数据 91 #图像数据格式转换 92 x_train = reshap_minist_data_to_4(x_train) 93 x_test = reshap_minist_data_to_4(x_test) 94 95 #标签数据Durex编码 96 nb_classes = 10 #类别种类 97 y_train = utils.to_categorical(y_train, nb_classes) 98 y_test = utils.to_categorical(y_test, nb_classes) #对训练标签数据进行独热编码 99 100 #显示输入输出数据形状 101 print("输入输出数据形状:") 102 print("x_train:",x_train.shape) 103 print("x_test:",x_test.shape) 104 print("y_train:",y_train.shape) 105 print("y_test:",y_test.shape) 106 107 #创建模型 108 model = creat_model() 109 110 #编译模型 111 model.compile(loss='categorical_crossentropy', optimizer="sgd")#[*]adam损失函数下降很慢,使用sgd后损失函数快速下降 112 #model.compile(optimizer=Adam(), loss='categorical_crossentropy', metrics=['accuracy']) 113 114 #设置TensorBoard回调函数 115 tb = TensorBoard(log_dir='E:\log', # log 目录 116 histogram_freq=1, # 按照何等频率(epoch)来计算直方图,0为不计算 117 batch_size=32, # 用多大量的数据计算直方图 118 write_graph=True, # 是否存储网络结构图 119 write_grads=False, # 是否可视化梯度直方图 120 write_images=False,# 是否可视化参数 121 embeddings_freq=0, 122 embeddings_layer_names=None, 123 embeddings_metadata=None) 124 callbacks = [tb] 125 126 #训练模型 127 model.fit(x_train,y_train,epochs=2,batch_size=128, 128 verbose=1,validation_data=(x_test,y_test), #verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录 129 callbacks=None) #这里没使用回调函数,报数据类型错误 130 #给模型打分,输出训练好的模型在测试集上的表现 131 score_history = model.evaluate(x_test, y_test, batch_size=128) 132 print('Test accuracy:', score_history) 133 134 #测试代码 135 if __name__ == '__main__': 136 main()
3-可视化模型结构:
Keras的utils里面专门有一个plot_model()
函数是用来可视化网络结构的,为了保证格式美观,我们在定义模型的时候给每个层都加了一个名字。
3-可视化训练过程
1-在model的fit函数中加入TensorBoard的回调函数即可,训练数据就会自动保存在log_dir指定的目录内
2-打开相同环境下的命令窗口,执行命令 tensorboard –logdir= log_dir (参数保存的目录)
3-根据命令行的提示,在浏览器内输入网址,例如我的网址为:http://microwin10-1735:6006
TensorBoard会记录loss及model.metrics里面的值,本例中即acc,loss,val_acc,val_loss四个值,每个epoch更新一次。
除了这些SCALARS,还会记录网络的GRAPH,直接可视化网络结构,但是相比用原生TensorFlow生成的图而言,相差还是比较大的,比较难看,所以不推荐在Keras中使用TensorBoard查看网络结构。
【遇到的问题】
1-报错-数据格式不对,解决办法,对数据变形处理
2-损失过大,解决办法,优化方法为sgd