前言:
各位读者好,这里是手写BP神经网络的第三个部分:总结。一定会有读者抱有一些疑惑:我已经通过Part2的上下的两个部分理解了甚至已经实现了模型,为什么还需要这一篇呢?至今为止读者掌握的是组成一台庞大的机器的所有的零件的制作方式,也同时掌握了制作这台机器的图纸。但是,这并不意味着读者可以依靠这些就加工出任何零件:可能不同品种的零件需要的是对于机器做一些细微的调整。如果说回BP神经网络就是:什么样的网络层才能收敛?不同的损失函数分别收敛的条件是什么?上限的准确率又是多少?这些问题都会在本章完成解析。这个部分作者做了比较完整的实验进行说明,也会在这一博文之中叙述出来。那么在开始本章之前,作者先贴上上一个Part的传送门。阅读本文之前建议先阅读上一组文章。
手写感知器的反向传播算法 Part2:基于理论推导的代码实践:如何实现自己的第一个神经网络完成手写体识别?(上)-优快云博客
预备:
预备Part1:说明实验背景:
由于本文更像是一个实验,所以这里作者先介绍实验的背景。
1)数据集一共620*12张图片,作者选择了6000张作为训练集,1440张作为测试集。
2)如同上一篇文章中所介绍的那样,本实验网络结构等可以调整。
3)learning rate作者设定为1e-2(关于这个部分作者后续会专门说明)
4)可以改变的是:损失函数的类别(ReLU&Sigmoid)&网络的层数结构&不同的trick
预备Part2:怎么进行实验?
(1)为什么会有这个问题出现?
关于如何进行实验这个问题,读者可能也会有些疑问:修改网络结构,训练就行了呗。但是实际上,体验过的读者都会发现,用自己的训练极慢无比。究其原因是因为其不可能用上cuda加速。而有无cuda加速将带来整整10倍的速度差异。那么这里作者将给出在pytorch上怎么进行类似训练的代码。这个部分不仅教会了读者如何用pytorch完成这个任务(这也是机器学习的基本任务之一),还给了读者自己写代码时如何用pytorch验证自己的任务是否出现了问题的方法
(2)具体怎么做?(理论分析)
想要完成一个严格的实验,那么需要的就是能够严格进行对照。这也就意味着对于感知器的初始化权重两者必须一样。手写的BP神经网络的权重想要定为一个值是比较容易的:在前面的initialize函数中修改即可,这里主要给出的就是,怎么在一个成型的pytorch程序之中让每一层都使用给定的权重。那么下面作者就给出对应的代码
(3)具体怎么做?(代码分析)
1.手写BP神经网络中的initialize函数:
def initialize(self):
n1 = np.loadtxt("matrix1.txt", delimiter=',', dtype=float)
n2 = np.loadtxt("matrix2.txt", delimiter=',', dtype=float)
n3 = np.loadtxt("matrix3.txt", delimiter=',', dtype=float)
n = [n1,n2,n3]
b1 = np.loadtxt("bias1.txt", delimiter=',', dtype=float)
b2 = np.loadtxt("bias2.txt", delimiter=',', dtype=float)
b3 = np.loadtxt("bias3.txt", delimiter=',', dtype=float)
b = [b1,b2,b3]
for i in range(layer_num + 1):
l = self.neuron_sit[i]
w = self.neuron_sit[i + 1]
copy(self.weight_para[:, :, i], n[i])
copy(self.bias_para[:, i], b[i])
# 每一个层只有需要的参数才非0,,这样安排便于检查
这里的每一个txt文件就是保存的初始化的权重。
2.pytorch代码之中的关键部分:
model = Linear_model.linear_model()
n1 = np.loadtxt("matrix1.txt", delimiter=',', dtype=float)
n2 = np.loadtxt("matrix2.txt", delimiter=',', dtype=float)
n3 = np.loadtxt("matrix3.txt", delimiter=',', dtype=float)
b1 = np.loadtxt("bias1.txt", delimiter=',', dtype=float)
b2 = np.loadtxt("bias2.txt", delimiter=&#