![神经网络设计与实现](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=1739161782-KVLoljHKGTGUuvkDEnweRLRVWBDolJ3i-0-6e745c48ad5d18716e365b8e3d2b3777)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-i.jpg?sign=1739161782-5FiNjkilseeArRkNbe9spZKcXEm4xX5s-0-658c218de5cc9c47b01ba1254c14d1f6)
由于我们决定使用sigmoid作为激活函数,这里可以将其添加为外部函数。同样,我们知道需要计算导数,因为我们正在使用SGD。因此,我们将其实现为另一种方法。通过使用上述公式,实现变得非常简单:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-2-i.jpg?sign=1739161782-PnyRhmoCTpLrK9r712hq7hzWtDdgvn9v-0-27142d1d99e1b868698d30d7bdc22bd9)
然后,我们用一个函数来计算前向传递,而另一个函数用于反向传递。我们将使用输入和权重之间的点积来计算输出,然后将所有内容通过sigmoid传递:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-3-i.jpg?sign=1739161782-5AWe7lV2YKUagwHE25f5hJAopU8zrJTf-0-8d75ea2cd6cb10267348ad469d06a8c2)
前向传播也是我们将用于预测的内容,但是我们将创建别名,因为在此任务中最常用的名称是predict:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-4-i.jpg?sign=1739161782-iFkIyNUZGi2h1hGkh0iSrWyvfNIULG98-0-e994905659efaca29bf3a3b392c66eb5)
反向传播中最重要的概念是误差的反向传播,从而调整权重并减少误差。我们在backward方法中实现此函数。为此,我们从输出开始,计算预测值与实际输出之间的误差。这将用于计算在更新权重时使用的delta。在所有层中,我们将神经元的输出用作输入,将其通过sigmoid的导数,然后乘以误差和步长(也称为学习率):
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/041-5-i.jpg?sign=1739161782-PR4ARmzTxe0iWoKFnf6ONkYloKjUm7Ds-0-1bcc8164ba11e6e0e15799677c233428)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-i.jpg?sign=1739161782-F9FDkjsVxeNO7NGaUxguHlWL6LqjzUaj-0-cf394d7f4bf9a394fef7c3aefa43cb79)
在就每个数据点训练模型时,我们将进行两次传递,前向一次,反向一次。因此,我们的fit方法将如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-2-i.jpg?sign=1739161782-qwSGHuauoJzPS0XeBpLaHlhX1bYYDFTs-0-6390236f038c986bff179b7a6ff244fb)
现在,神经网络已经准备就绪,可以用于我们的任务了。我们还需要一个训练集和一个测试集:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-3-i.jpg?sign=1739161782-gseZIG4hTXIMbzHJV2dlOn3EomNovpxy-0-d7e78a47c5c87efe65ae27f1b7119a85)
现在可以如下训练网络:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-4-i.jpg?sign=1739161782-2arYVa08TnpvQySgQculFBcQh6dAUSYv-0-4e22bca7499584c4ebb14c1fe4380593)
我们将验证算法的性能,如下所示:
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/042-5-i.jpg?sign=1739161782-g1ZNIjk6kZHaXliSQxQx0SLOsh2hM58j-0-a2f8df8057d4825bb6638c2ddfe4a01d)
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-i.jpg?sign=1739161782-3BQogQFKVdrzWsDR1t3Fw6DFlSl7lduc-0-823fcabecc993987ca79d384bd67ebdb)
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=1739161782-T1PGPggcUkBY6sI9AVYGOnIXN2aCgzbO-0-1d4411061572b319dd579527840dee0a)
我们会得到一个不错的结果,可通过下列的混淆矩阵进行检测。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/043-3-i.jpg?sign=1739161782-Spl9WVOgmswDbyt8LWyx2Dxhpj7fLu3C-0-71576954b858bd9d3a6a331a4cadcee7)
通过可视化聚类结果,我们可以清楚地知道误差在哪里,如图2-16所示。
![](https://epubservercos.yuewen.com/96A46E/20422784308285606/epubprivate/OEBPS/Images/2-16.jpg?sign=1739161782-sfGcesBrk8WP5VzzPc5t19i6cX5irgdg-0-1e7d5d4cb637a5888d2f33af89f0abfe)
图 2-16