RT-Thread智能车目标识别系统连载教程——训练卷积神经网络模型(2)

上期回顾:

这里会介绍如何训练图像领域应用非常广的卷积神经网络 (Convolutional Neural Network)这一部分应当不会涉及到很多理论了,其实用 Keras 训练模型写起代码来非常简单,如果发现不太清楚代码为什么要这么写,可以看看上一部分对应的算子。


2.1 MNIST 手写体训练集

首先我们需要介绍一下训练集,毕竟在训练之前我们得先看看训练集长什么样子。
这就是手写体识别数据库的官网了:http://yann.lecun.com/exdb/mnist/,风格比较跨世纪:

640?wx_fmt=png

这个图上就是全球各地大家用不同方法做手写体识别得到的准确率汇总,可以看到我用红圈画出来的部分,用前面介绍的 Logistic Regression (Linear Classifier) 做手写体识别效果是最差的,所以我们之后要使用的是卷积神经网络 CNN (之后我就都用 CNN 简写了)。

在网站的下面给出了训练集的二进制格式定义:

640?wx_fmt=png

当然,这是指自己从网站下载原始训练集,从当中提取图片才需要了解的,我们使用 tensorflow 不需要自己解析数据集。

2.2 开发环境搭建


首先介绍一下机器学习的开发环境,现在主流开发环境都是 Python,但是我们也不是一个裸 Python 打开记事本就直接开始写代码了,实际上数据科学家用的最多的开发环境是 Anaconda,里面集成了 Python 和 R 开发环境。

我们从官网下载 Anaconda 安装包 https://www.anaconda.com/distribution/ 根据自己的操作系统选择就可以了,因为安装过程基本就是单纯地下一步、下一步,所以这里就不介绍了。
安装好之后,我们打开 Anaconda Prompt:

Anaconda 其实是有图形界面的,叫 Anaconda Navigator,但是这里以控制台为主,因为图形界面其实用起来反而比较麻烦,因为控制台一行命令就解决了更加快速方便。

640?wx_fmt=png

然后我们输入:
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:

640?wx_fmt=png

可以把它重命名为 mnist-keras:

640?wx_fmt=png

接下来就可以开始训练模型了。

2.3 Keras 训练模型

2.3.1 导入库函数
我们首先导入需要的库函数,在 In[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
这些代码写进去之后就是这个样子,后面我就不一一截图了。

640?wx_fmt=png

如果你对上面 导入库 这一个注释比较感兴趣,可以在一个把光标移到到一个输入框,按下 Esc 再按下 m,这个输入框就从 代码段 变成 注释段 了,Anaconda 也是代码、注释、输出可以同时保存所以用起来体验非常好。更多的快捷键可以在菜单栏的 Help --> Keyboard Shortcuts 找到。

把光标移动到刚刚输入的代码块,按下键盘的 Shift + Enter 就自动执行了,并且会自动在下面增加一行代码输入框,导入库根据电脑的配置可能需要一些时间,耐心等待一下。
2.3.2 下载 MNIST 训练集
在代码块输入一行代码:
1mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #MNIST数据输入

这样就会自动下载数据集了,国内可能下载速度比较慢,可以从这个地址下载MNIST数据集 然后解压到 Anaconda Prompt 启动 Jupyter Notebook 的位置就不用等它慢慢下载了,默认是 C:/Users/你的用户名/

640?wx_fmt=png

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')

640?wx_fmt=png

也可以看看第二张图片:
1plt.imshow(X_train[1].reshape((28, 28)), cmap='gray')

640?wx_fmt=png

下面就正式开始建立训练模型了。

2.3.4 构建模型
同样先导入一下 Keras 库:
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()

640?wx_fmt=png

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])
这个模型非常小,不过我用 CPU 训练才迭代 50 步,也差不多花了 10 分钟,所以能用 GPU 我们是坚决不用 CPU 的。
我们可以看看刚刚的训练过程:
 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)

640?wx_fmt=png

可以看到,模型在训练集和测试集的 cost function 计算出来的 loss 都在减小,很神奇的是模型在测试集上的表现竟然比训练集还要好,不过模型精度不算太高才 60% 多一点的准确率,大家可以试着优化一下,在尝试改进模型的过程中,就会加深对模型的理解,如果我在这里直接就给出一个表现非常好的模型,可能对大家帮助反而不是那么大。

2.4 保存模型为 onnx

我们可以把模型保存为原生的 Keras 模型:

1classifier.save("mnist.h5")
当然,为了在 stm32 上面加载,我们更想保存为通用机器学习模型 onnx 的格式:
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(在外部浏览器打开)

640?wx_fmt=png

立即报名

#题外话# 喜欢RT-Thread不要忘了在GitHub上留下你的640?wx_fmt=pngSTAR640?wx_fmt=png哦,你的star对我们来说非常重要!链接地址:https://github.com/RT-Thread/rt-thread

你可以添加微信18917005679为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群

640?wx_fmt=jpeg

RT-Thread

长按二维码,关注我们

640?wx_fmt=png
看这里,求赞!求转发!
640?wx_fmt=gif

640?wx_fmt=gif点击阅读原文进入Github

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值