![PyTorch深度学习应用实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/410/52842410/b_52842410.jpg)
3-4 神经网络层
上一节运用自动微分实现一条简单线性回归线的求解,然而神经网络是多条回归线的组合,并且每一条回归线可能需再乘上非线性的Activation Function,假如使用自动微分函数逐一定义每条公式,层层串连,程序可能需要很多个循环才能完成。所以为了简化程序开发的复杂度,PyTorch直接建构了各种各样的神经层(Layer)函数,可以使用神经层组合神经网络的结构,我们只需要专注在算法的设计即可,轻松不少。
神经网络是多个神经层组合而成的,如下图,包括输入层(Input Layer)、隐藏层(Hidden Layer)及输出层(Output Layer),其中隐藏层可以有任意多层,广义来说,隐藏层大于或等于两层,即称为深度(Deep)学习。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P51_3390.jpg?sign=1739273368-OkL1zIr5NgfTp1MgDTmwrSqm9zqsxZVk-0-725d19b7477ce6a05f7dd61aebddb7f7)
图3.11 神经网络示意图
PyTorch提供十多类神经层,每一类别又有很多种神经层,都定义在torch.nn命名空间下,可参阅官网说明[2]。
首先介绍完全神经层(Linear Layers),参阅图3.11,即上一层神经层的每一个神经元(图中的圆圈)都连接到下一层神经层的每一个神经元,所以也称为完全连接层,又分为Linear、Bilinear、LazyLinear等,可参阅维基百科[3],接下来开始实操完全连接层。
范例1.进行试验,熟悉完全连接层的基本用法。
下列程序代码请参考【03_04_完全连接层.ipynb】。
(1)载入套件。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P51_3398.jpg?sign=1739273368-HPsoDtJNJpo49dzurTim0bMVQdEEgwJg-0-3513d651b3dd9c00fa6bcb754f846c85)
(2)产生随机随机数的输入数据,输出二维数据。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P51_3405.jpg?sign=1739273368-SufUKODr3utNyNcSbQY9EtxJvSxK3udr-0-bb2e6834f1e730cbf0682f2befca5c41)
(3)建立神经层,Linear参数依次为:
输入神经元个数。
输出神经元个数。
是否产生偏差项(bias)。
设备:None、CPU(‘cpu’)或GPU(‘cuda’)。
数据类型。
Linear神经层的转换为y=xAT+b,y为输出,x为输入。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3430.jpg?sign=1739273368-Yzi0t1bKkpkcWZQrzZlBgAF5tVLl187D-0-ad8eb039aab2693bc225f2a7a139896c)
(4)神经层计算:未训练Linear就是执行矩阵内积,维度(128, 20) @ (20, 30)=(128, 30)。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3437.jpg?sign=1739273368-y9dhy9tedhDLBxs9rPmxHfr2lWpZUf7k-0-942e5c4303aefcac0b1103b39d2f1aac)
执行结果:torch.Size([128, 30])。
再测试Bilinear神经层,Bilinear有两个输入神经元个数,转换为
(1)建立神经层。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3445.jpg?sign=1739273368-g9CBEWjhCbHsp8DbU5cvfhrU5wDO7eDB-0-eb8be5c5d72d9f643b1673d6fdcf10db)
(2)Bilinear神经层计算:未训练Linear就是执行矩阵内积,维度(128, 20) @ (20,40)+(128, 30) @ (20, 40)=(128, 40)。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3452.jpg?sign=1739273368-7bjQC79NNRQLqrW71IsT94IlGtCIMZc3-0-3793dab1f411061eac558fb699428eaa)
执行结果:torch.Size([128, 40])。
范例2.引进完全连接层,估算简单线性回归的参数w、b。
下列程序代码请参考【03_05_简单线性回归_神经层.ipynb】。
(1)载入套件。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3459.jpg?sign=1739273368-mCnuftHJFu4pEo1RhZvhE3kPziz44jGi-0-20d29761d921f4cb12486aabae1fde4f)
(2)产生随机数据,与上一节范例相同。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3466.jpg?sign=1739273368-K9pTkCr5c5GOUGY2ZG5W2jm4XfKgGmU2-0-c8b95cd79411ba9a343f0af2dd18c7e0)
(3)定义模型函数:导入神经网络模型,简单的顺序型模型内含Linear神经层及扁平层(Flatten),扁平层参数设定哪些维度要转成一维,设定范围参数为(0, -1)可将所有维度转成一维。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P52_3473.jpg?sign=1739273368-q92wXjgQJWmwFhf0wIKQZjZwiJmG1cUw-0-aac981ea8665230e13969aedf2642d15)
测试扁平层如下,Flatten()预设范围参数为(1, -1),故结果为二维,通常第一维为笔数,第二维为分类的预测答案。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P53_3493.jpg?sign=1739273368-1FaLpqAcWQA35SpXeTCNJXQmVKdKqm9w-0-d39f3e997c0d8a212d9b7395328f2cb2)
执行结果:torch.Size([32, 288])。
(4)定义训练函数。
定义模型:神经网络仅使用一层完全连接层,而且输入只有一个神经元,即x,输出也只有一个神经元,即y。偏差项(bias)默认值为True,除了一个神经元输出外,还会有一个偏差项,设定其实就等于y=wx+b。
定义损失函数:直接使用MSELoss函数取代MSE公式。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P53_3500.jpg?sign=1739273368-I75KgHObw8tHnEZmlUw3mmpD25rcp1Pq-0-98edafa8350020a69367fbdaa071b8d3)
(5)使用循环,反复进行正向/反向传导的训练。
计算MSE:改为loss_fn(y_pred, y)。
梯度重置:改由model.zero_grad()取代w、b逐一设定。
权重更新:改用model.parameters取代w、b逐一更新。
model[0].weight、model[0].bias可取得权重、偏差项。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P53_3507.jpg?sign=1739273368-O8dHQlChHpuvDpepXBUqhl6bkzR8eoi2-0-ef393fb37db909a7589c3590aa09b8ed)
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P53_3512.jpg?sign=1739273368-mDMpde3RAtMykOyOVfTvpDqsgMRiqhqt-0-eedb2462bd6c9bb51fd3e47375569a96)
(6)执行训练。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P53_3519.jpg?sign=1739273368-IQH1hVc6r1NP1G1J9g9hrlQPbhGrOk6N-0-a8c8c0367a83182c9c27a09a79680d87)
执行结果:w=0.847481906414032, b=3.2166433334350586。
(7)以NumPy验证。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3539.jpg?sign=1739273368-iHpO4Pt7vUDJq2euqWa71rSy37sJg40x-0-f3e65b39394b36a202b4587bbde99c72)
执行结果与答案非常相近。
w=0.8510051491073364, b=4.517198474698629。
(8)显示回归线。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3546.jpg?sign=1739273368-9mR3pBpVE5DXRZTGJNxKmH4BSYx4WMQ6-0-a892c49afcd0e289ccda7db31b0806a8)
执行结果。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3553.jpg?sign=1739273368-NmWIsX0BGXFirMgX8QMQgaebRo251PVc-0-64309c3b61d9af09d0f6b170ab586736)
(9)NumPy模型绘图验证。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3556.jpg?sign=1739273368-IGzmOZbKW2jZtB03wKIC0v6wNUaBly8c-0-361d9fbf3e94014e33bf3a7ccaed3ecb)
执行结果非常相近。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3563.jpg?sign=1739273368-fBIzc0gysvYQAKw7iXyS9kzeEEfrwAIx-0-0ce570451e7246c25e527b04ccbbc052)
(10)损失函数绘图。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P54_3566.jpg?sign=1739273368-jL3DThNvA3ImaMUJpZi2L26XwfMVVb2J-0-01f54adb7bd87a3538ff9d17f9a7b47e)
执行结果:在第25个执行周期左右就已经收敛。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P55_3586.jpg?sign=1739273368-AuveDqCemHneyJ8zuQxPQefG5H5Z5Sqj-0-74bfa93d61f19a3ded586610787092b4)
范例3.接着我们再进一步,引进优化器(Optimizer),操控学习率,参阅图3.9。
这里仅列出与范例2的差异,完整程序请参见程序【03_06_简单线性回归_神经层_优化器.ipynb】。
(1)定义训练函数。
定义优化器:之前为固定的学习率,改用Adam优化器,会采取动态衰减(Decay)的学习率,参见第8行。PyTorch提供多种优化器,第4章会详细说明。
梯度重置:改由优化器(Optimizer)控制,optimizer.zero_grad()取代model.zero_grad(),参见第19行。
权重更新:改用optimizer.step()取代,w、b逐一更新,参见第25行。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P55_3589.jpg?sign=1739273368-Zaqn2jj1lE2Yq3r1XvY74yaT4fvilSFC-0-00164a6d2c26e384123bd487a8cc0122)
(2)训练结果与范例2相同,注意,若出现w或b=nan,损失等于无穷大(inf),表示梯度下降可能错过最小值,继续往下寻找,碰到这种情况,可调低学习率。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3609.jpg?sign=1739273368-nszEWSxXgyGmkAEmqSCrro3Cp9ZD94Qu-0-bcd30a1032bac83bd8768ed4abb315d7)
范例4.除了回归之外,也可以处理分类(Classification)的问题,数据集采用Scikit-Learn套件内建的鸢尾花(Iris)。
下列程序代码请参考【03_07_IRIS分类.ipynb】。
(1)载入套件。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3612.jpg?sign=1739273368-fxGB573DFfZA9Nt5noyDxVpkUi7VabNj-0-c915ddffa773005229a2f0deca660e00)
(2)载入IRIS数据集:有花萼长/宽、花瓣长/宽共4个特征。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3619.jpg?sign=1739273368-IxVfwuPjorMmq4RbVuA0uSdDumYeoBa9-0-9bbfffa4df2e6aecf44126123dba44b3)
执行结果。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3626.jpg?sign=1739273368-cMpvKzVmE1ZUyznKw1jwhlcaVMd7Gqhs-0-eaafcce5eb680a4c567c783ca02b3a11)
(3)数据分割成训练及测试数据,测试数据占20%。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3633.jpg?sign=1739273368-xjN9oLO9WxSP6BbkdRVU2RRTZK5bYKlR-0-50cb3dbc258997264c405e7efbb54eca)
(4)进行one-hot encoding转换:y变成3个变量,代表3个品种的概率。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3640.jpg?sign=1739273368-Ya7ANzMP4HgnqlpboSUN4T1CJbQd5pfB-0-9fae5e6637a39af170a6aaf211fcb734)
也可以使用PyTorch函数。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P56_3647.jpg?sign=1739273368-Z99Mgr3K7MBFX9MgninZo7P5gl2lf8e3-0-80cc7797636a0d286811a96be026a4a0)
(5)转成PyTorch Tensor。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P57_3667.jpg?sign=1739273368-LGSXyWSwkfaYNOPqvCxIxAyih8nuM0oF-0-dd2f2e2ab4a8b849c0d30aa70f0f2a45)
(6)建立神经网络模型。
Linear(4, 3):4个输入特征;3个品种预测值。
Softmax激励函数会将预测值转为概率形式。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P57_3674.jpg?sign=1739273368-5PBjboVB8sbCNJlpqABgm2D4x7b6jwRh-0-bfec8d034d0c7bf0e3d27de3341c700d)
(7)定义损失函数、优化器:与之前相同。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P57_3681.jpg?sign=1739273368-lLSIJJ8pzdLEK4X0bWjN3hLoNfpXWjWu-0-ffb386b0c2de8f6374ca1af9ccca133a)
(8)训练模型:第9~10行比较实际值与预测值相等的笔数,并转为百分比。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P57_3688.jpg?sign=1739273368-66XilRyEIsYpMwNcNjDHAFZnjXO5GX7b-0-e309393191f7ddc8bdf1788a50c7a84b)
(9)绘制训练过程的损失及准确率趋势图。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P57_3695.jpg?sign=1739273368-WPvaheEzTrVBcPOX41aDYuuKA10deR8z-0-5a219aca4fcbc93046f7edf3cd49c998)
执行结果:在第400个执行周期左右就已经收敛。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P58_3715.jpg?sign=1739273368-lAwpL8e855bNZGbcbXFp8qtebaGxTqH3-0-9f06df32280eaf6f0af32da643b1969d)
(10)模型评估:评估测试数据的准确度。
![](https://epubservercos.yuewen.com/128DEE/31397898903670606/epubprivate/OEBPS/Images/Figure-P58_3718.jpg?sign=1739273368-ERCtVLre50yb6aM1AOhGXJC6DSSKHnbl-0-29c63dd07312d69e93ab22d09c593588)
执行结果:准确率100%,不过,数据分割是随机抽样,每次结果均不相同。