「机器学习-李宏毅」:Tips for Deep Learning
这篇文章中,详尽阐述了在训练Deep Neural Network时,改善performance的一些tips。
tips从Training和Testing两个方面展开。
在Training中结果不尽人意时,可以采取更换新的activation function(如ReLu,Maxout等)和采用Adaptive Learning Rate的GradientDescent算法(除了Adagrad,还有RMSprop、Momentum、Adam等)。
当在Training中得到好的performance,但在testing中perform bad时,即遇到了overfitting,又该怎么处理呢?文章后半部分详尽介绍了EarlyStopping、Regularization和Dropout三个solution。
Recipe of Deep Learning
Deep Learning 的三个步骤:

JGW8js.md.png
如果在Training Data中没有得到好的结果,需要重新训练Neural Network。
如果在Training Data中得到好的结果,在Testing Data(这里的Testing Data是指有Label的Data,比如Kaggle的Public Data或者是从Training Data中划分出的Development Data)没有得到的好的结果,说明Overfitting了,需要重新设计Neural Network的结构。
Do not always blame Overfitting

JGW3cj.md.png
如果在Testing Data中,看到上图,20-layer的error小,56-layer的error大,56-layer一定overfitting了。
No!!!不要总把原因归咎于Overfitting。

JGW13Q.md.png
再看Testing Data error之前,先看看Training Data的error。上图中,56-layer的DNN在Training Data的error本来就比20-layer的大,说明56-layer的DNN根本没有train好。
所以56-layer的DNN在Testing Data上的error大,原因不是overfitting,而是模型根本没有train好。
注: Overfitting是在Training Data上error小,但在Testing Data上的error大。
因此,对于在Training Data上得到不好的结果和在Training Data上得到好的结果但在Testing Data上得到不好的结果这两种情况,需要不同的解决方法。
Bad Results on Training Data
在不重新设计DNN结构时,如果在Training Data中得到Bad Results,一般有两种方法来改进结果:
- New activation function【neuron换新的激活函数】
- Adaptive Learning Rate
New activation function
Vanishing Gradient Problem

JGWl9g.md.png
上图表示,在手写数字辨识中,Deeper layers并不能有好的performance。
为什么会这样呢?
因为出现了Vanishing Gradient Problem,即gradient随着deeper layer逐渐消失的问题。

JGWM4S.md.png
上图中,假设neuron的activation function是sigmod函数。
靠近Input layer层的参数的变化对Loss的影响很小,所以对Loss function做微分,gradient很小,参数更新慢。
而靠近Output layer层的参数的编号对Loss的影响更大,所以对Loss function做微分,gradient很大,参数更新快。
因为靠近Output Layer层的参数更新快,所以很快converge(收敛、趋于稳定);但靠近Input Layer层的参数更新慢,几乎还处在random(随机)的状态。
当靠近Output Layer层的参数趋于稳定时,由于靠近Output Layer层的参数对Loss影响大,所以观察到的Loss的值也趋于稳定,于是,你就把training停掉了。
但是,靠近Input层的参数几乎处在random状态,所以拿模型用在Testing Data上,发现结果几乎是随机的。
怎么直观理解靠近Input Layer的参数的gradient小呢?
用微分的直观含义来表示gradient :
当 w 增加 \Delta{w} 时,如果 l 的变化 \Delta{l} 变化大,说明 \partial{l}/\partial{w} 大,否则 \partial{l}/\partial{w} 小。

JGWKN8.md.png
我们在DNN中使用的activation function是sigmod函数,sigmod函数会把值压到0和1之间。
因此,上图中,其他值不变,只有连接 x_N 的参数 w 增加 \Delta w 时,输入通过neuron的sigmod函数,函数的输出增加的 \Delta 会变小,随着Deeper Layer,neuron的输出的 \Delta 会越变越小,趋至0。
最后DNN输出的变化对 loss的影响小,即 \Delta{l} 趋至0,即参数的gradient \partial{l}/\partial{w} 趋至0。(即 Vanishing Gradient)
ReLu :Rectified Linear Unit
为了防止发生Vanishing Gradient Problem,在DNN中选择使用新的activation function。
ReLu长下面这个样子:

JGWuAf.md.png
z: input
a: output
当 z\leq0 时, a=0 ;当 z >0 时, a=z 。
Reason :
- Fast to compute
- Biological reason【有生物上的原因】
- Infinite sigmod with different biases. 【是无穷个 有不同bias的sigmod函数 的叠加】
- Vanishing gradient problem 【最重要的是没有vanishing gradient problem】
为什么ReLu没有vanishing gradient problem

JGWmHP.md.png
上图DNN中,ReLu在输入是负数时,输出是0。因此这些输出是0的neuron可以去掉。
就变成了下图这个A Thinner linear network。由于ReLu函数的性质,靠近Input Layer的参数不会有smaller gradient。

JGWeBt.md.png
这里有一个Q&A:
Q1: function变成linear的,会不会DNN就变弱了?
: 当neuron的operation region不变的话,DNN的确是linear的,但是当neuron的operation region改变后,就是unlinear的。
:即,当input的变化小,operation region不变(即输入不会从大于0变成小于0,小于0变成大于0这种),model还是linear的;但当input的变化大时,很多neuron的operation region都变化了,model其实就是unlinear的。
Q2: ReLu 怎么微分?
:ReLu在0点不可微,那就随便指定为0这样(台湾腔QAQ)。
ReLu - variant
当 z\leq 0 时,输出为0,就不能更新参数了。于是就有下图变体:

JGWZnI.md.png
当 z\leq0 时,gradient都为0.01,为什么不能是其他值。于是就有下图变体:其中 \alpha 也是一个需要学习的参数
Maxout
Maxout,如下图,在设计neural network时,会给每一层的neuron分组,成为一个新的neuron。

JGWk1H.md.png
Maxout也是一个Learnable activation function。
ReLu是Maxout学出来的一个特例。

JGWAcd.md.png
上图中,左图是ReLu。 ReLu的输入 z = wx+b ,输出 a 如上图的绿色的线。
右图是Maxout。Maxout的输入 z_1 =wx+b,z_2=0 ,那么输出取max,输出 a 如上图中绿色的线,和左图的ReLu相同。
Maxout is more than ReLu。
当参数更新时,Maxout的函数图像如下图:

JGWPhD.md.png
DNN中的参数是learnable的,所以Maxout也是一个learnable的activation function。
Reason :
Learnable activation function [Ian J. Goodfellow, ICML’13]
Activation function in maxout network can be any piecewise linear convex function.
在maxout神经网络中的激活函数可以是任意的分段凸函数。
How many pieces depending on how many elements in a group.
分段函数分几段取决于一组中有多少个元素。
JGWCtO.md.png
Maxout : how to train
Given a training data x, we know which z would be the max.
【当给出每笔training data时,我们能知道Maxout neuron中哪一个最大】

JGW9AK.md.png
如上图,在这笔training data x中,我们只train this thin and linear network 的参数,即max z相连的参数。
每笔不同的training data x,会得到不同的thin and linear network,最后,会train到每一个参数。
Adaptive Learning Rate
Review Adagrad
在这篇文章: Gradient 第一小节讲到一种adaptive learning rate的gradient 算法:Adagrad 算法。在那篇文章中,我们得出的结论是 the best step \propto |First dertivative| / Second derivative.

JGWF9e.md.png
在上图中,两个方向,因为蓝色方向的二阶微分更小,所以蓝色方向应该有更大的learning rate。
因此,在Adagrad中,我们用一阶微分来估量二阶微分的大小:
w^{t+1} \leftarrow w^{t}-\frac{\eta}{\sqrt{\sum_{i=0}^{t}\left(g^{i}\right)^{2}}} g^{t}RMSProp
但是,在训练NN时,Error Surface(Total Loss对参数的变化)的图像可能会更复杂,如下图:

JGWS76.md.png
因为函数图像过于复杂,可能在同一方向的不同位置,也需要有不同的learning rate。
RMSProp是Adagrad的进阶版。
RMSProp过程:
- w^{1} \leftarrow w^{0}-\frac{\eta}{\sigma^{0}} g^{0} \quad \sigma^{0}=g^{0}
- w^{2} \leftarrow w^{1}-\frac{\eta}{\sigma^{1}} g^{1} \quad \sigma^{1}=\sqrt{\alpha (\sigma^{0})^2+(1-\alpha)(g^1)^2}
- w^{3} \leftarrow w^{2}-\frac{\eta}{\sigma^{2}} g^{2} \quad \sigma^{2}=\sqrt{\alpha (\sigma^{1})^2+(1-\alpha)(g^2)^2}
…
- w^{t+1} \leftarrow w^{t}-\frac{\eta}{\sigma^{t}} g^{t} \quad \sigma^{t}=\sqrt{\alpha (\sigma^{t-1})^2+(1-\alpha)(g^t)^2}
\sigma^t 也是在算gradients的 root mean squar。
但是在RMSProp中,加入了参数 \alpha (需要手动调节大小的参数),可以给当前算出来的gradient g^t 更大的权重,即更相信现在gradient的方向,不那么相信以前gradient的方向。
Momentum
Momentum,则是引用物理中的惯性。

JGRxn1.md.png
上图中,当小球到达local minima时,会因为惯性继续往前更新,则有可能到达minima的位置。
这里的Momentum,就代指上一次前进(参数更新)的方向。
Vanilla Gradient Descent
如果将Gradient的步骤画出图来,就是下图这样:

JGRXc9.md.png
过程:
Start at position \theta^0
Compute gradietn at \theta^0
Move to \theta^1=\theta^0-\eta\nabla{L(\theta^0)}
Compute gradietn at \theta^1
Move to \theta^2=\theta^1-\eta\nabla{L(\theta^1)}
… …Stop until \nabla{L(\theta^t)}\approx0
Momentum
在Momentum中,参数更新方向是当前Gradient方向和Momentum方向(上一次更新方向)的叠加。

JGRjXR.md.png
Movement方向:上一次更新方向 - 当前gradient方向。
过程:
Start at position \theta^0
Movement: v^0=0
Compute gradient at \theta^0
Movement v^1=\lambda v^0-\eta\nabla{L(\theta^0)}
Move to \theta^1=\theta^0+v^1
Compute gradient at \theta^1
Movement v^2=\lambda v^1-\eta\nabla{L(\theta^1)}
Move to \theta^2=\theta^1+v^2
… …Stop until \nabla{L(\theta^t)}\approx0
和Vanilla Gradient Descent比较,v^i 其实是过去gradient( \nabla{L(\theta^0)} 、\nabla{L(\theta^1)} 、… 、 \nabla{L(\theta^{i-1})} )的加权和。
- 迭代过程:
- v^0=0
- v^1=-\eta\nabla{L(\theta^0)}
- v^2=-\lambda\eta\nabla{L(\theta^0)}-\eta\nabla{L(\theta^1)}
- …
再用那个小球的例子来直觉的解释Momentum:

JGRO1J.md.png
当小球在local minima时,gradient为0,但是Momentum(即上次移动方向)是继续往前,于是小球可以继续向前更新。
Adam = RMSProp + Momentum

JGRLp4.md.png
Algorithm:Adam, our proposed algorithm for stochastic optimization.
【Adam,是为了优化stochastic gradient】(至于什么是stochastic gradient,建议戳Post not found: Gradietn 这篇)
g_t^2 indicates the elementwise square g_t\odot g_t .
【g_t^2 是gradient g_t 向量和 g_t 的元素乘】
Good default settings for the tested machine learning problems are \alpha=0.001 , \beta_1=0.9 , \beta_2=0.999 and \epsilon=10^{-8} . All operations on vectors are element-wise. With \beta_1^t and \beta_2^t we denote \beta_1 and \beta_2 to the power t.
【参数说明:算法默认的参数设置是 \alpha=0.001 , \beta_1=0.9 , \beta_2=0.999 , \epsilon=10^{-8} 。算法中所有vector之间的操作都是对元素操作。 \beta_1^t 和 \beta_2^t 是 \beta_1 和 \beta_2 的 t 次幂】
Adam Pseudo Code:
Require:\alpha : Stepsize 【步长/learning rate \eta 】
Require:\beta_1,\beta_2\in\left[0,1\right) : Exponential decay rates for the moment estimates.
Require:f(\theta) : Stochastic objective function with parameters \theta .【参数 \theta 的损失函数】
Require: \theta_0 :Initial parameter vector 【初值】
m_0\longleftarrow 0 (Initial 1st moment vector) 【 m 是Momentum算法中的更新参数后的方向 v 】
v_0\longleftarrow 0 (Initial 2nd moment vector) 【 v 是RMSprop算法中gradient的root mean square \sigma 】
t\longleftarrow 0 (Initial timestep) 【更新次数】
while \theta_t not concerged do 【当 \theta 趋于稳定,即 \nabla{f(\theta)}\approx0 时】
t\longleftarrow t+1
- g_t\longleftarrow \nabla{f_t(\theta_{t-1})} (Get gradients w.r.t. stochastic objective at timestep t)
【算第t次时 \theta 的gradient】
- m_{t} \leftarrow \beta_{1} \cdot m_{t-1}+\left(1-\beta_{1}\right) \cdot g_{t} (Update biased first momen t estimate)
【用Momentum算更新方向】
- v_{t} \leftarrow \beta_{2} \cdot v_{t-1}+\left(1-\beta_{2}\right) \cdot g_{t}^{2} (Update biased second raw moment estimate)
【RMSprop估测最佳步长( 和v 负相关) 】
- \widehat{m}_{t} \leftarrow m_{t} /\left(1-\beta_{1}^{t}\right) (Comppute bbi. as-corrected first momen t estima te)
【算出来的值有bias,论文中有具体解释为什么有。当更新次数增加时, 1-\beta_1^t 也趋近于1】
- \widehat{v}_{t} \leftarrow v_{t} /\left(1-\beta_{2}^{t}\right) (Compute bias-corrected second raw momen t estimate)
【和上同理】
- \theta_{t} \leftarrow \theta_{t-1}-\alpha \cdot \widehat{m}_{t} /(\sqrt{\widehat{v}_{t}}+\epsilon) (Update parameters)
【 $\widehat{m}t 相当于是更准确的gradient的方向,\sqrt{\widehat{v}{t}}+\epsilon$ 是为了估测最好的步长,调节learning rate】
Gradient Descent Limitation?
在Gradient这篇文章中,讲到过Gradient有一些问题不能处理:
- Stuck at local minima
- Stuck at saddle point
- Very slow at the plateau

