![神经网络设计与实现](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=1739288688-nXAjCh4N0kow3BCpAXCFHxTt1BPIY8SH-0-0ce0848b6e17fa02987bcd0f5ea7ed61)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-i.jpg?sign=1739288688-yTbvQmo7QsqTUrMbn625ofWLNJU0KZ14-0-2d3313d70355d5e821a7dca5a55362bb)
由于我们决定使用sigmoid作为激活函数,这里可以将其添加为外部函数。同样,我们知道需要计算导数,因为我们正在使用SGD。因此,我们将其实现为另一种方法。通过使用上述公式,实现变得非常简单:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-2-i.jpg?sign=1739288688-trsXm3Sho0y32ZDNaEfo5hZQVKOBV4eb-0-a431cf6565f2fd6ad77bbcf9c0fb4305)
然后,我们用一个函数来计算前向传递,而另一个函数用于反向传递。我们将使用输入和权重之间的点积来计算输出,然后将所有内容通过sigmoid传递:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-3-i.jpg?sign=1739288688-CF3FXo0Z5cgVRK57bUpENL0pk8VqifOz-0-cc2faa0f9594f9ab4d667619e999813e)
前向传播也是我们将用于预测的内容,但是我们将创建别名,因为在此任务中最常用的名称是predict:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-4-i.jpg?sign=1739288688-nOgHCrxM0HN6aJLGyr3d0fXT59PxVRPo-0-f2a61d5414b81bddc18a9f4085909aa5)
反向传播中最重要的概念是误差的反向传播,从而调整权重并减少误差。我们在backward方法中实现此函数。为此,我们从输出开始,计算预测值与实际输出之间的误差。这将用于计算在更新权重时使用的delta。在所有层中,我们将神经元的输出用作输入,将其通过sigmoid的导数,然后乘以误差和步长(也称为学习率):
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-5-i.jpg?sign=1739288688-kH2UyOXVwfW1lKPzFTBEfyIQ73NNN2cP-0-f0629e71a040172bc3bc48e4a56f170e)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-i.jpg?sign=1739288688-KBMVMegvSkHsjmqMfBZkFO3S2FzDpaeT-0-a5dc0b7ec10ea70b62dcb4eaee60c25e)
在就每个数据点训练模型时,我们将进行两次传递,前向一次,反向一次。因此,我们的fit方法将如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-2-i.jpg?sign=1739288688-qGgJAzS1XIHXgX1PC2QhhmirccdcGI4H-0-aa4b802149d7d04036fef1a0e4791761)
现在,神经网络已经准备就绪,可以用于我们的任务了。我们还需要一个训练集和一个测试集:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-3-i.jpg?sign=1739288688-sVAO1w96nVisPZPbOchsP4rMdPCpSQuB-0-1fe72ae290fa6c36c04a3ab18a6fc889)
现在可以如下训练网络:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-4-i.jpg?sign=1739288688-wvzuxpc2McUqleOOzlXFa4gADovWow3O-0-6923b911c87c907f1e0d212c4c3abf64)
我们将验证算法的性能,如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-5-i.jpg?sign=1739288688-YjlNyKSQkD6RqAn2EOfzhWJeMP5DTTyF-0-bcc3fffd64672540fda9f7330bd554ba)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-i.jpg?sign=1739288688-iSFnhr1gv9NABlnwdPbtUHxgYDeG1RYx-0-c53765ad64e59ed0788a2238499a39aa)
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=1739288688-DaU8ACGyFCRg8gIqucs9eDr5r2PUetHf-0-7fddf3af0742e19ee49c4744966688b9)
我们会得到一个不错的结果,可通过下列的混淆矩阵进行检测。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-3-i.jpg?sign=1739288688-ZGHeJXH8JZ3HLeoLA7PPaneeev36f1dM-0-4d57da8a9f8ce7acb6dec0a9bdd7e8ed)
通过可视化聚类结果,我们可以清楚地知道误差在哪里,如图2-16所示。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/2-16.jpg?sign=1739288688-htVl2fCyEgyHp9fsMYXSoEgwyklHt82p-0-4c86be2f38b57a7d43a942798d5d4030)
图 2-16