这里会介绍如何训练图像领域应用非常广的卷积神经网络 (Convolutional Neural Network)这一部分应当不会涉及到很多理论了,其实用 Keras 训练模型写起代码来非常简单,如果发现不太清楚代码为什么要这么写,可以看看上一部分对应的算子。
2.1 MNIST 手写体训练集
这个图上就是全球各地大家用不同方法做手写体识别得到的准确率汇总,可以看到我用红圈画出来的部分,用前面介绍的 Logistic Regression (Linear Classifier) 做手写体识别效果是最差的,所以我们之后要使用的是卷积神经网络 CNN (之后我就都用 CNN 简写了)。
在网站的下面给出了训练集的二进制格式定义:
2.2 开发环境搭建
首先介绍一下机器学习的开发环境,现在主流开发环境都是 Python,但是我们也不是一个裸 Python 打开记事本就直接开始写代码了,实际上数据科学家用的最多的开发环境是 Anaconda,里面集成了 Python 和 R 开发环境。
Anaconda 其实是有图形界面的,叫 Anaconda Navigator,但是这里以控制台为主,因为图形界面其实用起来反而比较麻烦,因为控制台一行命令就解决了更加快速方便。
1# 如果你是用的 CPU
2conda create -n tensorflow-cpu tensorflow
3
4# 如果你是用的 GPU (NVIDIA 显卡会自动安装显卡驱动,CUDA,cudnn,简直方便)
5conda create -n tensorflow-gpu tensorflow-gpu
这样开发环境就搭好了,我们激活一下当前的开发环境:
1# 如果你是用的 CPU
2conda activate tensorflow-cpu
3
4# 如果你是用的 GPU
5conda activate tensorflow-gpu
这里 激活 开发环境是指,在 Anaconda 下我们可以有多个开发环境,比如如果你想对比一下 CPU 和 GPU 计算速度的差距,可以同时安装 2 个开发环境,然后根据需要切换到 CPU 开发环境,或者 GPU 开发环境,非常方便。如果不用 Anaconda 而是一个 Python 裸奔的话,要么使用 VirtualEnv,要么就只能反复安装卸载不同的开发环境了。
1# 这里的软件包 anaconda 可能已经都装好了,以防万一再确认一遍
2pip install numpy scipy sklearn pandas pillow matplotlib keras onnx jupyter -i https://pypi.tuna.tsinghua.edu.cn/simple
3
4# 启动编辑器
5jupyter notebook
这样就会自动打开浏览器,看到我们的开发环境了,在这里新建一个 notebook:
接下来就可以开始训练模型了。
2.3 Keras 训练模型
2.3.1 导入库函数
1#coding:utf-8
2from tensorflow.examples.tutorials.mnist import input_data
3
4import numpy as np
5np.set_printoptions(suppress=True)
6
7import matplotlib.pyplot as plt
8%matplotlib inline
如果你对上面 导入库 这一个注释比较感兴趣,可以在一个把光标移到到一个输入框,按下 Esc 再按下 m,这个输入框就从 代码段 变成 注释段 了,Anaconda 也是代码、注释、输出可以同时保存所以用起来体验非常好。更多的快捷键可以在菜单栏的 Help --> Keyboard Shortcuts 找到。
2.3.2 下载 MNIST 训练集
1mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #MNIST数据输入
这样就会自动下载数据集了,国内可能下载速度比较慢,可以从这个地址下载MNIST数据集 然后解压到 Anaconda Prompt 启动 Jupyter Notebook 的位置就不用等它慢慢下载了,默认是 C:/Users/你的用户名/
2.3.3 看一看 MNIST 数据
1X_train = mnist.train.images
2y_train = mnist.train.labels
3X_test = mnist.test.images
4y_test = mnist.test.labels
5
6# 输入图像大小是 28x28 大小
7X_train = X_train.reshape([-1, 28, 28, 1])
8X_test = X_test.reshape([-1, 28, 28, 1])
如果比较好奇这是一个怎样的图片,可以看看它长什么样子,比如我们看看训练集的第一张图片
1plt.imshow(X_train[0].reshape((28, 28)), cmap='gray')
1plt.imshow(X_train[1].reshape((28, 28)), cmap='gray')
下面就正式开始建立训练模型了。
2.3.4 构建模型
1# Importing the Keras libraries and packages
2# Importing the Keras libraries and packages
3from keras.models import Sequential
4from keras.layers import Dense
5from keras.layers import Conv2D
6from keras.layers import MaxPooling2D
7from keras.layers import Dropout
8from keras.layers import Flatten
接下来就可以建模了,可以看到这里的模型和上一部分介绍的 CNN 算子是一模一样的,熟悉的 conv2d, maxpooling, dropout, flatten, dense, softmax, adam, 如果忘了它们是什么意思,随时可以切换到上一个部分回忆一下。
1def build_classifier():
2
3 classifier = Sequential()
4
5 # 第一层 Conv2D,激活函数 Relu
6 classifier.add(Conv2D(filters = 2, kernel_size = 3, strides = 1, padding = "SAME", activation = "relu", input_shape = (28, 28, 1)))
7
8 # 第二层 Maxpooling, 使用保持图像大小的 padding
9 classifier.add(MaxPooling2D(pool_size=(2, 2), padding='SAME'))
10
11 # 第三层 Dropout
12 classifier.add(Dropout(0.5))
13
14 # 第四层 Conv2D,激活函数 Relu
15 classifier.add(Conv2D(filters = 2, kernel_size = 3, strides = 1, padding = "SAME", activation = "relu"))
16
17 # 第五层 Maxpoling,使用保持图像大小的 padding
18 classifier.add(MaxPooling2D(pool_size=(2, 2), padding='SAME'))
19
20 # 第六层 Dropout
21 classifier.add(Dropout(0.5))
22
23 # 第七层 Flatten
24 classifier.add(Flatten())
25
26 # 第八层 Dense
27 classifier.add(Dense(kernel_initializer="uniform", units = 4))
28
29 # 第九层 softmax 输出
30 classifier.add(Dense(kernel_initializer="uniform", units = 10, activation="softmax"))
31
32 # 使用 adam 训练
33 classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics=['accuracy'])
34
35 return classifier
代码真的就是一层只要一行,但是一定要知道自己的模型为什么要这么建,比如为什么 maxpooling 要放在 con2d 之后,为什么要加 dropout,最后的 softmax 到底是在干什么,可不可以不要?
我们可以看看自己建立的模型长什么样:
1classifier = build_classifier()
2classifier.summary()
2.3.5 训练模型
接下来我们就可以开始训练模型了:
1from keras.callbacks import ModelCheckpoint
2checkpointer = ModelCheckpoint(filepath='minions.hdf5', verbose=1, save_best_only=True, monitor='val_loss',mode='min')
3
4history = classifier.fit(X_train, y_train, epochs = 50, batch_size = 50, validation_data=(X_test, y_test), callbacks=[checkpointer])
1def plot_history(history) :
2 SMALL_SIZE = 20
3 MEDIUM_SIZE = 22
4 BIGGER_SIZE = 24
5
6 plt.rc('font', size=SMALL_SIZE) # controls default text sizes
7 plt.rc('axes', titlesize=SMALL_SIZE) # fontsize of the axes title
8 plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
9 plt.rc('xtick', labelsize=SMALL_SIZE) # fontsize of the tick labels
10 plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels
11 plt.rc('legend', fontsize=SMALL_SIZE) # legend fontsize
12 plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title
13
14 fig = plt.figure()
15 fig.set_size_inches(15,10)
16 plt.plot(history['loss'])
17 plt.plot(history['val_loss'])
18 plt.title('Model Loss')
19 plt.xlabel('epoch')
20 plt.ylabel('loss')
21 plt.legend(['train', 'test'],loc='upper left')
22 plt.show()
用图片显示一下训练过程:
1plot_history(history.history)
2.4 保存模型为 onnx
我们可以把模型保存为原生的 Keras 模型:
1classifier.save("mnist.h5")
1import onnx
2import keras2onnx
3
4onnx_model = keras2onnx.convert_keras(classifier, 'mnist')
5onnx.save_model(onnx_model, 'mnist.onnx')
这样在 Anaconda Prompt 默认目录下 C:/Users/你的用户名 可以看到 mnist.h5 和 mnist.onnx 两个文件,这就是训练好的模型。
这样我们模型也训练好了,也保存好了,下一步就是怎么使用训练好的模型了。
(大家可以试试把 Dropout 的概率从 0.5 改为 0.3,训练集准确度就会从 60% 提升到 80%,测试集则有 90% 以上,为什么呢??)
2.5 参考文献(以下链接请复制至外部浏览器打开)
MNIST 训练集:
http://yann.lecun.com/exdb/mnist/
Anaconda GPU 环境:
https://www.anaconda.com/tensorflow-in-anaconda/
END
RT-Thread线上活动
1、【RT-Thread能力认证考试12月——RCEA】经过第一次考试的验证,
能力认证官网链接:https://www.rt-thread.org/page/rac.html(在外部浏览器打开)
立即报名
#题外话# 喜欢RT-Thread不要忘了在GitHub上留下你的STAR哦,你的star对我们来说非常重要!链接地址:https://github.com/RT-Thread/rt-thread
你可以添加微信18917005679为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群
RT-Thread
长按二维码,关注我们
点击阅读原文进入Github