Tips for training DNN
一个困境
得到一个DNN的步骤:
- 设定 F u n c t i o n S e t Function\ Set Function Set
- 设定 L o s s F u n c t i o n Loss\ Function Loss Function
- 找到最好的函数
但容易出现一个问题:
如果 F u n c t i o n Function Function在 T r a i n i n g D a t a Training\ Data Training Data上表现不好,我们会重新调整 F u n c t i o n Function Function,直至其表现好为止
如果 F u n c t i o n Function Function又在 T e s t i n g D a t a Testing\ Data Testing Data上表现不好,这就是 O v e r f i t t i n g Overfitting Overfitting,这个时候就要再次调整 F u n c t i o n Function Function
但这样一来, F u n c t i o n Function Function又可能在 T r a i n i n g D a t a Training\ Data Training Data上表现不好
因此,不能总是将问题归结于
O
v
e
r
f
i
t
t
i
n
g
Overfitting
Overfitting,既要看
T
r
a
i
n
i
n
g
D
a
t
a
Training\ Data
Training Data也要看
T
e
s
t
i
n
g
D
a
t
a
Testing\ Data
Testing Data,如果
T
r
a
i
n
i
n
g
D
a
t
a
Training\ Data
Training Data表现也不好并且DNN本身就很深,这就说明是没训练好。
可能的原因:
- 局部最小(local minima)
- 鞍点(saddle point)
- 停滞(plateau)
我们有很多解决 T r a i n i n g D a t a Training\ Data Training Data和 T e s t i n g D a t a Testing\ Data Testing Data表现差的方法。
在 T r a i n i n g D a t a Training\ Data Training Data上表现差
换激活函数(New activation function)
例子:在MNIST上的网络,如果用
s
i
g
m
o
i
d
sigmoid
sigmoid激活函数,则当层数越多时,效果反而越差!
原因:梯度弥散(Vanishing Gradient Problem):在靠近input的部分梯度较小,在远离input的地方,梯度较大。因此,靠近input的参数更新慢、收敛也慢,远离input的参数更新快、收敛得也很早。
一个直观的感受:在input位加上一个
△
w
△w
△w,这个影响会随着深度的加深越来越小。因此,我们需要一个不会衰减
△
w
△w
△w的方法。
ReLU
ReLu函数就是一个解决方案,有一下理由:
- 计算快速: a < 0 a<0 a<0时 σ ( z ) = 0 σ(z)=0 σ(z)=0, a > 0 a>0 a>0时 σ ( z ) = z σ(z)=z σ(z)=z
- 有生物学基础:来源于神经元细胞的特性,能量不足时就不激活
- 等同于无穷多层的偏差不同的sigmoid函数叠加的结果
-
能解决Vanishing Gradient Problem
如图所示,如果某个数据为0,那么它对DNN将无贡献,就把它从DNN中去除。剩下的就是个线性函数。
问题:如果网络都用ReLU了,网络变成了线性的了?那NN的效果不会变得很差吗?这与我们使用深层网络的初衷不是违背了吗?
答:其实使用ReLU的NN整体还是非线性的。当每个神经元的操作域(operation region)是想相同的时,它是线性的。即当你对input只做小小的改变,不改变神经元的操作域,那NN就是线性的;但如果对input做比较大的改变,改变了神经元的操作域,这样NN就是非线性的了。
问题:ReLU不能微分呀?怎么做梯度下降呀?
答:当x>0时,ReLU微分就是1,当x<0时,ReLU微分就是0。而x的值一般不太可能恰好是0,所以不在意x=0时的微分值也没问题。
ReLu的变形:当
a
<
0
a<0
a<0时
σ
(
z
)
σ(z)
σ(z)可以适当改变,有助于更新。如下图:
Maxout
Maxout是另一种解决方案。基本流程:
- 将每个数据乘上一个系数,结果相加,得到更多的数据。
- 将新的数据分组, n ( n ≥ 2 ) n(n\geq2) n(n≥2)个一组,每组选出一个最大的数据。
- 重复1、2步骤
下图为两个数据,
n
=
2
n=2
n=2的情况。
同时,ReLU是Maxout的一种特殊情况,因为Maxout本质上是将几个线性函数组合一下,ReLU显然就是两根线性函数的组合,即:折线函数。
当然,Maxout还能做到更多。
Maxout的训练也很直观,直接训练拿掉了未被选中的neuron后的”瘦长“网络就可以。不用担心这样会造成那些为被选中的neuron的参数无法被训练到,因为其实你每次输入的训练数据不同时,被选中的neuron也不同,所以终究而言,所有的neuron都是能被训练到的。
自适应学习率(Adaptive Learning Rate)
Adagrad:
w
t
+
1
←
w
t
−
η
∑
i
=
0
t
g
i
2
w_{t+1}\leftarrow w_t-\frac{η}{\sqrt{\sum_{i=0}^{t}g_i^2}}
wt+1←wt−∑i=0tgi2
η。思想是:对于梯度一般比较小的参数,我们给它较大的学习率;对于梯度一般比较大的参数,我们给它较小的学习率。
这当然是适合简单情况的,但实际中,常常出现一些复杂的情况。
比如下图中的”月形“的损失函数上,w1的更新我们需要它在平坦的区域给它较小的学习率,在较陡峭的地方,给它较大的学习率,即它的学习率应该是更加动态变化的,但adagrad的话只能做到单调递减的学习率。
RMSProp
RMSProp就是解决这一问题的一个方法,公式如下:
不要太担心local minima影响更新。可以这么想:每个参数出现local minima的概率为
p
p
p,一般一个模型有1000个参数,只有一起出现local minima时,参数才会停止更新。因此,遇上参数停止更新的概率为
p
1000
p^{1000}
p1000,是很小的。
Momentum
Momentum从物理的惯性得到启发。参数的每次更新就是加上一个向量
v
v
v,在简单的Gradient Descent中,
v
v
v只由梯度决定。但在Momentum中,之前的更新会作为“惯性”继续影响着后续的更新,但“惯性”会逐渐减小。
Adam
Adam就是RMSProp和Momentum的结合了。
在 T e s t i n g D a t a Testing\ Data Testing Data上表现差
早停法(Early Stopping)
为了防止
O
v
e
r
f
i
t
t
i
n
g
Overfitting
Overfitting的产生,我们应该把训练停在测试集损失最小的位置。但这要求知道测试集上的损失变化情况,所以我们常常用验证集来代替。
正则化(Regularization)
将Loss Function加工一下:
对其进行微分,得到新的迭代式:
因为
(
1
−
η
λ
)
<
1
(1-ηλ )<1
(1−ηλ)<1,所以每一次更新都会使参数衰减一点。
由于这里的的参数是平方之后加入到Loss Function里的,所以称为L2 regularization。
同理,还有L1 regularization。
我们可以看到L1与L2作参数更新时的差别:L1是每次参数多减去一个固定值,而L2是每次对参数进行乘以一个小于1的正值的衰减,因此L1最后会得到比较多的0值(更稀疏),而L2会得到比较多的较小但非0的值。
Dropout
训练过程中,每一次更新参数前,我们对网络中的每个神经元做一次sampling,即令每个神经元有
p
%
p\%
p%的概率被丢弃掉,然后只更新余下的神经元的参数。
但是,在Testing的时候不做Dropout,并对所有参数乘以
1
−
p
%
1-p\%
1−p%。
这是因为用dropout训练时,期望每次会有
p
%
p\%
p%的神经元未得到训练。而在测试集上,每次都是所有的神经元都参与了工作,所以在计算z值时,会是原来训练时的
1
1
−
p
%
\frac{1}{1-p\% }
1−p%1倍,因此需要在测试时乘以
1
−
p
%
1-p\%
1−p%。
Dropout通常很有效,Dropout是一种极致的ensemble。
因为每次用一个minibatch的数据对NN进行训练时,由于dropout,每次都相当于训练了一个新结构的网络,那么当我们整个NN中有M个神经元时,我们最多可以训练处2M2M个可能的网络,而最终测试时,也就相当于这些网络合力给出结果。
也不用担心说一个网络只用一个batch来训练,效果会不会很差,因为神经元的参数是共享的,大家其实可以整体看做还是在合力使得彼此的能力都变得更强。
那么按理来说,我们如果这样做ensemble,最后应该把所有的网络都输入测试数据x,再取所有输出的平均作为结果,但是因为网络数量太多,这样做不太实际。而神奇的就是:当我们把所有的网络参数乘以(100-p)%,然后把测试数据x输入到原本的网络中,它的输出结果就和ensemble的结果很接近!!!