深度学习最底层的理论,竟有些生疏了。
反向传播算法
首先是bp反向传播,其核心idea就是,从后向前,一层层的梯度传递。
高数中求偏导的时候就有个链式法则,对所有路径的偏导乘积求和,就是该参数的偏导
bp算法就是通过自后向前的偏导计算,避免了重复的计算。每一个节点的偏导值,都可以在前一级的偏导计算中用到
下面举个简单反向传播的直链例子:
ω
\omega
ω、
b
b
b是参数,
h
h
h是隐含层神经元激活后的值,
f
f
f是激活函数。
g
i
g_i
gi我把它叫做梯度参数,每次更新和缓存的也是这个。
且很容易推得
g
i
=
g
i
+
1
⋅
ω
i
+
1
⋅
f
′
(
ω
i
h
i
+
b
i
)
g_i=g_{i+1}\cdot\omega_{i+1}\cdot f^\prime(\omega_ih_i+b_i)
gi=gi+1⋅ωi+1⋅f′(ωihi+bi)
其中 ω i + 1 ⋅ f ′ ( ω i h i + b i ) \omega_{i+1}\cdot f^\prime(\omega_ih_i+b_i) ωi+1⋅f′(ωihi+bi)决定了BP过程的梯度传递和更新,太小会发生梯度消失,太大会造成梯度爆炸,因为这种传播经过若干层后,会指数级的变化。
而对某个参数 ω i \omega_i ωi的偏导还与激活值 h i h_i hi有关,等于 g i h i g_ih_i gihi
推广到DNN中,传播无非是多个支路的求和,一样的是从之前缓存的梯度系数,计算该节点的梯度,以及参数g缓存下来。
直观的图示可以参见知乎的这个如何直观地解释 backpropagation 算法? - YE Y的回答 - 知乎
梯度消失/爆炸
再回顾一下梯度消失与爆炸的根本原因,上面说了是和 ω i + 1 ⋅ f ′ ( ω i h i + b i ) \omega_{i+1}\cdot f^\prime(\omega_ih_i+b_i) ωi+1⋅f′(ωihi+bi)项直接相关的。
sigmoid的导数是限制在[0, 1/4],当它接近0时,有可能指数效应引起梯度消失
w参数初始化一般较小,但如果模值大于1了,很有可能引发梯度过大,爆炸,NaN
解决梯度消失爆炸的方法有很多,比如激活函数的改进,改进
f
′
f^\prime
f′:
比如BN层,改变
ω
\omega
ω的分布,可以防止爆炸(参见我的另一篇博客:BN浅析及用法)
ResNet为什么work
ResNet的残差结构,让模型一直处在一个最优的学习状态(激活值都更接近0,易学习)
我之前的理解是,乍一看,似乎是可以解决,至少是缓解了梯度消失
但是现在都是合理的初始化、BN层以及ReLu,梯度消失本不是个问题,这点kaiming大神在ResNet论文中introduction也提到了
(有意思的是,我后来看了DenseNet的论文,该文作者认为ResNet是缓解了梯度消失爆炸的,因为模型越深,传播次数越多,梯度出问题的风险越大,而shotcut减短了loss的反向传播路径,较小了这种风险。所以DenseNet使用了更恐怖的稠密连接方式,最大化信息的流动过程。可参见我的这篇博文:DenseNet论文浅析与代码实现)
ResNet的真正作用还需从其他角度来理解,kaiming的一个观点是:
也就是说,即便解决了梯度消失/爆炸,也不是所有的model都很容易进行优化,随着模型加深,很容易发生degradation
ResNet就是通过残差恒等映射,只学习输入与输出之间的残差与输入间的关系,构建了一个更容易优化的模型
kaiming大神这里的意思很简单。假设目前已经达到了最优的网络状态,此时接着加深网络,model效果反而变差,如果只是学习residual mapping,则可能会将这条通路变为0,而另一条路径identity mapping变成直连的shortcut,模型仍是最优状态。而对于优化非残差结构,需要在几个堆叠的非线性层学习出一个近似恒等映射,来保证模型性能不变:
Introduction:
第三部分也有类似解释:
对于实际情况,虽然不可能完全是0,但是即便是近似恒等,shortcut也使得这一学习过程变得简单了:
(不过,这种解释有个疑问是,这样能解释残差结构不会使模型发生degradation现象,无法说明网络堆的深了效果变好了……)
这两个解释暂时没搞懂啥意思
似乎有点道理: