当前位置:   article > 正文

深度学习从入门到精通+TensorFlow案例演示:神经网络实践_深度学习tensorflow案例

深度学习tensorflow案例
接下来,我们将开始以神经网络实践各种应用,可以暂时
与数学 / 统计说再见,我们会着重于概念的澄清与程序的
撰写。笔者会尽可能地运用大量图解,帮助读者迅速掌握
各种算法的原理。
同时也会借由 手写阿拉伯数字辨识 的案例,实践机
器学习流程的十大步骤,并详细解说构建神经网络的函数
用法及各项参数代表的意义,最后我们会撰写一个完整的
窗口接口程序及网页程序,让终端用户( End User )亲身
体验 AI 应用程序,期望激发用户对企业导入 AI 有更多的体
验。

4-1 撰写第一个神经网络程序

手写阿拉伯数字辨识,如图 4.1 所示,问题定义如下。
1 )读取手写阿拉伯数字的影像,将影像中的每个像素当成一
个特征。数据源为 MNIST 机构所收集的 60000 个训练数据,另含
10000 个测试数据,每个数据是一个阿拉伯数字、宽高为
28, 28 )的位图形。
2 )建立神经网络模型,利用梯度下降法,求解模型的参数
值,一般称为权重。
3 )依照模型推算每一个影像是 0~9 的概率,再以最大概率者
为预测结果。
图4.1 手写阿拉伯数字辨识
图4.1 手写阿拉伯数字辨识

4-1-1 最简短的程序

TensorFlow 1.x 版使用会话( Session )及运算图
Computational Graph )的概念来编写,光是要将两个张量相
加就要撰写一大段程序,被 PyTorch 比了下去,于是
TensorFlow 2.x 为了回击对手,官网直接在文件首页展示了一个
超短程序,示范如何撰写手写阿拉伯数字的辨识,要证明改版
后的 TensorFlow 确实更好用,现在我们就来看看这支程序。
范例 . TensorFlow 官网的手写阿拉伯数字辨识。
程序: 04_01_ 手写阿拉伯数字辨识 .ipynb 。程序代码如下:
执行结果如下:
上述的程序除去批注,仅 10 多行,辨识的准确率高达
97%~98% TensorFlow 成功实现了超越!

4-1-2 程序强化

