小白也能看懂的BP反向传播
BP过程中,更新公式长什么样?
众所周知,BP过程中通过权值的不断更新,使得神经网络的输出向groundtruth靠近。
开门见山,直接看图,这部分是为==后面==做铺垫,很简单昂~
我们随机给输入a,b添加一个随机值,然后用步长step来控制增加速度,看python代码:
1 | import random |
运行程序,输出30.023996846498836,比30大,但是如果继续测试,会出现问题,速看如下代码:
1 | def func(): |
运行程序,输出29.982885896252554,比30小,把输入a,b改成负数就失效了,所以对于step后面乘的系数,应该找一个和输入相关的值来控制,也就是一个关于输入值的函数。如果在这个点上,输出结果是随着输入值增加而增加,那么step乘以一个正数即可,反之,则需要乘以一个负数才能使输出结果增加!显然这就是函数在某点上的==微分==(前文铺垫的就是他)的定义!
eg:对于f = f(a, b) ,我们想要更新变量a,b的值,就可以根据下图公式来更新
实际上这就是BP的最基本思想啦~假设f就是神经网络的输出,将f与groundtruth计算误差,让f变大(或变小),使其更接近groundtruth,我们将改变f的变量,而f其实是长这样的,f = f(w,b) . 只不过真正的神经网络更复杂。
进一步了解BP
接下来,我们将一步一步地接近最终的神经网络中的BP。
不废话,直接看图。
代码实现如下:
1 | def multiply(x, y): |
输出结果为-7,现在开始训练,就是改变输入的a,b,c三个值,使函数f的值变大,那么就按照下图的方式更新。
更新公式
链式求导
现在问题就变成了如何求解f关于a,b,c的微分。
我们将f反着往回写,我们将第一个神经元的输出记作d,那么f = d *c , 继续反着推,d = a +b。这样就成了两个函数。如图:
下面开始链式求导,考过数学一二三的人最喜欢这个东西了。
继续,==不要停==:
然后最终结果如下:
反向传播代码实现
代码实现上述过程:
1 | def multiply(x, y): |
输出结果为-7
1 | def update(a, b, c): |
输出结果为-6.0113999999999965
可以看到更新之后的输出确实增大了,说明我们现在已经可以实现嵌套神经元的变量参数的更新了。
总结BP更新本质
首先,前向传播,从输入开始分析,输入值为a=5,b=-6,c=7,第一个神经元的输出d为-1,然后第二个神经元输出为7,最后结果为-7,这就是前向传播的过程。
然后,反向传播,从输出开始分析,目标是将输出变大,输出值是由-1*7得到的,现在要增加输出值,显然就是增加-1,减少7。再来计算微分,微分结果就是增加d,减少c。这里d又是由a,b决定的!那么只要增加a和b就行了,运用链式法则求a,b的微分,也能得到相同的结果。
我们倒着从输出到输入的过程就是反向传播的过程。通过计算微分可以更新变量的值,使得输出朝着我们期待的方向的变化!