这篇博客主要推导深度神经网络中,经典的Backpropagation求导算法的推导。 因为是随手做的笔记,所以中间有一些中英文夹杂的表达,希望不会对您的理解不会有干扰。还请读者见谅。 In this part, we will derive some most important equations in deep learning. \
在一个神经网络中,使用alk表示第l层,第k个神经元的activation的值,使用blk表示第l层,第k个神经元的bias。使用wljk表示第l层上的第j个单元和第l-1层上的第k个单元的权重。由此可以根据前一层的激活值,计算出当前层任意一个单元的激活值。激活函数是
alj=σ(∑kwljkal−1k+blj)
其中σ 是激活函数。\
假设第l层有2个单元,第l-1层有4个单元,那么我们可以将其写成向量形式
al=σ^(wlal−1+bl)=σ^([wl11wl21wl12wl22wl13wl23wl14wl24]⎡⎣⎢⎢⎢⎢⎢al−11al−12al−13al−14⎤⎦⎥⎥⎥⎥⎥+[bl1bl2])
相应的,激活函数σ^也变成可以处理向量的形式。\
这里用C表示cost function,BP的目的是求出∂C∂w 和 ∂C∂b。 最原始的求函数代价函数的偏导的方式就是使用表达式然后求导。 以两层神经元为例,计算代价函数,然后对weight进行求导如下:这里的未知数就是w2,b2,代价函数为
C∂C∂w∂C∂b=a2−a^2=σ^(w2a1+b2)=σ^′∂(w2)a1=σ^′∂(b2)
这里只有一个输入层,一个输出层,比较简单,但是如果有多个层,就比较复杂了,比如右图中的情况
C=a3−a^3=σ(w3a2+b3)−a^3=σ(w3σ(w2a1+b2)+b3)−a^3
如果层数再增加,嵌套就只能在往上增加了,最后导致求导非常复杂。\
BP很早就被使用在auto difficiation中,第一个在神经网络中使用BP的应该是Werbos (1982)。 然后接着在论文中发表 (Parker, 1985; LeCun, 1985)。 here is a link to talk about the history of backpropagation “Who Invented Backpropagation”. 下面开始介绍BP具体做的内容。\
在前面的做法中,我们直接把最终的误差和单个weight联系起来,在BP中,我们引入一个新的中间变量,表示某个单元的误差,σlj.\ 这里介绍了一个扰动的概念,zlj表示该单元的weighted 输入,如果通过扰动该单元(改变单元的权重wlj),我们有Δzlj,那么该单元就输出σ(zlj+Δzlj),相应的最终的输出也要变,变化量可以求出来∂C∂zljΔzlj. 如果想要向下降方向移动,那么这个扰动需要满足∂C∂zljΔzlj<0, 这里举一个f(x)=4x2为例,初始值给1,∂f∂x=8x, 那么在xop>0时,Δx应该选择向小的方向变动,当xop<0时, Δx应该选择向大的方向变动。 这里也是这个道理,如果求得了∂C∂zlj,就可以知道怎么调整Δzlj(即权重),使得目标函数变小,即往优化的方向上走。因为这个缘故,我们专门定义一个指标
δlj≡∂C∂zlj
在这种定义下,根据链式法则,我们可以将之前的求导目标变成
∂C∂W=∂C∂Z∂Z∂W=δ∂Z∂W
对每一个神经元来说,其输入zlj是w和b的线性函数,求导相当容易。所以求每个神经元的误差是非常有用的。
\subsection{Derivative of neuron error}
这里假设C的表达式是已知的,比如
C∂C∂aLδL=1/2||(y−aL)||2=aL−y=(aL−y)⊙∂aL∂zL=(aL−y)⊙σ(zL)′
这里是第L层,那第L-1层呢?因为C也是关于aL−1的函数,所以
∂C∂aL−1δL−1=∂C∂zL∂zL∂aL−1=δL∂zL∂aL−1=(WL)TδL=∂C∂aL−1∂aL−1∂zL−1=(WL)TδL⊙σ(zL−1)′
以上图中的神经网络为例,∂C∂aL∈R3×1,z3=w33×2a22×1+b33×1.
根据这种传播规律,首先计算出第L层的neurons error δ之后,\textbf{就可以逐步往前回溯},求出前面所有层中的error。这个error并不是目标函数中的error,而是一个变化率,当输入和改变1个单位的时候,目标函数C的该变量。\
以L层为例对weight进行求导
zL3×1∂C∂wL=wL3×2aL−12×1+bL3×1=δL∂zL∂wL=δL(aL−1)T
同理,以L层为例对bias求偏导
∂C∂bL=δL
到此为止,使用backpropagation求偏导就解决了。