上一节的范例 手写阿拉伯数字辨识 是官网为了炫技刻意缩短
了程序,本节将会按照机器学习流程的十大步骤(见图 4.2 ),
撰写完整程序,并对每个步骤仔细解析,读者务必理解每一行
程序背后代表的内涵。
图4.2 机器学习流程十大步骤
图4.2 机器学习流程十大步骤
范例 . 依据上图十大步骤撰写手写阿拉伯数字辨识。
程序: 04_02_ 手写阿拉伯数字辨识 _ 完整版 .ipynb
1 )步骤 1 :加载 MNIST 手写阿拉伯数字数据集。程序代码如
下:
执行结果:取得 60000 个训练数据, 10000 个测试数据,每个数
据是一个阿拉伯数字,宽高各为( 28, 28 )的位图形,要注意数
据的维度及其大小必须与模型的输入规格契合。执行结果如
下:
2 )步骤 2 EDA ,对数据集进行探索与分析,首先观察训练
数据的目标值( y ),即影像的真实结果。程序代码如下:
执行结果如下,每个数据是一个阿拉伯数字。
3 )打印第一个训练数据的像素。程序代码如下:
执行结果如下,每个像素的值在( 0, 255 )之间,为灰阶影像,
0 为白色, 255 为最深的黑色。 注意:这与 RGB 色码刚好相反,
RGB 中黑色为 0 ,白色为 255        
4 )为了看清楚图片的手写的数字,将非 0 的数值转为 1 ,变为
黑白两色的图片。程序代码如下:
执行结果如下,笔者以笔描绘为 1 的范围,隐约可以看出是 5
5 )显示第一个训练数据图像,确认是 5 。程序代码如下:
执行结果如下:
6 )步骤 3 :进行特征工程,将特征缩放至( 0, 1 )区间,特征
缩放可提高模型准确度,并且可以加快收敛速度。特征缩放采
用正态化( Normalization )公式
x - 样本最小值) / (样本最大值 - 样本最小值)
执行结果如下:
7 )步骤 4 :数据分割为训练及测试数据,此步骤无须进行,
因为加载 MNIST 数据时,数据已经切割好了。
8 )步骤 5 :建立模型结构如图 4.3 所示。
图4.3 手写阿拉伯数字辨识的模型结构
图4.3 手写阿拉伯数字辨识的模型结构
Keras 提供两类模型,包括顺序型模型( Sequential Model )及
Functional API 模型。顺序型模型函数为
tf.keras.models.Sequential ,适用于简单的结构,神经层一层接一
层地顺序执行;使用 Functional API 可以设计较复杂的模型结
构,包括多个输入层或多个输出层,也允许分叉,后续用到时
再详细说明。这里使用简单的顺序型模型,内含各种神经层。
程序代码如下:
①扁平层( Flatten Layer ):将宽高各 28 像素的图压扁成一维数
组( 28×28=784 个特征)。
②完全连接层( Dense Layer ):输入为上一层的输出,输出为
128 个神经元,即构成 128 条回归线,每一条回归线有 784 个特
征。输出通常定为 4 的倍数,并无建议值,可经由实验调校取得
较佳的参数值。
Dropout Layer :类似于正则化( Regularization ),希望避免
过度拟合,在训练周期随机丢弃一定比例( 0.2 )的神经元,一
方面可以估计较少的参数,另一方面能够取得多个模型的均
值,避免受极端值影响,借以矫正过度拟合的现象。通常会在
每一层 Dense 后面加一个 Dropout ,比例也无建议值,如图 4.4
示。
图4.4 神经网络
图4.4 神经网络
a )标准神经网络;( b )丢弃一定比例的神经元后
④第二个完全连接层:为输出层,因为要辨识 0~9 这十个数字,
故输出要设成 10 ,透过 Softmax Activation Function ,可以将输出
转为概率形式,即预测 0~9 的个别概率,再从中选择最大概率者
为预测值。
9 )编译指令( model.compile )需设定参数,优化器为
Adam ,损失函数为 sparse_categorical_crossentropy (交叉熵),
而非 MSE ,相关参数后面章节会详细说明。程序代码如下:
10 )步骤 6 :结合训练数据及模型结构,进行模型训练。程序
代码如下:
validation_split :将训练数据切割一部分为验证数据,目前设
0.2 ,即验证数据占 20% ,在训练过程中,会用验证数据计算
准确度及损失函数值,确认训练过程有无异常。
epochs :设定训练要执行的周期数,所有训练数据经过一次
正向和反向传导,称为一个执行周期。
③执行结果如下,每一个执行周期都包含训练的损失、准确率
及验证数据的损失( val_loss )、准确率( val_accuracy ),这些
信息都会存储在 history 变量内,为一字典( dict )数据类型。
11 )对训练过程的准确率绘图。程序代码如下:
执行结果:随着执行周期次数的增加,准确率越来越高,且验
证数据与训练数据的准确率应趋于一致,若不一致或准确率过
低,就要检查每个环节是否出错,如图 4.5 所示。
图4.5 对训练过程绘图执行结果
图4.5 对训练过程绘图执行结果
12 )对训练过程的损失绘图。程序代码如下:
执行结果:随着执行周期次数的增加,损失越来越低,验证数
据与训练数据的损失应趋于一致,如图 4.6 所示。
图4.6 训练过程损失绘图执行结果
图4.6 训练过程损失绘图执行结果
13 )步骤 7 :评分( Score Model ),使用 evaluate() 函数,输入
测试数据,会计算出损失及准确率。程序代码如下:
执行结果: loss 0.0833 accuracy 0.9743
14 )实际比对测试数据的前 20 个,使用 predict_classes()
数,可以得到预测类别。程序代码如下:
执行结果如下,执行结果全部正确。
15 )显示第 9 个的概率:使用 predict() 函数,可以得到 0~9 预测
概率各自的值。
执行结果:发现 5 6 的概率很相近,表示模型并不很肯定。所
以,实际上,我们可以提高门槛,规定概率须超过规定的下
限,如 0.8 ,才算是辨识成功,以提高可信度,避免模棱两可的
预测。
9 张图像如下,像 5 又像 6
16 )步骤 8 :效果评估,暂不进行,之后可调校相关超参数
Hyperparameter )及模型结构,寻找最佳模型和参数。超参数
是指在模型训练前可以调整的参数,如学习率、执行周期、权
重初始值、训练批量等,但不含模型求算的参数如权重或偏
差。
17 )步骤 9 :模型部署,将最佳模型存盘,再开发用户接口或
提供 API ,连同模型文件一并部署到上线环境
Production Environment )。程序代码如下:
18 )步骤 10 :接收新数据预测,之前都是使用 MNIST 内建数
据测试,严格说并不可靠,因为这些都是出自同一机构所收集
的数据,因此,建议读者自己利用绘图软件亲自撰写测试。我
们准备一些图文件,放在 myDigits 目录内,读者可自行修改,
再利用下列程序代码测试,注意, 从图文件读入影像后要反转 颜色 ,颜色 0 为白色,与 RGB 色码不同, RGB 色码中 0 为黑色。
程序代码如下:
19 )使用下列指令显示模型汇总信息( summary )。程序代
码如下:
①执行结果:执行结果如下,包括每一神经层的名称及输出参
数的个数。
②计算参数个数:举例来说 dense_5 ,输出参数为 1290 ,意思是
共有 10 条回归线,每一条回归线都有 128 个特征对应的权重
w )与一个偏差项( b ),所以总共有 10× 128 +1 = 1290
参数。 20 )绘制图形,显示模型结构:要绘制图形显示模型结构,
需先完成以下步骤,才能顺利绘制图形。
①安装 graphviz 软件,网址为
https://www.graphviz.org/download ,再把安装目录下的 bin 路径
加到环境变量 Path 中。
②安装两个库: pip install graphviz pydotplus
③执行 plot_model 指令,可以同时显示图形和存盘。
执行结果:如图 4.7 所示。
图4.7 绘制图形显示模型结构
图4.7 绘制图形显示模型结构
以上我们按机器学习流程的十大步骤撰写了一支完整的程序,
虽然篇幅很长,读者应该还是有些疑问,许多针对细节的描
述,将于下一节登场,我们会做些实验来说明建构模型的考
虑,同时解答教学现场同学们常提出的问题。

