问题2.1: 如何计算梯度下降中代价函数的梯度?
对于这个问题,我们首先给出几个定义:
- w j k l w_{jk}^l wjkl代表 ( l − 1 ) (l-1) (l−1)层的第k个神经元到 l l l层的第 j j j个神经元的权重。
- b j l b_j^l bjl代表 l l l层的第 j j j个神经元的偏置。
- a j l a_j^l ajl代表第 l l l层第 j j j个神经元的激活值(也就是对应一组神经网络输入的输出)。
那么,激活值之间的关系可以表示成:
a
j
l
=
σ
(
∑
k
w
j
k
l
a
k
l
−
1
+
b
j
l
)
a_j^l = \sigma(\sum_k w_{jk}^l a_k^{l-1} + b_j^l)
ajl=σ(k∑wjklakl−1+bjl)
写成向量形式:
a
l
=
σ
(
w
l
a
l
−
1
+
b
l
)
a^l = \sigma(w^l a^{l-1} + b^l)
al=σ(wlal−1+bl)
其中的
z
l
=
w
l
a
l
−
1
+
b
l
z^l=w^l a^{l-1} + b^l
zl=wlal−1+bl我们叫做带权输入,
σ
\sigma
σ是sigmoid函数。
同时,我们定义 δ j l = ∂ C ∂ z j l \delta_j^l=\displaystyle\frac{\partial C}{\partial z_j^l} δjl=∂zjl∂C为第 l l l层第 j j j个神经元上的误差。写成向量形式就是 δ l = ∇ z l C \delta^l=\displaystyle\nabla_{z^l}C δl=∇zlC。那么,我们有下面的几个比较重要的误差公式:
- 输出层误差: δ L = ∇ a C ⊙ σ ′ ( z L ) \displaystyle\delta^L=\nabla_a C\odot\sigma'(z^L) δL=∇aC⊙σ′(zL) (也就是对 a a a求偏导,而不是对 z z z)
- 相邻层误差关系: δ l = ( w l + 1 ) T δ l + 1 ⊙ σ ′ ( z l ) \displaystyle\delta^l=(w^{l+1})^T\delta^{l+1}\odot\sigma'(z^l) δl=(wl+1)Tδl+1⊙σ′(zl)(含义是第 l l l层的误差分量会扩散到第 l + 1 l+1 l+1层的不同神经元去,所以自然也可以由第 l + 1 l+1 l+1层的误差反推出来)
- 代价函数关于⽹络中任意偏置的改变率: ∂ C ∂ b l = δ l \displaystyle\frac{\partial C}{\partial b^l}=\delta^l ∂bl∂C=δl
- 代价函数关于任何⼀个权重的改变率: ∂ C ∂ w j k l = a k l − 1 δ j l \displaystyle\frac{\partial C}{\partial w^l_{jk}}=a_k^{l-1}\delta^l_j ∂wjkl∂C=akl−1δjl
显然,当输⼊神经元激活值很低,或者输出神经元已经饱和了(过⾼或者过低的激活值),权重会学习缓慢。
我们已经做好了介绍反向传播算法的准备工作。反向传播算法其实就是通过计算偏导数来调整代价的方法。为此,我们把算法描述出来:
- 输⼊ x x x:为输⼊层设置对应的激活值 a 1 a^1 a1
- 前向传播:对每个 l = 2 , 3 , . . . , L l = 2, 3, ..., L l=2,3,...,L,计算相应的 z l = w l a l − 1 + b l z^l = w^l a^{l−1} + b^l zl=wlal−1+bl 和 a l = σ ( z l ) a^l = \sigma(z^l) al=σ(zl)
- 输出层误差 δ L \delta^L δL :计算向量 δ L = ∂ a C ⋅ σ ′ ( z L ) \delta^L = \partial_a C\cdot \sigma'(z^L) δL=∂aC⋅σ′(zL)
- 反向误差传播:对每个 l = L − 1 , L − 2 , . . . , 2 l = L − 1, L − 2, ..., 2 l=L−1,L−2,...,2,计算 δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l ) \delta^l = ((w^{l+1})^T \delta^{l+1})\odot \sigma'(z^l) δl=((wl+1)Tδl+1)⊙σ′(zl)
- 输出:代价函数的梯度由 ∂ C ∂ w j k l = a k l − 1 σ j l \frac{\partial C}{\partial w_{jk}^l}= a_k^{l−1}\sigma_j^l ∂wjkl∂C=akl−1σjl 和 ∂ C ∂ b j l = δ j l \frac{\partial C}{\partial b_j^l}=\delta_j^l ∂bjl∂C=δjl 得出
问题2.2:如何使用梯度完成整个学习算法?
首先,我们随机选取样本量大小为 m m m的mini-batch来执行下面算法。然后重复循环迭代直到所有样本训练完成。
- 输入训练样本
- 对每个训练样本x,完成上面计算梯度的步骤2-4并得到 δ x , l \delta^{x,l} δx,l
- 更新权重
w
l
w^l
wl和偏置
b
l
b^l
bl
w l = w l − η m ∑ x δ x , l ( a x , l − 1 ) T b l = b l − η m ∑ x δ x , l w^l = w^l - \frac{\eta}{m}\sum_x\delta^{x,l}(a^{x,l-1})^T \\ b^l = b^l - \frac{\eta}{m}\sum_x\delta^{x,l} wl=wl−mηx∑δx,l(ax,l−1)Tbl=bl−mηx∑δx,l
问题2.3:反向传播算法究竟干了什么事情?
其实,反向传播研究了一个在权重或者偏置上的微小变化如何影响最后的输出这么一件事情。其中因为网络是层层相连的,所以,微积分的各个项就是在微小的影响这最终的结果。
从反向传播算法来看,其应用了动态规划的思想,把正向计算能够得到的结果给保存起来,然后用空间换时间的思路将整个反向传播算法计算完全。所以是一种很聪明的方法。
备注:由上面的两章内容可以看出来,激活函数的选择其实和代价函数并无直接联系,可能还是由于经验看出来选择某个激活函数匹配某个代价函数更为合适把。