【ATU Book-i.MX8系列 - TFLite】Tensorflow Keras 建立手写识别

一.   概述

上篇文章,说明如何搭建 Tensorflow Keras 环境以及 Keras 使用版本为 2.3.1 。此外,若各位想了解 TF 1.x 与 2.x 的差异,可以前往本系列的其他文章去认识 Tensorflow 1.x 与 2.x 的主要运作模式。本章节将快速带领初学者使用 Tensorflow 的高阶 API – Keras 来搭建手写辨识 ! 事不宜迟,动手一起体验吧!! 如下图所示,为系列博文之示意架构图。此架构图隶属于 i.MX8M Plus 的方案博文中,并属于 eIQ 机器学习开发环境 内的 推理引擎层(Inference Engines Layer) 的子系列 !! 目前章节介绍 “Tensorflow Keras 建立手写识别”!! 若欲架设 Tensorflow 1.x 或 2.x 的版本,请参照该系列其他的建立手写识别章节。

若新读者欲理解人工智能、机器学习以及深度学习的差异,可点选查阅下方博文
大大通精彩博文   探讨机器学习与深度学习之差异

 

 TFlite 系列博文 - 文章架构示意图 (1)


 

 

TFlite 系列博文 - 文章架构示意图 (2)

 

 

二.  Tensorflow Keras  建立手写识别

使用搭建环境 : Python 3.6 + Windows 10 + Tensorflow 2.1.0 + Keras 2.3.1

本节将介绍如何使用原生 TensorFlow 建立手写辨识之 CNN 卷积神经网路,并以拆分细节的方式来阐述。
若欲快速建立神经网路或是模组化的撰写程序,请参照 TensorFlow 的进阶 API : Keras、TFLearn、TF-Slim。

(1)  深度学习基础概念 :

在练习手写识别之卷积网路前,我们必须简单地了解一下深度学习的概念,以利于加深印象 !! 所谓的 深度学习(Deep Learning) 是隶属于人工智能与机器学习的一项新颖知识,随著运算能力大幅度提升而神经网路的概念受到重用,竟而提倡出“深度”的概念 !! 如下图所示,白话一点就是不断利用 卷积(Convolution) 的概念,提取出影像中细节 !! 透过一层一层的提取,也让资料量不断增加就如同深度一般 !!

 

深度学习概念示意图

这里将深度学习拆分成四大步骤,分别为 收集资料 、建立卷积神经网路架构、训练卷积神经网路架构、预测结果。建立神经网路的第一步,往往都是收集资料 ( database资料库) …而初学者不必须要花费心力去收集,仅需要善用网路上或官方提供的资源即可。有了资料后,就可以开始去搭建神经网路架构,对于架构的设计是需要有一定程度的知识理解,这里建议先学会使用为主,后续再来探讨深入细节 !! 在架设好之后,就可以进行神经网路的训练,这将透过所建立的网路架构与资料去学习图片中的手写数字。在训练之前必须先每张图片标记上分类 (官方已经标注),也就是常见的 label.txt 档案!! 利用这些分类定义告知机器什么是数字 1、数字2 … 而训练过后所记录下的分类规则 (权重) 就是所谓的 模组(model)。最后我们就可以使用模组来验证预测结果是否正确 !!

 

深度学习步骤示意图

 

 

深度学习四大步骤 :收集资料 、建立卷积神经网路架构、训练卷积神经网路架构、预测结果

 (2)  收集资料

 下载经典的手写辨识资料集 MNIST : 


 开启 Jupyter Notebook 撰写代码 : 

#---------------------------------------------------------------------------------------------------------------
# 载入函式库
#---------------------------------------------------------------------------------------------------------------
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, LeakyReLU, Conv2D
import numpy as np
#---------------------------------------------------------------------------------------------------------------
# 读取手写识别数据
#---------------------------------------------------------------------------------------------------------------
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 28,28,1).astype('float32') /255
x_test = x_test.reshape(10000, 28,28,1).astype('float32') /255
print('\nLoading MNIST DataBase\n',
'train number =',x_train.shape[0],"\n", 'test number =', x_test.shape[0],"\n",
'train image shape', x_train.shape,"\n",'label image shape', y_train.shape,"\n",
'train image size', x_train.shape[1]* x_train.shape[2],"\n")


下载完成手写辨识数据集
 MNIST : 

若显示以下资讯则代表,下载成功并显示资料集资讯

 


下载完成 MNIST 数据集之后,下一步须使用 热编码 的方式,将标签转成特定形式的编码结构以利于程式运算。

 热编码(One-Hot Encoding) : 

One-Hot 热编码是种非常有效的方式,以 N 个独立状态暂存器来进行编码。换句话说,假设标签特征有 [“男”, “女”, “混合”] 则编码后会以 [ 100, 010, 001] 来表示其资讯 !! 如同下图所表示,依序对应的实际标签为 5、0、4、1、9、2、1、3、1、4 。

 


 延续上一步,进行 独热编码(One-Hot Encoding) 代码 : 

#---------------------------------------------------------------------------------------------------------------
# 将标签转换为 独热编码(One-Hot Encoding)
#---------------------------------------------------------------------------------------------------------------
num_classes = 10
y_train_onehot = keras.utils.to_categorical(y_train, num_classes)
y_test_onehot = keras.utils.to_categorical(y_test, num_classes)​

 

 

(3) 建立卷积神经网路

建立卷积神经网路架构须一步步建立起输入层、卷积层、池化层、全部连接层、隐藏层、输出层才能构成神经网路架构,如同下图所示。而本篇文章只介绍经典的模型架构,细节的架设就不于此探讨,这里强调建立原生 Tenosrflow 1.x 技术,须先以 TensorFlow 静态图的概念,建置好架构后即可运作。

 

 

 延续上一步,建立 卷积神经网路架构(CNN) 代码 : 


