均方差损失函数+Sigmoid激活函数
Sigmoid激活函数 σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1+e^{-z}} σ(z)=1+e−z1
- 对于Sigmoid,当𝑧的取值越来越大后,函数曲线变得越来越平缓,意味着此时的导数𝜎′(𝑧)也越来越小。同样的,当𝑧的取值越来越小时,也有这个问题。仅仅在𝑧取值为0附近时,导数𝜎′(𝑧)的取值较大。
- 均方差+Sigmoid的BP反向传播算法中,每一层向前递推都要乘以𝜎′(𝑧),得到梯度变化值。Sigmoid曲线意味着在大多数时候,梯度变化值都很小,导致𝑊, 𝑏更新到极值的速度较慢。(算法收敛速度较慢)
交叉熵损失函数+Sigmoid激活函数
CrossEntropy损失函数 J ( W , b , a , y ) = − [ y l n a + ( 1 − y ) l n ( 1 − a ) ] J(W,b,a,y) = - [y lna + (1-y) ln(1 -a)] J(W,b,a,y)=−[ylna+(1−y)ln(1−a)] δ L = ∂ J ( W , b , a L , y ) ∂ z L = − y 1 a L ( a L ) ( 1 − a L ) + ( 1 − y ) 1 1 − a L ( a L ) ( 1 − a L ) = a L − y \delta^L = \frac{\partial J(W,b,a^L,y)}{\partial z^L} = -y\frac{1}{a^L}(a^L)(1-a^L) + (1-y) \frac{1}{1-a^L}(a^L)(1-a^L)= a^L-y δL=∂zL∂J(W,b,aL,y)=−yaL1(aL)(1−aL)+(1−y)1−aL1(aL)(1−aL)=aL−y
- 使用交叉熵,得到的的 δ l \delta^l δl梯度表达式没有了𝜎′(𝑧),梯度为预测值和真实值的差距,这样求得的 W l , b l W^l,b^l Wl,bl的梯度也不包含𝜎′(𝑧),因此避免了反向传播收敛速度慢的问题。
对数似然损失函数和softmax激活函数
Softmax激活函数
a
i
=
e
z
i
∑
j
=
1
n
e
z
j
a_i = \frac{e^{z_i}}{\sum\limits_{j=1}^{n}e^{z_j}}
ai=j=1∑nezjezi
对数似然损失函数
J
(
W
,
b
,
a
L
,
y
)
=
−
∑
k
y
k
l
n
a
k
L
J(W,b,a^L,y) = - \sum\limits_ky_klna_k^L
J(W,b,aL,y)=−k∑yklnakL如果某一训练样本的输出为第i类,则
y
i
y_i
yi= 1,其余的𝑗≠𝑖都有
y
j
y_j
yj= 0。
J
(
W
,
b
,
a
L
,
y
)
=
−
l
n
a
i
L
J(W,b,a^L,y) = - lna_i^L
J(W,b,aL,y)=−lnaiL
∂
J
(
W
,
b
,
a
L
,
y
)
∂
w
i
j
L
=
∂
J
(
W
,
b
,
a
L
,
y
)
∂
a
i
L
∂
a
i
L
∂
z
i
L
∂
z
i
L
∂
w
i
j
L
=
(
a
i
L
−
1
)
a
j
L
−
1
\frac{\partial J(W,b,a^L,y)}{\partial w_{ij}^L}= \frac{\partial J(W,b,a^L,y)}{\partial a_i^L}\frac{\partial a_i^L}{\partial z_i^L}\frac{\partial z_i^L}{\partial w_{ij}^L}=(a_i^L -1) a_j^{L-1}
∂wijL∂J(W,b,aL,y)=∂aiL∂J(W,b,aL,y)∂ziL∂aiL∂wijL∂ziL=(aiL−1)ajL−1
∂
J
(
W
,
b
,
a
L
,
y
)
∂
b
i
L
=
a
i
L
−
1
\frac{\partial J(W,b,a^L,y)}{\partial b_i^L} = a_i^L -1
∂biL∂J(W,b,aL,y)=aiL−1
梯度爆炸梯度消失与ReLU激活函数
在反向传播算法过程中,由于使用了矩阵求导的链式法则,如果连乘的数字在每层都小于1,则梯度越往前乘越小,导致梯度消失,而如果连乘的数字在每层都大于1,则梯度越往前乘越大,导致梯度爆炸。
δ
l
=
∂
J
(
W
,
b
,
x
,
y
)
∂
z
l
=
(
∂
z
L
∂
z
L
−
1
∂
z
L
−
1
∂
z
L
−
2
.
.
.
∂
z
l
+
1
∂
z
l
)
T
∂
J
(
W
,
b
,
x
,
y
)
∂
z
L
\delta^l =\frac{\partial J(W,b,x,y)}{\partial z^l} = (\frac{\partial z^L}{\partial z^{L-1}}\frac{\partial z^{L-1}}{\partial z^{L-2}}...\frac{\partial z^{l+1}}{\partial z^{l}})^T\frac{\partial J(W,b,x,y)}{\partial z^L}
δl=∂zl∂J(W,b,x,y)=(∂zL−1∂zL∂zL−2∂zL−1...∂zl∂zl+1)T∂zL∂J(W,b,x,y)
- 如果样本导致每一层
∂
z
l
+
1
∂
z
l
\frac{\partial z^{l+1}}{\partial z^{l}}
∂zl∂zl+1都小于1,则随着反向传播的进行,
δ
l
\delta^l
δl会随着层数越来越小,甚至接近于0,导致梯度几乎消失,进而导致前面隐藏层的𝑊, 𝑏参数随着迭代的进行,几乎没有大的改变,不能收敛。这个问题目前没有完美的解决办法。
- 一个可能部分解决梯度消失问题的办法是使用ReLU(Rectified Linear Unit)激活函数 σ ( z ) = m a x ( 0 , z ) \sigma(z) = max(0,z) σ(z)=max(0,z)
- 对于梯度爆炸,则一般可以通过调整DNN模型中的初始化参数得以解决。
解决方案
- 换用Relu、LeakyRelu、Elu等激活函数
- BatchNormalization
- ResNet残差结构
- LSTM结构
- 预训练加fine_tunning
每次训练一层隐藏层节点,将上一层隐藏层的输出作为输入,而本层的输出作为下一层的输入,这就是逐层预训练。 - 梯度剪切、正则
如果更新梯度时,梯度超过了这个阈值,那么就将其强制限制在这个范围之内。这样可以防止梯度爆炸。
DNN其他激活函数
- tanh:sigmoid的变种
t
a
n
h
(
z
)
=
e
z
−
e
−
z
e
z
+
e
−
z
tanh(z) = \frac{e^z-e^{-z}}{e^z+e^{-z}}
tanh(z)=ez+e−zez−e−z
tanh和sigmoid对比主要的特点是:输出落在了[-1,1],这样输出可以进行标准化。同时tanh的曲线在较大时平坦的幅度没有sigmoid那么大,这样求梯度变化值有一些优势。
小结
- 如果使用sigmoid激活函数,则交叉熵损失函数一般肯定比均方差损失函数好。
- 如果是DNN用于分类,则一般在输出层使用softmax激活函数和对数似然损失函数。
- ReLU激活函数对梯度消失问题有一定程度的解决,尤其是在CNN模型中。