详解反向传播算法(小白版)
反向传播算法在神经网络中站很大的地位,大多数神经网络都能用反向传播算法进行训练,
但不少初学者不容易弄懂(比如说我),所以写个小白版教程很有必要
(这里不讲前向传播,可自行寻找相关信息)
首先先规定一些宏:
LS:神经网络的层数 NF(n):神经网络第n层的神经元个数BF(n,a):神经网络第n层第a个神经元的偏置(输入层没有偏置)WF(n,a,p):神经网络第n层第a个神经元的第p个权重(输入层没有权重)NETF(n,a):神经网络第n层第a个神经元的加权和(wx+b)OF(n,a):神经网络的第n层第a个神经元的输出(不包括输入层,OF可有可无,有点话使用某些激活函数可方便计算)SF(n,a):神经网络的第n层第a个神经元的误差INF(n):神经网络的第n个输入OUTF(n):神经网络的第n个实际输出(即输出层第n个输出)TAF(n):神经网络的第n个理想输出(即样本输出)LN:学习率F(x):激活函数函数F_(x):激活函数的导函数
注意:
我设计的输入层比较特殊,只有输入,严格来说不属于神经元,单纯做数据输入口
由于输入层和输出层比较特殊,所以反向传播过程中需要分开进行(不分开也行,靠自己设计呗)
在进行反向传播之前,首先需要先前向传播一次,计算好各个层的(加权和)和输出
首先是计算输入层的误差(为了更加容易理解,这里用文字和符号表述):
SF(LS,1) = (2.0/NF(LS))*(OUTF(1) - TAF(1))输出层第1个神经元的误差 = (2.0/输出层神经元数量)*(实际第1个输出-理想第1个输出),以此类推ps:注意这里是浮点数2.0不是整数2
更新输入层的权重和偏置:
BF(LS,1) = BF(LS,1) - LN * SF(LS,1)更新后的输入层第1个偏置 = 原偏置 - 学习率*输入层第1个误差,以此类推WF(LS,1,2) = WF(LS,1,2) - LN * SF(LS,1) * OF(LS-1,2);更新后的输入层第1个神经元的第2个权重 = 原权重 - 学习率 * 输入层第1个误差 * 上一层第2个输出作为参照:WF(LS,1,4) = WF(LS,1,4) - LN * SF(LS,1) * OF(LS-1,4);更新后的输入层第1个神经元的第4个权重 = 原权重 - 学习率 * 输入层第1个误差 * 上一层第4个输出 以此类推
然后是隐藏层的误差:
SF(n,4) = SF(n+1,1)*WF(n+1,1,4)*F_(NETF(n,4)) + SF(n+1,2)*WF(n+1,2,4)*F_(NETF(n,4)) + SF(n+1,3)*WF(n+1,3,4)*F_(NETF(n,4)) + ...........第n层第4个神经元的误差 = 下一层第1个神经元的误差 * 下一层第1个神经元第4个权重 * 第n层的第4个神经元的导函数输出 +下一层第2个神经元的误差 * 下一层第2个神经元第4个权重 * 第n层的第4个神经元的导函数输出 +下一层第3个神经元的误差 * 下一层第3个神经元第4个权重 * 第n层的第4个神经元的导函数输出+........ps:这里之所以用计算第n层第4个神经元的误差做例,是为了更好的理解实际上就是个数学表达式:第n层的误差数组 = (下一层的误差数组*下一层的权重矩阵)*第n层的加权和的导数数组
隐藏层的误差计算 , 权重和偏置的更新与输出层一样,这里就不加赘述了
由于输入层只有输入,所以没有误差
总之,神经网络搭建完后,就可以开始训练了,导入样本,然后开始前向传播一次,反向传播一次,反复计算
其中需要计算总误差:
double val = 0; for (int a = 1; a <= NF(LS); a++) { val += ((OF(LS, a) - TAF(a)) * (OF(LS, a) - TAF(a))) / NF(LS); }
至此,反向传播的大致公式就完了,具体细节和相关知识可自行查询(资料挺多的,应该不用担心)