Tensorflow Keras 函式使用方式 :
https://keras.io/zh/

#---------------------------------------------------------------------------------------------------------------
# 建立神经网路架构
#---------------------------------------------------------------------------------------------------------------
model = Sequential()
model.add(Conv2D(filters=16,kernel_size=(5,5),padding='same',input_shape=(28,28,1),activation='relu')) #卷积层 convolution layer 1
model.add(MaxPooling2D(pool_size=(2,2))) #池化层 Pool layer 1
model.add(Conv2D(filters=36,kernel_size=(5,5),padding='same',activation='relu')) #卷积层convolution layer 2
model.add(MaxPooling2D(pool_size=(2,2))) #池化层 Pool layer 2
model.add(Dropout(0.25))
model.add(Flatten())# 平坦层 flatten layer
model.add(Dense(128,activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(10,activation='softmax')) #输出层 output

 

 模组结构 (Model Struction) : 

Keras 提供了一种极为便利的函式可将所建构的模组架构呈现出来。如下图所示,为上述代码所建构的神经网路分别由卷积层、最大池化层、平坦层、全部连接层等等建构起来,并显示每一层的输出大小,可说对于初学者而言是相当友善的。

 

 

(4)  训练卷积神经网路

建立卷积神经网路架构后,即可利用训练数据来训练神经网路构成模型(Model)

延续上一步,建立 训练模型 代码 : 

#---------------------------------------------------------------------------------------------------------------
# 训练神经网路架构
#---------------------------------------------------------------------------------------------------------------
#最佳化设定 optimizer
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])

#开始训练模型 tranning model
batch_size = 100
epochs = 20
history = model.fit(x_train, y_train_onehot,batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_test, y_test_onehot))


 开始训练 (结果) : 

 

 

(5)  进行手写识别预测

训练完成模型后,即可使用测试数据预测结果是否恰当。

 延续上一步,建立 预测模型 代码 : 

#---------------------------------------------------------------------------------------------------------------
# 显示训练过程
#---------------------------------------------------------------------------------------------------------------
import matplotlib.pyplot as plt
def show_train_history(train_history, train, validation):
plt.plot(train_history.history[train])
plt.plot(train_history.history[validation])
plt.title('Train History')
plt.ylabel(train)
plt.xlabel('Epoch')
plt.legend(['train','validation'], loc='upper left')
plt.show()

show_train_history(history,'accuracy','val_accuracy')
show_train_history(history,'loss','val_loss')
#---------------------------------------------------------------------------------------------------------------
# 预测结果
#---------------------------------------------------------------------------------------------------------------
def plot_images_labels_prediction(images,labels,prediction,idx,num=10):
fig = plt.gcf()
fig.set_size_inches(12,14)
images_reshape = images.reshape(images.shape[0], 28,28)
if num>25: num = 25
for i in range(0,num):
ax = plt.subplot(5,5,i+1)
ax.imshow(images_reshape[idx],cmap='binary')
title = "label"+str(labels[idx])
if len(prediction)>0:
title+="predict="+str(prediction[idx])
ax.set_title(title,fontsize=10)
ax.set_xticks([])
ax.set_yticks([])
idx+=1
plt.show()
prediction = model.predict_classes(x_test)
plot_images_labels_prediction(x_test, y_test,prediction, idx=340)


 储存模组 : 

model.save('./tf2_keras_handwrite.h5')​


绘出损失曲线与准确度 (结果) : 

如下图所示,为每次训练过程的准确度与损失曲线的分析,可以发现随著训练次数提升,辨识的准确度会越来越高、错误率则会越来越低,到最后接近饱和,即表示完成训练。


预测结果 (结果) : 

观察图片上手写的数字与预测值(predict) 是否相同

 

 

 

三.  结语

相信各位已经成功的建立手写识别范例并看到预测结果,此实作结果与 Tensorflow 1.x  与 2.x 的结果没有什么太大差异,仅有实现方法不同 ( Keras 实现方式最为简洁、迅速) !! 此础范例在测试集所的准确度约 98% 左右 !! 预测结果是相当不错的 !! 若想深度研究仍须要思考测试与训练资料的样本、神经网路的架构、学习率、过拟合(Overfitting)、梯度消失等等机器学习会遇到的问题,而本篇系列暂不探讨此部分,后续文章将朝轻量化模组的部分前进,以 NXP i.MX8 平台带领读者实现 Tensorflow Lite 手写识别,体验轻量化网路运算速度 !! 敬请期待 !!

 

 

四.  参考文件

[1] ITREAD    - 从0.1到2.0一文看尽TensorFlow奋斗史
[2] 软体之心  - 包装再升级?Tensorflow 2.0的重大改变
[3] WiKi        -  Keras开源神经网路库
[4] 科技报橘 -  手机上的轻量版 AI 运算,TensorFlow Lite 问世!
[5] Anaconda - 官方网站
[6] Tensorflow – 官方网站
[7] 深智数位 – Tensorflow 1.x/2.x 完整工程实作
[8] 软体之心 - 包装再升级?Tensorflow 2.0的重大改变
[9] iT1邦帮忙 - Tensorflow 的 Eager Mode
[10] 软体之心 - Keras 手写辨识 MNIST

如有任何相关 Tensorflow Lite 技术问题,欢迎至博文底下留言提问 !!
接下来还会分享更多 Tensorflow Lite 的技术文章 !!敬请期待 【ATU Book-i.MX8 系列 - TFLite
 !!

 

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论