本文来自于网易云课堂
梯度消失和梯度爆炸
训练神经网络,尤其是深度神经网络所面临的一个问题是梯度消失(data vanishing)或梯度爆炸(exploding gradients).什么是梯度消失或梯度爆炸呢?通俗点说就是梯度很小或者梯度很大。那么怎么产生的呢?
为了解决梯度消失和梯度爆炸问题,人们提出了一个不完整的解决方案,虽然不能彻底地解决问题,但是很有用,它会帮助网络更明智的选择随机初始化权重。
为了更好的理解,先举一个权重初始化的例子。
z=w1x1+w2x2+w3x3......+wnxn
z
=
w
1
x
1
+
w
2
x
2
+
w
3
x
3
.
.
.
.
.
.
+
w
n
x
n
,这里忽略b
可以看到n越大,z就会越大,为了让z不太大,我们需要较小的
wi
w
i
,最合理的做法是将
wi
w
i
的方差设置为
1n
1
n
,n表示神经元的输入特征数量。
对于l层来说,实际上你要做的就是设置某层权重矩阵
w[l]=np.random.randn(shape)∗np.sqrt(1n[l−1])
w
[
l
]
=
n
p
.
r
a
n
d
o
m
.
r
a
n
d
n
(
s
h
a
p
e
)
∗
n
p
.
s
q
r
t
(
1
n
[
l
−
1
]
)
,如果你使用的激活函数是Relu时,设置方差为
2n
2
n
会更好,此时,
g[l](z)=Relu(z)
g
[
l
]
(
z
)
=
R
e
l
u
(
z
)
如果激活函数的输入特征被零均值,且标准方差为1,那么z也会调整到相似的范围,这虽然没解决问题,但它的确降低了梯度消失和爆炸问题,因为它给权重矩阵设置了合理值。
Adrew Ng还提到了其他一些激活函数,如tanh函数,设置为 np.sqrt(1n[l−1]) n p . s q r t ( 1 n [ l − 1 ] ) 的效率更高
实际上,Adrew Ng认为这些公式只是给定了一个起点,他们给出初始化权重的方差的默认值。
梯度的数值逼近
在实施backprop时,有一个测试叫做梯度检验,它的作用是确保backprop正确实施。因为有时候,你虽然写下了这些方程式却不能100%确定执行backprop的所有细节都是正确的。所以,为了逐渐实现梯度检验,我们首先说说如何对计算梯度做数值逼近。
那么如何用它来检验调试backprop的实施是否正确呢?
首先,将
W[1],b[1],W[2],b[2]...W[L],b[L]
W
[
1
]
,
b
[
1
]
,
W
[
2
]
,
b
[
2
]
.
.
.
W
[
L
]
,
b
[
L
]
连接(concatenate)并重组为一个大的向量
θ
θ
,也就是
J(W[1],b[1],W[2],b[2]...W[L],b[L])=J(θ)
J
(
W
[
1
]
,
b
[
1
]
,
W
[
2
]
,
b
[
2
]
.
.
.
W
[
L
]
,
b
[
L
]
)
=
J
(
θ
)
。
然后,将
dW[1],db[1],dW[2],db[2]...dW[L],db[L]
d
W
[
1
]
,
d
b
[
1
]
,
d
W
[
2
]
,
d
b
[
2
]
.
.
.
d
W
[
L
]
,
d
b
[
L
]
连接(concatenate)并重组为一个大的向量
dθ
d
θ
。
然后进行梯度检验:
for each i:
dθiapprox=J(θ1,θ2...θi+ϵ...)−J(θ1,θ2...θi...)2ϵ
d
θ
a
p
p
r
o
x
i
=
J
(
θ
1
,
θ
2
.
.
.
θ
i
+
ϵ
.
.
.
)
−
J
(
θ
1
,
θ
2
.
.
.
θ
i
.
.
.
)
2
ϵ
dθi=dJdθi
d
θ
i
=
d
J
d
θ
i
我们要做的就是验证
dθiapprox
d
θ
a
p
p
r
o
x
i
与
dθi
d
θ
i
是不是真的接近。
那么如何定义接近呢?
Adrew Ng通过计算他们之间的欧几里德距离并归一化来判断:
d=∥dθiapprox−dθi∥∥dθiapprox∥+∥dθi∥
d
=
‖
d
θ
a
p
p
r
o
x
i
−
d
θ
i
‖
‖
d
θ
a
p
p
r
o
x
i
‖
+
‖
d
θ
i
‖
假如说
ϵ=10−7
ϵ
=
10
−
7
,如果d比
10−7
10
−
7
小,那么这个比较好,如果
d=10−5
d
=
10
−
5
,那么可能没问题,如果
d=10−3
d
=
10
−
3
,那么就可能有bug了,这时就必须检查所有的
θ
θ
,不断的调试调试调试…来找到bug。
如何在神经网络中实施梯度检验的使用技巧和注意事项
- 不要在训练中使用梯度检验,它只用于调试。
计算 dθapprox d θ a p p r o x 是一个非常漫长的计算过程,为了实施梯度下降,你必须使用backprop来计算 dθ d θ ,只有在调试的过程中你才会计算 dθapprox d θ a p p r o x 来确认数值是否接近 dθ d θ 。如果完成,你就会关闭梯度检验,在梯度下降的每一个迭代过程中都不执行它,因为它太慢了。 - 如果算法的梯度检验失败,要检查所有项,并试着找出bug。
也就是说,如果 dθapprox d θ a p p r o x 与 dθ d θ 相差太大,我们要做的就是查找不同的I值,看看是哪个导致的 - 如果使用正则化,请记住检验时要加上正则项
- 梯度检验不能与dropout同时使用
因为每次迭代过程中,dropout会随机消除隐藏层单元的不同子集,计算dropout在梯度下降上的代价函数J是很难的。