JG4l9O.md.png
(李老师说的,不是我说的QAQ):但是Andrew(吴恩达)在2017年说过,不用太担心这个问题。为什么呢?
如果要stuck at local minima,前提是每一维度都是local minima。
如果在一个维度遇到local minima的概率是p,当NN很复杂时,有很多参数时,比如1000,那么遇到local minima的概率是 p^{1000} ,趋近于0了,几乎不会发生。
:所以不用太担心Gradient Descent的局限性。
Bad Results on Testing Data
Early Stopping
在更新参数时,可能会出现这样曲线图:

JGRbhF.md.png
图中,Total Loss在training set中逐渐减小,但在validation set中逐渐增大。
而我们真正关心的其实是validation set的Loss。
所以想让参数停在validation set中loss最低时。
Keras能够实现EarlyStopping功能[1]:click here
1 | from keras.callbacks import EarlyStopping |
Regularization
Regularization:Find a set of weight not only minimizing original cost but also close to zero.
构造一个新的loss function,除了最小化原来的loss function,还能使得参数趋紧0,使得function更平滑。
function的曲线更平滑,当输入有轻微扰动,不会太影响输出的结果。
L2 norm regularization
New loss function:
\begin{equation} \begin{aligned} \mathrm{L}^{\prime}(\theta)&=L(\theta)+\lambda \frac{1}{2}\|\theta\|_{2} \\ \theta &={w_1,w_2,...} \\ \|\theta\|_2&=(w1)^2+(w_2)^2+... \end{aligned} \end{equation}其中用第二范式 \lambda\frac{1}{2}|\theta|_2 作为regularization term。做regularization是为了使函数更平滑,所以一般不考虑bias)
New gradient:
\frac{\partial \mathrm{L}^{\prime}}{\partial w}=\frac{\partial \mathrm{L}}{\partial w}+\lambda wNew update:
\begin{equation} \begin{aligned} w^{t+1} &\longrightarrow w^{t}-\eta \frac{\partial \mathrm{L}^{\prime}}{\partial w} \\ &=w^{t}-\eta\left(\frac{\partial \mathrm{L}}{\partial w}+\lambda w^{t}\right) \\ &=(1-\eta \lambda) w^{t}-\eta \frac{\partial \mathrm{L}}{\partial w} \end{aligned} \end{equation}在更新参数时,先乘一个 (1-\eta\lambda) ,再更新。
weight decay(权值衰减):由于 \eta,\lambda 都是很小的值,所以 w^t 每次都会先乘一个小于1的数,即逐渐趋于0,实现regularization。但是,因为更新中还有gradient部分,所以不会等于0。
L1 norm regularization
Regularization除了用第二范式,还可以用其他的,比如第一范式 |\theta|_1=|w_1|+|w_2|+…
New loss function:
\begin{equation}\begin{aligned}\mathrm{L}^{\prime}(\theta)&=L(\theta)+\lambda \frac{1}{2}\|\theta\|_1\\ \theta &={w_1,w_2,...} \\ \|\theta\|_1&=|w_1|+|w_2|+...\end{aligned}\end{equation}用sgn()符号函数来表示绝对值的求导。
符号函数:Sgn(number)
如果number 大于0,返回1;等于0,返回0;小于0,返回-1。
New gradient:
\frac{\partial \mathrm{L}^{\prime}}{\partial w}=\frac{\partial \mathrm{L}}{\partial w}+\lambda \text{sgn}(w)New update:
\begin{equation} \begin{aligned} w^{t+1} &\longrightarrow w^{t}-\eta \frac{\partial \mathrm{L}^{\prime}}{\partial w} \\ &=w^{t}-\eta\left(\frac{\partial \mathrm{L}}{\partial w}+\lambda \text{sgn}(w^t)\right) \\ &=w^{t}-\eta \frac{\partial \mathrm{L}}{\partial w}-\eta \lambda \operatorname{sgn}\left(w^{t}\right) \end{aligned} \end{equation}在用第一范式做regularization时,每次 w^t 都要减一个值 \eta\lambda\text{sgn}(w^t) ,和用第二范式做regularization比较,后者每次都要乘一个小于1的值,即使是乘0.99,w下降也很快。
Weight decay(权值衰减)的生物意义:
Our brain prunes(修剪) out the useless link between neurons.
JGRHtU.md.png
Dropout
Wiki: Dropout是Google提出的一种正则化技术,用以在人工神经网络中对抗过拟合。Dropout有效的原因,是它能够避免在训练数据上产生复杂的相互适应。Dropout这个术语代指在神经网络中丢弃部分神经元(包括隐藏神经元和可见神经元)。在训练阶段,dropout使得每次只有部分网络结构得到更新,因而是一种高效的神经网络模型平均化的方法。[2]
这里讲Dropout怎么做。
Training

