![神经网络设计与实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/765/38894765/b_38894765.jpg)
2.4 从头开始使用Python编写FFNN
为了创建我们的网络,我们将创建一个类,它与第1章为感知器创建的类相似。与面向对象编程(OOP)所规定的相反,我们不会利用先前创建的感知器类,而使用更为方便的权重矩阵。
我们的目标是使用代码展示如何实现我们刚刚说的理论。因此,解决方案将非常适合于我们的用例。我们知道网络将分为三层,输入大小将为2,并且知道隐藏层中神经元的数量:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/040-2-i.jpg?sign=1739612203-7kpWB5PpTXZuTkPpsyeDVGT4jmpPzEsC-0-8991f7ee564810731c1ee7ab5a298910)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-i.jpg?sign=1739612203-9Cq7uHEPO9e8zxMQGgC4gHtkvMgjJKLW-0-ba17048f652459dcb590c2da2fe8e8a0)
由于我们决定使用sigmoid作为激活函数,这里可以将其添加为外部函数。同样,我们知道需要计算导数,因为我们正在使用SGD。因此,我们将其实现为另一种方法。通过使用上述公式,实现变得非常简单:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-2-i.jpg?sign=1739612203-ndZR8FcYOhWxI7YbROpjEvmhGkR3BNbP-0-bbcb119935e4178d4265b75076ff7dab)
然后,我们用一个函数来计算前向传递,而另一个函数用于反向传递。我们将使用输入和权重之间的点积来计算输出,然后将所有内容通过sigmoid传递:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-3-i.jpg?sign=1739612203-htVD7A4kzZKe5TuZPsLbA2baLZs1hNXP-0-118cfbbf0d70984f9d1b407361a59c8c)
前向传播也是我们将用于预测的内容,但是我们将创建别名,因为在此任务中最常用的名称是predict:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-4-i.jpg?sign=1739612203-0ibyx2RXBwKXCeN9j3mNNgUKCpcZ8VgT-0-5119016348e962d27a0e97850d42a72d)
反向传播中最重要的概念是误差的反向传播,从而调整权重并减少误差。我们在backward方法中实现此函数。为此,我们从输出开始,计算预测值与实际输出之间的误差。这将用于计算在更新权重时使用的delta。在所有层中,我们将神经元的输出用作输入,将其通过sigmoid的导数,然后乘以误差和步长(也称为学习率):
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-5-i.jpg?sign=1739612203-qMnFFETgJVw9zli1R85htBm13impMsgA-0-a9c4de869aecdadf4ffc4b0452721503)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-i.jpg?sign=1739612203-NPE2M4KXqbZ4iE1mvUH1CSpXbcTSNQru-0-301436868cc1cf40dc69ea97a61319be)
在就每个数据点训练模型时,我们将进行两次传递,前向一次,反向一次。因此,我们的fit方法将如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-2-i.jpg?sign=1739612203-O7D1seCQ10ejdU0snUPozzXu1z7d6GUp-0-258104a3ab45ec08eb4073f0a3754185)
现在,神经网络已经准备就绪,可以用于我们的任务了。我们还需要一个训练集和一个测试集:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-3-i.jpg?sign=1739612203-67yZmtdzQrnWRWyujVdKwBmatfzVuOqA-0-82cbfb29655a7c7f1419ec37ce61cc5a)
现在可以如下训练网络:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-4-i.jpg?sign=1739612203-UzGIvGYXSigoCWfJ4XtKbOMY75iq3KCz-0-60a54008dcca7db0529fa5a771f17bc5)
我们将验证算法的性能,如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-5-i.jpg?sign=1739612203-EsleppHRiU7nOKLRzed1cAksyxoqCtOJ-0-f39feb0427190e8ed11f43ae9cfcdad0)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-i.jpg?sign=1739612203-oPdwrP5GKGQAK2CRPvZFRtVh44Kvis58-0-c517a3fd9e396e113c2abb7be5015e78)
1 000个epoch后的MSE小于0.01,这是一个相当不错的结果。我们通过使用ROC曲线下面积(Area Under the Curve,AUC)来衡量性能,该指标衡量了预测情况的好坏。如果AUC超过0.99,我们相信会有极少的错误,但是该模型仍然运行良好。
也可以使用混淆矩阵来验证性能。这种情况下,我们必须设定阈值以区分预测一个标签或另一个标签。由于结果之间有很大的差距,因此将阈值设为0.5可能比较合适:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-2-i.jpg?sign=1739612203-XEBMDKbTH2wyAnFdwl95QTIxKn79sTQn-0-0912ba9cab5403dbad503a10257e2aba)
我们会得到一个不错的结果,可通过下列的混淆矩阵进行检测。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-3-i.jpg?sign=1739612203-DjJroO7A5fhOKBJgs4QryEUoCJu6ynJU-0-7d9b9b91fe127db6811979c32eda7c53)
通过可视化聚类结果,我们可以清楚地知道误差在哪里,如图2-16所示。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/2-16.jpg?sign=1739612203-GRSfbzdWUtrCGLbR2GIJ0zFer8571SSk-0-e80071ad4eed55e0ff774abf53dc22ee)
图 2-16