bp算法
又称反向传导算法,英文: back propagation。
我们了解,前向传导,可以根据W,b来计算出隐层、输出层的各个神经元的值以及对应的激活值,最终得到输出。如果输出和我们的目标存在误差,这个误差可以用成本函数表示(loss function),那么我们就需要反向的把这个误差分配到前面的各个传导的过程中,也就是W和B上;我们需要知道每个神经元带来了多少误差,这个影响程度我们用“残差”的概念来表示。
有了残差和目标函数,我们可以对参数W和B随机梯度下降法来求解,即:求导后表示为残差的某种共识。最后W的更新,与:残差、当前神经元的激活函数求导、输入值;由这三部分来共同决定参数的更新。如此反复迭代直到收敛。 从而求出W和B。
这个算法的核心则是:残差的求解;因为激活函数是事先定义的,输入值也是前向算法中已经计算好的。那么问题则归结为误差反向传导的时候,如何分配因子。
前向过程

公式回顾和例子
这个是计算下一层第一个神经元的过程,就是利用前一层权重W和输入X线性组合后,加上偏置项,最后利用激活函数变换得到最终的结果。
这里需要澄清一下: x1,x2,x3 x 1 , x 2 , x 3 代表的是三个特征值,而不是三个instance,这地方要清晰。 这一点在逻辑回归中更好理解, X=[x1,x2,...,xn] X = [ x 1 , x 2 , . . . , x n ] 代表n个特征表示的一个样本数据,映射到 Y=+1,−1 Y = + 1 , − 1 (假设是二分类)。
而我们的第i个训练数据表示为 (X(i),y(i)) ( X ( i ) , y ( i ) ) .
例子
利用例子理解神经网络。
三层神经网络。
说明:
- 第一层是输入层,有2个神经元,i1和i2;截距项为b1=1;
- 第二层是隐含层,包括神经元h1,h2和截距项b2;
- 第三层是输出层o1,o2;
- 神经元之间的权重用w表示;
- 激活函数是sigmoid函数;
初始化
- 输入数据:i1=0.05, i2=0.10;
- 输出数据:o1=0.01, o2=0.99;
- 初始权重: w1=0.15, w2=0.20, w3=0.25, w4=0.30, w5=0.40, w6=0.45, w7=0.50, w8=0.55
目标:通过fp和bp算法,训练w和b,使得输入和输出匹配,拟合已有的数据。
step1:输入层到隐含层
神经元
注意net层只是线性组合,还没有执行激活函数;
这一步是执行激活操作。
参考:
each neuron is composed of two units. First unit adds products of weights coefficients and input signals. The second unit realise nonlinear function, called neuron activation function. Signal e is adder output signal, and y = f(e) is output signal of nonlinear element. Signal y is also output signal of neuron.
http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html (这篇后面的推导有问题,思路是对的。主要是负梯度有误,另外,一般用残差推导,这地方用的误差,残差=误差*激活求导。)
step2:隐含层到输出层
这样前向传播的过程就结束了,我们得到输出值为【0.7513,0.7729】得到多少个输出取决于分类标签的维度,比如打算分成两个类,则为2;如果打算分成10个类,则有10个神经元。
与实际值【0.01,0.99】相差较大,开始计算误差,进行反向传播,更新权重,重新计算。
step3:计算误差
有两个输出,误差分别计算o1和o2,总误差为两者之和:
误差就是目标函数,也就是loss function。没有目标的优化都是耍流氓。
误差的传播
误差从哪里来,就用梯度转向那里去;为了找到源头,则要一步步的从后往前传递,所以才有了:反向传播;链式求导这两个概念。
针对我们的传播,大体上就是两个核心步骤:线性组合的求导;以及激活函数的求导。如此根据关联一步步相乘,这也是链式求导的内涵。见下图:
由于e和cd有关系;而cd又和ab有关系;于是梯度的链式法则如图所示。(从哪里来,到哪里去!)
针对我们的神经网络:
step4:输出层反向到隐含层
我们依照误差先输出节点求导、再激活函数求导、然后线性组合求导的原则可知:
有了梯度,则用负梯度更新变量则可以保证目标函数下降最快。
step5:隐含层到隐含层
现在对w1求偏导;同理可以利用链式法则:
求导分三块,中间部分的求导是直接的,激活函数; 最后一部分求导也是线性求导,直接的。
第一部分则比较复杂一些,因为
outh1
o
u
t
h
1
影响了o1和o2,所以反向求导的时候,则需要关联到
Eo1,Eo2
E
o
1
,
E
o
2
那么我们就按照h1到最后的这条路径,一个个求导过来,并按照有多少路径累加,如果h1发出了3个神经元,则就需要反向三个梯度的累加。
正向的时候 w1->net(h1)->out(h1)->net(o1,o2,xxx)->out(o1,o2,xxx)->Etotal
反向求导的时候只要有关系,就必须求导相乘。
同理可求其他参数。
公式再归纳
从上面的示例中,我们大体了解了整个过程,那么我们再用公式推导一番。注意下面的公式将按照顺序直接给出,减少,防止思路中断。
从当前点传播过去的点都要反传回来,同时要对当前线性组合后的值求导,公式是激活函数。
至此,梯度和残差的关系结束。
参考文献
http://ufldl.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95
http://blog.csdn.net/zhaomengszu/article/details/77834845