一. 概述
上篇文章,说明如何搭建 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】 !!
评论