反向传播算法及其梯度扩散
前言
最近开始认真学习了下反向传播算法和梯度传递的问题,其本质是导数的链式法则的应用,由此可以分析出为什么sigmoid激活函数不适合用于做多层网络的激活函数,可以考虑联系我的另一篇关于激活函数的文章。如有谬误,请联系指正。转载请注明出处。
联系方式:
e-mail : FesianXu@163.com
QQ : 973926198
github : https://github.com/FesianXu
完整代码开源: click me || 其中的sigmoid_base_BP.py
神经网络
要知道什么是反向传播算法,我们还是要从神经网络开始将起。神经网络如图所示。
图中所示的是一个具有一个输入层(input layer),一个隐藏层(hidden layer),一个输出层(output layer)的三层神经网络。我们都知道,在神经网络的训练过程中,其权值是通过梯度的变化大小来更新的,我们这里先进行符号规定,以便于接下来的分析。
w j k l w^l_{jk} w j k l 是l-1 层的第k个神经元与l 层的第j个神经元的连接权值
b j l b^l_{j} b j l 是l 层的第j个神经元的偏置。
z j l z^l_{j} z j l 是l 层的第j神经元的输入。
a j l a^l_{j} a j l 是l 层的第j神经元的激活输出。
用公式表达即是:
(1.1) z j l = ∑ k ( w j k l ∗ a k l − 1 + b j l ) z^l_{j} = \sum_{k} (w^l_{jk}*a^{l-1}_{k}+b^l_j) \tag{1.1} z j l = k ∑ ( w j k l ∗ a k l − 1 + b j l ) ( 1 . 1 )
(1.2) a j l = σ ( z j l ) = σ ( ∑ k ( w j k l ∗ a k l − 1 + b j l ) ) a^l_j = \sigma(z^l_j) = \sigma(\sum_k (w^l_{jk}*a^{l-1}_k+b^l_j) ) \tag{1.2} a j l = σ ( z j l ) = σ ( k ∑ ( w j k l ∗ a k l − 1 + b j l ) ) ( 1 . 2 )
其中的σ ( x ) \sigma(x) σ ( x ) 为激活函数。多采用sigmoid,ReLU,tanh 等。
C = 1 2 n ∗ ∑ x ∣ ∣ y − a L ∣ ∣ 2 C = \frac{1}{2n}*\sum_x||y-a^L||^2 C = 2 n 1 ∗ ∑ x ∣ ∣ y − a L ∣ ∣ 2 代价函数,其中L是神经网络的层数。
我们知道,进行权值更新的时候,我们采用的是梯度下降法更新(Gradient Descent), 公式如下:
(1.3) w j k l : = w j k l − η ∗ ∂ C ∂ w j k l
w^l_{jk} := w^l_{jk}-\eta*\frac{\partial{C}}{\partial{w^l_{jk}}}
\tag{1.3}
w j k l : = w j k l − η ∗ ∂ w j k l ∂ C ( 1 . 3 )
这里最重要的便是需要求得∂ C ∂ w j k l \frac{\partial{C}}{\partial{w^l_{jk}}} ∂ w j k l ∂ C ,为了求得这个导数,我们现在有几个公式需要推导,这些公式大多都有链式法则推导而出。
δ L = ∇ a C ⨀ σ ′ ( z L ) \delta^L = \nabla_a{C}\bigodot \sigma^\prime(z^L) δ L = ∇ a C ⨀ σ ′ ( z L ) (对L层的误差)
其中我们要注意的是,对于某层的误差δ l \delta^l δ l 定义为δ l = ∂ C ∂ z l \delta^l = \frac{\partial{C}}{\partial{z^l}} δ l = ∂ z l ∂ C ,其中具体到某一个神经元j的误差为δ j l = ∂ C ∂ z j l \delta^l_j = \frac{\partial{C}}{\partial{z^l_j}} δ j l = ∂ z j l ∂ C 。
推导:
(2.1) δ j L = ∂ C ∂ z j L = ∂ C ∂ a j L ∗ ∂ a j L ∂ z j L = ∂ C ∂ a j L ∗ σ ′ ( z j L )
\delta^L_j = \frac{\partial{C}}{\partial{z^L_j}} = \frac{\partial{C}}{\partial{a^L_j}}*\frac{\partial{a^L_j}}{\partial{z^L_j}} = \frac{\partial{C}}{\partial{a^L_j}}*\sigma^\prime(z^L_j)
\tag{2.1}
δ j L = ∂ z j L ∂ C = ∂ a j L ∂ C ∗ ∂ z j L ∂ a j L = ∂ a j L ∂ C ∗ σ ′ ( z j L ) ( 2 . 1 )
所以当扩展到对于所有的第L层的神经元时,我们为了方便用一个矩阵去代表我们的结果:
(2.2) δ L = ( δ 1 L δ 2 L )
\delta^L = \left(\begin{array}{c}
\delta^L_1 \\
\delta^L_2
\end{array}\right)
\tag{2.2}
δ L = ( δ 1 L δ 2 L ) ( 2 . 2 )
需要注意的是,所有的误差矩阵都可以这样定义,如:
(2.3) δ l = ( δ 1 l , δ 2 l , ⋯  , δ n l ) T
\delta^l = (\delta^l_1, \delta^l_2, \cdots,\delta^l_n)^T
\tag{2.3}
δ l = ( δ 1 l , δ 2 l , ⋯ , δ n l ) T ( 2 . 3 )
其中n是l层神经元的数量,类似的,可以得出:
(2.4) σ ′ ( z l ) = ( σ ′ ( z 1 l ) , σ ′ ( z 2 l ) , ⋯  , σ ′ ( z n l ) )
\sigma^\prime(z^l) = (\sigma^\prime(z^l_1),\sigma^\prime(z^l_2),\cdots,\sigma^\prime(z^l_n))
\tag{2.4}
σ ′ ( z l ) = ( σ ′ ( z 1 l ) , σ ′ ( z 2 l ) , ⋯ , σ ′ ( z n l ) ) ( 2 . 4 )
其中n是第l层的神经元数量
由此可以得出结论:
(2.5) δ L = ∇ a C ⨀ σ ′ ( z L )
\delta^L = \nabla_a{C}\bigodot \sigma^\prime(z^L)
\tag{2.5}
δ L = ∇ a C ⨀ σ ′ ( z L ) ( 2 . 5 )
其中,∇ ( ⋅ ) \nabla(·) ∇ ( ⋅ ) 算子代表了梯度 ,具体为∇ x f ( x ) \nabla_xf(x) ∇ x f ( x ) 代表f ( x ) f(x) f ( x ) 对x x x 的所有偏导数的矩阵,类似于:
(2.6) ∇ x f ( x ) = ( ∂ f ( x ) ∂ x 1 , ∂ f ( x ) ∂ x 2 , ⋯  , ∂ f ( x ) ∂ x n ) , x ∈ R n
\nabla_xf(x) = (\frac{\partial{f(x)}}{\partial{x_1}}, \frac{\partial{f(x)}}{\partial{x_2}}, \cdots, \frac{\partial{f(x)}}{\partial{x_n}}), x \in R^n
\tag{2.6}
∇ x f ( x ) = ( ∂ x 1 ∂ f ( x ) , ∂ x 2 ∂ f ( x ) , ⋯ , ∂ x n ∂ f ( x ) ) , x ∈ R n ( 2 . 6 )
而⨀ \bigodot ⨀ 是点乘 ,表示了两个操作数的各个元素的分别相乘,前提是两个操作数的维度统一。
δ j l = ∑ k ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) ) \delta^l_j = \sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j)) δ j l = ∑ k ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) ) 第l层第j个神经元的误差
(3.1) δ j l = ∂ C ∂ z j l = ∑ k ∂ C ∂ z k l + 1 ∗ ∂ z k l + 1 ∂ a j l ∗ ∂ a j l ∂ z j l = ∑ k δ k l + 1 ∗ ∂ ( w k j l + 1 ∗ a j l + b k l + 1 ) ∂ a j l ∗ σ ′ ( z j l ) = ∑ k ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) )
\delta^l_j =
\frac{\partial{C}}{\partial{z^l_j}} =
\sum_k \frac{\partial C}{ \partial z^{l+1}_k} * \frac{ \partial{z^{l+1}_k} }{ \partial{a^l_j} } *
\frac{ \partial{a^l_j} }{ \partial{z^l_j} } \\
= \sum_k \delta^{l+1}_k * \frac{ \partial({w^{l+1}_{kj}} * a^l_j+b^{l+1}_k )}{ \partial{a^l_j} } * \sigma^\prime(z^l_j)
= \sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j))
\tag{3.1}
δ j l = ∂ z j l ∂ C = k ∑ ∂ z k l + 1 ∂ C ∗ ∂ a j l ∂ z k l + 1 ∗ ∂ z j l ∂ a j l = k ∑ δ k l + 1 ∗ ∂ a j l ∂ ( w k j l + 1 ∗ a j l + b k l + 1 ) ∗ σ ′ ( z j l ) = k ∑ ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) ) ( 3 . 1 )
同样的,为了表示方便,也多用矩阵形式表示,有:
(3.2) δ 1 l = δ 1 l + 1 ∗ w 11 l + 1 ∗ σ ′ ( z 1 l ) + δ 2 l + 1 ∗ w 21 l + 1 ∗ σ ′ ( z 1 l ) \delta^l_1 = \delta^{l+1}_1*w^{l+1}_{11}*\sigma^\prime(z^l_1)+
\delta^{l+1}_2*w^{l+1}_{21}*\sigma^\prime(z^l_1)
\tag{3.2}
δ 1 l = δ 1 l + 1 ∗ w 1 1 l + 1 ∗ σ ′ ( z 1 l ) + δ 2 l + 1 ∗ w 2 1 l + 1 ∗ σ ′ ( z 1 l ) ( 3 . 2 )
(3.3) δ 2 l = δ 1 l + 1 ∗ w 12 l + 1 ∗ σ ′ ( z 2 l ) + δ 2 l + 1 ∗ w 22 l + 1 ∗ σ ′ ( z 2 l )
\delta^l_2 = \delta^{l+1}_1*w^{l+1}_{12}*\sigma^\prime(z^l_2)+
\delta^{l+1}_2*w^{l+1}_{22}*\sigma^\prime(z^l_2)
\tag{3.3}
δ 2 l = δ 1 l + 1 ∗ w 1 2 l + 1 ∗ σ ′ ( z 2 l ) + δ 2 l + 1 ∗ w 2 2 l + 1 ∗ σ ′ ( z 2 l ) ( 3 . 3 )
(3.4) δ 3 l = δ 1 l + 1 ∗ w 13 l + 1 ∗ σ ′ ( z 3 l ) + δ 2 l + 1 ∗ w 23 l + 1 ∗ σ ′ ( z 3 l )
\delta^l_3 = \delta^{l+1}_1*w^{l+1}_{13}*\sigma^\prime(z^l_3)+
\delta^{l+1}_2*w^{l+1}_{23}*\sigma^\prime(z^l_3)
\tag{3.4}
δ 3 l = δ 1 l + 1 ∗ w 1 3 l + 1 ∗ σ ′ ( z 3 l ) + δ 2 l + 1 ∗ w 2 3 l + 1 ∗ σ ′ ( z 3 l ) ( 3 . 4 )
(3.5) δ 4 l = δ 1 l + 1 ∗ w 14 l + 1 ∗ σ ′ ( z 4 l ) + δ 2 l + 1 ∗ w 24 l + 1 ∗ σ ′ ( z 4 l )
\delta^l_4 = \delta^{l+1}_1*w^{l+1}_{14}*\sigma^\prime(z^l_4)+
\delta^{l+1}_2*w^{l+1}_{24}*\sigma^\prime(z^l_4)
\tag{3.5}
δ 4 l = δ 1 l + 1 ∗ w 1 4 l + 1 ∗ σ ′ ( z 4 l ) + δ 2 l + 1 ∗ w 2 4 l + 1 ∗ σ ′ ( z 4 l ) ( 3 . 5 )
(3.6) W l + 1 = ( w 11 l + 1 w 12 l + 1 w 13 l + 1 w 14 l + 1 w 21 l + 1 w 22 l + 1 w 23 l + 1 w 24 l + 1 )
W^{l+1} = \left(\begin{array}{ccc}
w^{l+1}_{11} & w^{l+1}_{12} & w^{l+1}_{13} & w^{l+1}_{14}\\
w^{l+1}_{21} & w^{l+1}_{22} & w^{l+1}_{23} & w^{l+1}_{24}
\end{array}\right)
\tag{3.6}
W l + 1 = ( w 1 1 l + 1 w 2 1 l + 1 w 1 2 l + 1 w 2 2 l + 1 w 1 3 l + 1 w 2 3 l + 1 w 1 4 l + 1 w 2 4 l + 1 ) ( 3 . 6 )
所以,有:
(3.7) δ l = ( ( W l + 1 ) T ∗ δ l + 1 ) ⨀ σ ′ ( z l )
\delta^l = ((W^{l+1})^T * \delta^{l+1}) \bigodot \sigma^\prime(z^l)
\tag{3.7}
δ l = ( ( W l + 1 ) T ∗ δ l + 1 ) ⨀ σ ′ ( z l ) ( 3 . 7 )
∂ C ∂ w j k l = a k l − 1 ∗ δ j l \frac{\partial{C}}{\partial{w^l_{jk}}} = a^{l-1}_k*\delta^l_j ∂ w j k l ∂ C = a k l − 1 ∗ δ j l 误差具体到对某个边权重的偏导数
(4.1) ∂ C ∂ w j k l = ∂ C ∂ z j l ∗ ∂ z j l ∂ w j k l = a k l − 1 ∗ δ j l = a k l − 1 ∗ ∑ k ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) )
\frac{\partial{C}}{\partial{w^l_{jk}}} = \frac{\partial{C}}{\partial{z^l_{j}}} *
\frac{\partial{z^l_j}}{\partial{w^l_{jk}}} =
a^{l-1}_k*\delta^l_j=a^{l-1}_k *
\sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j))
\tag{4.1}
∂ w j k l ∂ C = ∂ z j l ∂ C ∗ ∂ w j k l ∂ z j l = a k l − 1 ∗ δ j l = a k l − 1 ∗ k ∑ ( δ k l + 1 ∗ w k j l + 1 ∗ σ ′ ( z j l ) ) ( 4 . 1 )
由此可以看出,∂ C ∂ w j k l \frac{\partial{C}}{\partial{w^l_{jk}}} ∂ w j k l ∂ C 与σ ′ ( z j l ) \sigma^\prime(z^l_j) σ ′ ( z j l ) 呈正相关的关系,当激活函数采用了sigmoid函数时,由于x越大,其导数呈现指数衰减,所以在层数太大而且输出值范围太大的时候,∂ C ∂ w j k l \frac{\partial{C}}{\partial{w^l_{jk}}} ∂ w j k l ∂ C 就会变得很小,从而使得参数的更新速率变得很慢,因此会出现梯度消散 的问题(The problem of gradient vanishing)。
此时,可以考虑替换代价函数或者激活函数,对于更换激活函数,可以更换为ReLU (Rectified Linear Units)函数,R e L U = m a x ( 0 , x ) ReLU = max(0, x) R e L U = m a x ( 0 , x ) 其导数为分段导数,在激活区x > 0 x > 0 x > 0 时,其导数恒为1,不会存在梯度消散的问题。
∂ C ∂ b j l = δ j l \frac{\partial{C}}{\partial{b^l_j}} = \delta^l_j ∂ b j l ∂ C = δ j l 误差对偏置的导数
(5.1) ∂ C ∂ b j l = ∂ C ∂ z j l ∗ ∂ z j l ∂ b j l = δ j l ∗ 1 = δ j l
\frac{\partial{C}}{\partial{b^l_j}} =
\frac{\partial{C}}{\partial{z^l_j}} *
\frac{\partial{z^l_j}}{\partial{b^l_j}} = \delta^l_j*1 = \delta^l_j
\tag{5.1}
∂ b j l ∂ C = ∂ z j l ∂ C ∗ ∂ b j l ∂ z j l = δ j l ∗ 1 = δ j l ( 5 . 1 )
总的更新公式
(6.1) w l : = w l − η ∗ δ l ∗ ( a l − 1 ) T
w^l := w^l-\eta*\delta^l*(a^{l-1})^T
\tag{6.1}
w l : = w l − η ∗ δ l ∗ ( a l − 1 ) T ( 6 . 1 )
(6.2) b l : = b l − η ∗ δ l
b^l := b^l-\eta*\delta^l
\tag{6.2}
b l : = b l − η ∗ δ l ( 6 . 2 )
我们在这篇文章中推导了BP算法的公式,我们接下来将在下一篇文章《基于numpy和python的反向传播算法的实现与分析》 中利用numpy和python实现BP算法,有兴趣的朋友请移步。
引用
《基于numpy和python的反向传播算法的实现与分析》