4-1-3 实验

前一节我们完成了第一个深度学习的程序,也见识到了它的作
用,扣除说明,短短十几行的程序就能够辨识手写阿拉伯数
字,且准确率达到 97% 。然而,仔细思考后我们会产生许多疑
问。
1 )模型结构为什么要设计成两层 Dense ?更多层准确率会提
高吗?
2 )第一层 Dense 输出为什么要设为 128 ?设为其他值会有何影
响?
3 )目前第一层 Dense Activation Function 设为 relu ,代表什么
意义?设为其他值又会有何不同?
4 )优化器、损失函数、效果衡量指标有哪些选择?设为其他
值会有何影响?
5 Dropout 比例为 0.2 ,设为其他值会更好吗?
6 )影像为单色灰阶,若是彩色可以辨识吗?怎么修改?
7 )目前执行周期设为 5 ,设为其他值会更好吗?
8 )准确率可以达到 100% ,以便企业安心导入吗?
9 )如果要辨识其他对象,程序要修改哪些地方?
10 )如果要辨识多个数字,如输入 4 位数,要如何辨识?
11 )希望了解更详细的相关信息,有哪些资源可以参阅?
以上问题是这几年授课时学员常提出的疑惑,我们就来逐一实
验,试着寻找答案。
问题 1. 模型结构为什么要设计成两层 Dense ?更多层准确率会提
高吗?
解答:
条回归线可能还会包含在 Activation Function 内,变成非线性的
函数,因此,要单纯以数学方法求解几乎不可能,只能以优化
方法求得近似解,但是,只有凸集合的数据集,才保证有全局
最佳解( Global Minimization ),以 MNIST 为例,总共有 784
特征,即 784 度空间,根本无法知道它是否为凸集合,因此严格
来讲,到目前为止,神经网络依然是一个黑箱( Black Box )科
学,我们只知道它威力强大,但如何实现较佳的准确率,依旧
需要经验与实验,因此,模型结构并没有明确规定要设计成几
层,会随着不同的问题及数据来进行测试, case by case 进行效
果调校,寻找较佳的参数值。
2 )理论上,越多层架构,回归线就越多,预测应当越准确,
ResNet 模型就高达 150 层,但是,经过实验证实,超过某一界
限后,准确率可能会不升反降,这与训练数据量有关,如果只
有少量的数据,要估算过多的参数( w b ),自然准确率不
高。
3 )我们就来实验一下,多一层 Dense ,准确率是否会提高?
请参阅程序 04_03_ 手写阿拉伯数字辨识 _ 实验 1.ipynb
4 )修改模型结构如下,加一对 Dense/Dropout ,其余程序代码
不变。程序代码如下:
执行结果如下,准确率未见提升,反而微降。
loss 0.0840
accuracy 0.9733
问题 2. 第一层 Dense 输出为什么要设为 128 ?设为其他值会有何
影响?
解答:
1 )输出的神经元个数可以任意设定,一般来讲,会使用 4
倍数,以下我们修改为 256 ,请参阅程序 04_04_ 手写阿拉伯数字
辨识 _ 实验 2.ipynb 。程序代码如下:
执行结果如下,准确率略微提高,但不明显。
loss 0.0775
accuracy 0.9764
2 )同问题 1 ,照理来说,神经元个数越多,回归线就越多,
特征也越多,预测应该会越准确,但经过验证,准确率并未显
著提高。依 Deep Learning with TensorFlow 2.0 and Keras 一书测
试如图 4.8 所示,也是有一个极限,超过这个极限准确率就会不
升反降。
图4.8 准确率测试
图4.8 准确率测试
3 )神经元个数越多,训练时间就越长,如图 4.9 所示。
图4.9 训练时间
图4.9 训练时间
问题 3. 目前第一层 Dense Activation Function 设为 relu ,代表什
么意义?设为其他值会有何不同?
解答:
Activation Function 有很多种,后面会有详尽介绍,读者可先参
阅维基百科,部分表格撷取见表 4.1 。其中包括函数的名称、概
率分布图形、公式及一阶导数:
表4.1 部分Activation Function
表4.1 部分Activation Function
早期隐藏层大都使用 sigmoid 函数,近几年发现 relu 准确率较
高,因此我们先尝试比较这两种函数,请参阅程序 04_05_ 手写
阿拉伯数字辨识 _ 实验 3.ipynb
1 )将 relu 改为 sigmoid ,程序代码如下:
2 )执行结果如下, sigmoid 准确率确实略低于 relu
loss 0.0847
accuracy 0.9762
问题 4. 优化器、损失函数、效果衡量指标有哪些选择?设为其
他值会有何影响?
解答: 1 )优化器有很多种,从最简单的固定值的学习率( SGD ),
到很复杂的动态改变的学习率,甚至是能够自定义优化器。请
参考参考文献 [8] [9] 。优化器的选择,主要会影响收敛的速
度,大多数状况下, Adam 优化器都有不错的表现。
2 )损失函数也种类繁多,包括常见的 MSE Entropy ,其他
更多的损失函数请参考参考文献 [10] [11] 。损失函数的选择,
主要也是影响着收敛的速度,另外,某些自定义损失函数有特
殊功能,如风格转换( Style Transfer ),它能够制作影像合成的
效果,生成对抗网络( GAN ),后面章节会有详细的介绍。
3 )效果衡量指标:除了准确率,还可以计算精确率
Precision )、召回率( Recall )、 F1 等,也可以同时设定多个
效果衡量指标,请参考参考文献 [12] ,如下面程序代码所示,
完整程序可参阅程序 04_06_ 手写阿拉伯数字辨识 _ 实验
4.ipynb
①注意:设定多个效果衡量指标时,准确率请不要使用
Accuracy ,否则数值会非常低;而需使用 CategoricalAccuracy
表示分类的准确率,而非回归的准确率。
②执行结果如下:
loss 0.0757
categorical_accuracy 0.9781
precision_3 0.9810
recall_3 0.9751
问题 5. 目前 Dropout 比例为 0.2 ,设为其他值会更好吗?
解答:
Dropout 比例为 0.1 ,我们测试看看,请参阅程序 04_07_ 手写阿
拉伯数字辨识 _ 实验 5.ipynb 。部分代码如下:
执行结果如下,准确率略为提高。
loss 0.0816
accuracy 0.9755
可见抛弃比例过高时,准确率会陡降,如图 4.10 所示。
图4.10 准确率随抛弃比例变化
图4.10 准确率随抛弃比例变化
问题 6. 目前 MNIST 影像为单色灰阶,若是彩色可以辨识吗?怎
么修改?
解答:可以,若颜色有助于辨识,可以将 RGB 三通道分别输入
辨识,后面我们谈到卷积神经网络时会有范例说明。
问题 7. 目前执行周期设为 5 ,设为其他值会更好吗?
解答:执行周期改为 10 ,请参阅程序 04_08_ 手写阿拉伯数字辨
_ 实验 6.ipynb 。部分代码如下:
执行结果如下,准确率略为提高。
loss 0.0700 accuracy 0.9785
理论上,训练周期越多,准确率越高,但是,过多的训练周期
会导致过度拟合( Overfitting ),反而会使准确率降低,如图
4.11 所示。
图4.11 准确率随训练周期变化
图4.11 准确率随训练周期变化
问题 8. 准确率可以达到 100% ,以便企业安心导入吗?
解答:很少模型准确率能够达到 100% ,除非是用数学证明,然
而,神经网络只是近似解而已,另一方面,神经网络是从训练
数据中学习到知识,但是,测试或预测数据并不参与训练,若
与训练的数据分布有所差异,甚至来自于不同的概率分布,则
很难确保准确率能达到 100%
问题 9. 如果要辨识其他对象,程序要修改哪些地方?
解答:我们只需修改很少的程序代码,就可以辨识其他对象。
例如, MNSIT 另一个数据集 FashionMnist ,它包含女人身上的 10
种配件,请参阅 04_09_FashionMnist_ 实验 .ipynb ,除了加载数 据的指令不同之外,其他的程序代码几乎不变。这也说明了一
点, 神经网络并不是真的认识 0~9 或女人身上的 10 个配件,它只
是从像素数据中推估出的模型,即所谓的从数据中学习到知识
Knowledge Discovery from Data, KDD ,以 MNIST 而言,
模型只是统计 0~9 这十个数字,它们的像素大部分分布在那些位
置而已。
问题 10. 如果要辨识多个数字,如输入 4 位数,要如何辨识?
解答:可以使用图像处理分割数字,再分别依序输入模型预测
即可。还有更简单的方法,直接将视觉接口( UI )设计成 4 格,
规定使用者只能在每格子内各输入一个数字即可。
问题 11. 希望了解更详细的相关信息,有哪些资源可以参阅?
解答:可以参考 TensorFlow 官网或 Keras 官网,版本快速的更新
已经使网络上的信息新旧杂陈,官网才是最新信息的正确来
源。
以上的实验大多只对单一参数作做较,假如要同时比较多个变
量,就必须 跑遍 所有参数组合,这样程序会很复杂吗?读者
不必担心,有一些库可以帮忙,包括 Keras Tuner hyperopt
Ray Tune Ax 等,在后续超参数调校中会有较详细的介绍。
由于这个模型的辨识率很高,要观察超参数调整对模型的影
响,并不容易,建议找一些辨识率较低的模型进行相关实验,
例如 FashionMnist CiFar 数据集,才能有比较显著的效果,笔
者针对 FashionMnist 做了另一次实验,请参
04_09_FashionMnist_ 实验 .ipynb
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/779507
推荐阅读
相关标签
  

闽ICP备14008679号