本文主要是BP网络的前后向传播较详细推导,以及C++实现,记下来也方便后面的回顾,也希望对关系细节的读者也一丝帮助。如果有不对的地方,请指正。
BP图模型:
网络中单个激活单元:
- 上图定了隐层中的激活单元,该隐层激活单元中含有一个偏置项b。相关运算如图所示,符号右上角角标为单元在网络中的层好,结合代码实现时,网络激活单元之间的权重一般保存在前一层的单元中。
这里有两点注意:
- 输入层的单元中没有偏置项b,但有权值项w。
- 输出层的单元中没有权值项w,但有偏置项b。
相关符号定义:
符号 | 意义 |
---|---|
m | 样本数 |
nl | 网络的总层数 |
Ll | 第 l 层 |
|
l 层的j单元与
|
b(l)i | 第 l 层第i个单元的偏置项 |
|
表示第 l 层的节点数 |
|
表示第 l 层第i单元的激活值 |
f(x) | sigmoid函数:
|
z(l)i | 表示第 l 层第i单元的输入 |
|
表示整个网络对输入x的输出结果,等价于 a(nl) |
损失函数(带2范式正则):
J(W,b)=1m∑i=1mJ(W,b;xi,yi)+λ2∑l=1nl−1∑i=1Sl∑j=1Sl+1(W(l)ji)2
其中,J(W,b;x,y)=12∥hwb(x)−y∥2
我们优化所有权值和偏置就是通过最小化损失函数来实现的,通过对损失函数计算各权值和偏置的梯度,然后沿着各自梯度的反方向走,就可以让损失函数慢慢变小,由于神经网络不是的损失函数不是严格凸函数,所以并不能保证找到全局最优解。我们首先就要计算各权值和偏置关于损失函数的梯度。
前向传播
Tip : 这里需要先初始化各单元中的权值和偏置项的值,权值可以按照标准正态分布去产生,也可以使用其它方式产生,但最好不要偷懒而给所有权值赋上相同的值,这样会导致极慢的收敛速度,有兴趣的读者可以修改下面的程序自己试下。
- 输入层向隐层的前向传播:
- 向输入层输入数据X,第二层第i个激活单元相关计算:
该激活单元的输入: z(2)i=∑j=1S1W(1)ija(1)j+b(2)i ,其中 a(1)i=Xi
该激活单元的输入: a(2)i=f(z(2)i)=11+e−z(2)i
计算完输入层的前向传播后就可以计算隐层间的传播了。
- 向输入层输入数据X,第二层第i个激活单元相关计算:
- 隐层间的传播:
- 上一层的隐层输出值作为当前隐层的输入值:
第l 层第i个激活单元输入: z(l)i=∑j=1Sl−1W(l−1)ija(l−1)j+b(l)i
第l 层第i个激活单元输出: a(l)i=f(z(l)i)=11+e−z(l)i
隐层按照从低向高的顺序依次计算各层的激活单元,依次计算各层: l=3,4,...Snl−1
- 上一层的隐层输出值作为当前隐层的输入值:
- 输出层的传播:
- 传播到最后的输出层:
第 Snl 层第i个激活单元输入: z(nl)i=∑j=1Snl−1W(nl−1)ija(nl−1)j+b(nl)i
第 Snl 层第i个激活单元最终的输出: a(nl)i=f(z(nl)i)=11+e−z
- 传播到最后的输出层: