李宏毅机器学习(10)

Tips for training DNN

一个困境

得到一个DNN的步骤:

  1. 设定 F u n c t i o n   S e t Function\ Set Function Set
  2. 设定 L o s s   F u n c t i o n Loss\ Function Loss Function
  3. 找到最好的函数

但容易出现一个问题:

如果 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上表现不好

李宏毅机器学习(10)
因此,不能总是将问题归结于 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)
    李宏毅机器学习(10)
    我们有很多解决 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表现差的方法。
    李宏毅机器学习(10)

在 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激活函数,则当层数越多时,效果反而越差!
李宏毅机器学习(10)
原因:梯度弥散(Vanishing Gradient Problem):在靠近input的部分梯度较小,在远离input的地方,梯度较大。因此,靠近input的参数更新慢、收敛也慢,远离input的参数更新快、收敛得也很早。
李宏毅机器学习(10)
一个直观的感受:在input位加上一个 △ w △w △w,这个影响会随着深度的加深越来越小。因此,我们需要一个不会衰减 △ w △w △w的方法。
李宏毅机器学习(10)

ReLU

李宏毅机器学习(10)
ReLu函数就是一个解决方案,有一下理由:

  1. 计算快速: a < 0 a<0 a<0时 σ ( z ) = 0 σ(z)=0 σ(z)=0, a > 0 a>0 a>0时 σ ( z ) = z σ(z)=z σ(z)=z
  2. 有生物学基础:来源于神经元细胞的特性,能量不足时就不激活
  3. 等同于无穷多层的偏差不同的sigmoid函数叠加的结果
  4. 能解决Vanishing Gradient Problem
    李宏毅机器学习(10)
    李宏毅机器学习(10)

如图所示,如果某个数据为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)可以适当改变,有助于更新。如下图:
李宏毅机器学习(10)

Maxout

Maxout是另一种解决方案。基本流程:

  1. 将每个数据乘上一个系数,结果相加,得到更多的数据。
  2. 将新的数据分组, n ( n ≥ 2 ) n(n\geq2) n(n≥2)个一组,每组选出一个最大的数据。
  3. 重复1、2步骤

下图为两个数据, n = 2 n=2 n=2的情况。
李宏毅机器学习(10)
同时,ReLUMaxout的一种特殊情况,因为Maxout本质上是将几个线性函数组合一下,ReLU显然就是两根线性函数的组合,即:折线函数。
李宏毅机器学习(10)
当然,Maxout还能做到更多。
李宏毅机器学习(10)
Maxout的训练也很直观,直接训练拿掉了未被选中的neuron后的”瘦长“网络就可以。不用担心这样会造成那些为被选中的neuron的参数无法被训练到,因为其实你每次输入的训练数据不同时,被选中的neuron也不同,所以终究而言,所有的neuron都是能被训练到的。
李宏毅机器学习(10)

自适应学习率(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=0t​gi2​ ​η​。思想是:对于梯度一般比较小的参数,我们给它较大的学习率;对于梯度一般比较大的参数,我们给它较小的学习率。
这当然是适合简单情况的,但实际中,常常出现一些复杂的情况。
比如下图中的”月形“的损失函数上,w1的更新我们需要它在平坦的区域给它较小的学习率,在较陡峭的地方,给它较大的学习率,即它的学习率应该是更加动态变化的,但adagrad的话只能做到单调递减的学习率。
李宏毅机器学习(10)

RMSProp

RMSProp就是解决这一问题的一个方法,公式如下:
李宏毅机器学习(10)
不要太担心local minima影响更新。可以这么想:每个参数出现local minima的概率为 p p p,一般一个模型有1000个参数,只有一起出现local minima时,参数才会停止更新。因此,遇上参数停止更新的概率为 p 1000 p^{1000} p1000,是很小的。
李宏毅机器学习(10)

Momentum

Momentum从物理的惯性得到启发。参数的每次更新就是加上一个向量 v v v,在简单的Gradient Descent中, v v v只由梯度决定。但在Momentum中,之前的更新会作为“惯性”继续影响着后续的更新,但“惯性”会逐渐减小。
李宏毅机器学习(10)

Adam

Adam就是RMSPropMomentum的结合了。
李宏毅机器学习(10)

在 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的产生,我们应该把训练停在测试集损失最小的位置。但这要求知道测试集上的损失变化情况,所以我们常常用验证集来代替。
李宏毅机器学习(10)

正则化(Regularization)

将Loss Function加工一下:
李宏毅机器学习(10)
对其进行微分,得到新的迭代式:
李宏毅机器学习(10)
因为 ( 1 − η λ ) < 1 (1-ηλ )<1 (1−ηλ)<1,所以每一次更新都会使参数衰减一点。
由于这里的的参数是平方之后加入到Loss Function里的,所以称为L2 regularization。
同理,还有L1 regularization。
李宏毅机器学习(10)
我们可以看到L1与L2作参数更新时的差别:L1是每次参数多减去一个固定值,而L2是每次对参数进行乘以一个小于1的正值的衰减,因此L1最后会得到比较多的0值(更稀疏),而L2会得到比较多的较小但非0的值。

Dropout

训练过程中,每一次更新参数前,我们对网络中的每个神经元做一次sampling,即令每个神经元有 p % p\% p%的概率被丢弃掉,然后只更新余下的神经元的参数。
李宏毅机器学习(10)
李宏毅机器学习(10)
但是,在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%。
李宏毅机器学习(10)
Dropout通常很有效,Dropout是一种极致的ensemble。
李宏毅机器学习(10)
李宏毅机器学习(10)
因为每次用一个minibatch的数据对NN进行训练时,由于dropout,每次都相当于训练了一个新结构的网络,那么当我们整个NN中有M个神经元时,我们最多可以训练处2M2M个可能的网络,而最终测试时,也就相当于这些网络合力给出结果。

也不用担心说一个网络只用一个batch来训练,效果会不会很差,因为神经元的参数是共享的,大家其实可以整体看做还是在合力使得彼此的能力都变得更强。
李宏毅机器学习(10)
那么按理来说,我们如果这样做ensemble,最后应该把所有的网络都输入测试数据x,再取所有输出的平均作为结果,但是因为网络数量太多,这样做不太实际。而神奇的就是:当我们把所有的网络参数乘以(100-p)%,然后把测试数据x输入到原本的网络中,它的输出结果就和ensemble的结果很接近!!!
李宏毅机器学习(10)

上一篇:shell编程_反引号


下一篇:golang的testing包使用