JG4M4K.md.png
Each time before updating the parameters:
Each neuron has p% to dropout. Using the new thin network for training.
【如上图,每个neuron有p的概率被dropout。于是NN就变成了下图thinner的NN】
JGR5mq.md.png
For each mini-batch, we resample the dropout neurons.
【每次mini-batch,都要重新dropout,更新NN的结构】
Testing
Testing中不做dropout
If the dropout rate at training is p%, all the weights times 1-p%.
【如果在training中 dropout rate是 p%,在testing是,每个参数都乘 (1-p%)】
【比如dropout rate 是0.5。如果train出来的w是 1,那么testing中 w=0.5】
Why dropout in training:Intuitive Reason
这是一个比较有趣的比喻:
JGRI00.md.png
这也是一个有趣的比喻hhh:
JGRo7V.md.png
即,团队合作的时候,如果每个人都认为队友在带我,那每个人都可能划水。
但是,(training中)如果你知道你的队友在划水,那你可能会做的更好。
但是,(testing中)发现每个人都有更好地做,都没有划水,那么结果就会很好。
(hhhh,李老师每次讲Intuitive Reason的时候,都觉得好有道理hhh,科学的直觉orz给我也整一个)
Why multiply (1-p%) in testing: Intuitive reason
为什么在testing中 weights要乘(1-p%)?
用一个具体的例子来直观说明:

JGRf6s.md.png
上图中,如果dropout rate=0.5,假设只训练一次, w_2,w_4 相连的neuron都被dropout。
在testing中,因为不对neurondropout,所以如果不改变weight,计算出的结果 z’\approx 2z 。
因此将所有weight简单地和(1-p%) 相乘,能尽量保证计算出的结果 z’\approx z 。
Dropout is a kind of ensemble
Ensemble(合奏),如下图,将testing data丢给train好的NN来估计,最后的估计值取所有NN输出的平均,如下图:

JGRhXn.md.png
为什么说dropout is a kind of ensemble?

JGRRpQ.md.png
Using one mini-batch to train one network
【dropout相当于每次用一个mini-batch来训练一个network】
Some parameters in the network are shared
【有些参数可能会在很多个mini-batch都被train到】
由于每个神经元有 p%的概率被dropout,因此理论上,如果有M个neuron,可能会训练 2^M 个network。
但是在Ensemble中,将每个network存下来,testing的时候输出取平均,这样的过程太复杂了,结果也不一定会很好。
所以在testing中,no dropout,对原始network中的每个参数乘 (1-p%),用这样简单的操作来达到ensemble的目的。

JGRWlj.md.png
Reference
「机器学习-李宏毅」:Tips for Deep Learning
Related Issues not found
Please contact @f7ed to initialize the comment