机器学习基础随笔(10)

本文探讨了深度学习中的优化技巧,包括如何在训练集和测试集上提升模型性能。针对训练集表现不佳,介绍了ReLU和Maxout等新型激活函数,以及Adagrad、RMSProp、Momentum和Adam等自适应学习率方法。对于测试集表现不佳,提出了早停法和正则化策略,如L1和L2正则化。文章强调不要一味归咎于过拟合,而应根据问题选择合适的方法。
摘要由CSDN通过智能技术生成

Tips for Deep Learning

本文会顺带解决CNN部分的两个问题:
1、max pooling架构中用到的max无法微分,那在gradient descent的时候该如何处理?
2、L1 的Regression到底是什么东西

本文的主要思路:针对training set和testing set上的performance分别提出针对性的解决方法
1、在training set上准确率不高:
new activation function:ReLU、Maxout
adaptive learning rate:Adagrad、RMSProp、Momentum、Adam
2、在testing set上准确率不高:Early Stopping、Regularization or Dropout

Recipe of Deep Learning

three step of deep learning

Recipe,配方、秘诀,这里指的是做deep learning的流程应该是什么样子

我们都已经知道了deep learning的三个步骤

  • define the function set(network structure)
  • goodness of function(loss function – cross entropy)
  • pick the best function(gradient descent – optimization)

做完这些事情以后,你会得到一个更好的neural network,那接下来你要做什么事情呢?

Good Results on Training Data?

你要做的第一件事是,提高model在training set上的正确率

先检查training set的performance其实是deep learning一个非常unique的地方,如果今天你用的是k-nearest neighbor或decision tree这类非deep learning的方法,做完以后你其实会不太想检查training set的结果,因为在training set上的performance正确率就是100,没有什么好检查的

有人说deep learning的model里这么多参数,感觉一脸很容易overfitting的样子,但实际上这个deep learning的方法,它才不容易overfitting,我们说的overfitting就是在training set上performance很好,但在testing set上performance没有那么好;只有像k nearest neighbor,decision tree这类方法,它们在training set上正确率都是100,这才是非常容易overfitting的,而对deep learning来说,overfitting往往不会是你遇到的第一个问题

因为你在training的时候,deep learning并不是像k nearest neighbor这种方法一样,一训练就可以得到非常好的正确率,它有可能在training set上根本没有办法给你一个好的正确率,所以,这个时候你要回头去检查在前面的step里面要做什么样的修改,好让你在training set上可以得到比较高的正确率

Good Results on Testing Data?

接下来你要做的事是,提高model在testing set上的正确率

假设现在你已经在training set上得到好的performance了,那接下来就把model apply到testing set上,我们最后真正关心的,是testing set上的performance,假如得到的结果不好,这个情况下发生的才是Overfitting,也就是在training set上得到好的结果,却在testing set上得到不好的结果

那你要回过头去做一些事情,试着解决overfitting,但有时候你加了新的technique,想要overcome overfitting这个problem的时候,其实反而会让training set上的结果变坏;所以你在做完这一步的修改以后,要先回头去检查新的model在training set上的结果,如果这个结果变坏的话,你就要从头对network training的process做一些调整,那如果你同时在training set还有testing set上都得到好结果的话,你就成功了,最后就可以把你的系统真正用在application上面了

Do not always blame overfitting

不要看到所有不好的performance就归责于overfitting

先看右边testing data的图,横坐标是model做gradient descent所update的次数,纵坐标则是error rate(越低说明model表现得越好),黄线表示的是20层的neural network,红色表示56层的neural network

你会发现,这个56层network的error rate比较高,它的performance比较差,而20层network的performance则是比较好的,有些人看到这个图,就会马上得到一个结论:56层的network参数太多了,56层果然没有必要,这个是overfitting。但是,真的是这样子吗?

你在说结果是overfitting之前,有检查过training set上的performance吗?对neural network来说,在training set上得到的结果很可能会像左边training error的图,也就是说,20层的network本来就要比56层的network表现得更好,所以testing set得到的结果并不能说明56层的case就是发生了overfitting

在做neural network training的时候,有太多太多的问题可以让你的training set表现的不好,比如说我们有local minimum的问题,有saddle point的问题,有plateau的问题…所以这个56层的neural network,有可能在train的时候就卡在了一个local minimum的地方,于是得到了一个差的参数,但这并不是overfitting,而是在training的时候就没有train好

有人认为这个问题叫做underfitting,但我的理解上,underfitting的本意应该是指这个model的complexity不足,这个model的参数不够多,所以它的能力不足以解出这个问题;但这个56层的network,它的参数是比20层的network要来得多的,所以它明明有能力比20层的network要做的更好,却没有得到理想的结果,这种情况不应该被称为underfitting,其实就只是没有train好而已

conclusion

当你在deep learning的文献上看到某种方法的时候,永远要想一下,这个方法是要解决什么样的问题,因为在deep learning里面,有两个问题:

  • 在training set上的performance不够好
  • 在testing set上的performance不够好

当只有一个方法propose(提出)的时候,它往往只针对这两个问题的其中一个来做处理,举例来说,deep learning有一个很潮的方法叫做dropout,那很多人就会说,哦,这么潮的方法,所以今天只要看到performance不好,我就去用dropout;但是,其实只有在testing的结果不好的时候,才可以去apply dropout,如果你今天的问题只是training的结果不好,那你去apply dropout,只会越train越差而已

所以,你必须要先想清楚现在的问题到底是什么,然后再根据这个问题去找针对性的方法,而不是病急乱投医,甚至是盲目诊断

下面我们分别从Training data和Testing data两个问题出发,来讲述一些针对性优化的方法

Good Results on Training Data?

这一部分主要讲述如何在Training data上得到更好的performance,分为两个模块,New activation function和Adaptive Learning Rate

New activation function

这个部分主要讲述的是关于Recipe of Deep Learning中New activation function的一些理论

activation function

如果你今天的training结果不好,很有可能是因为你的network架构设计得不好。举例来说,可能你用的activation function是对training比较不利的,那你就尝试着换一些新的activation function,也许可以带来比较好的结果

在1980年代,比较常用的activation function是sigmoid function,如果现在我们使用sigmoid function,你会发现deeper不一定imply better,下图是在MNIST手写数字识别上的结果,当layer越来越多的时候,accuracy一开始持平,后来就掉下去了,在layer是9层、10层的时候,整个结果就崩溃了;但注意!9层、10层的情况并不能被认为是因为参数太多而导致overfitting,实际上这张图就只是training set的结果,你都不知道testing的情况,又哪来的overfitting之说呢?

Vanishing Gradient Problem

上面这个问题的原因不是overfitting,而是Vanishing Gradient(梯度消失),解释如下:

当你把network叠得很深的时候,在靠近input的地方,这些参数的gradient(即对最后loss function的微分)是比较小的;而在比较靠近output的地方,它对loss的微分值会是比较大的

因此当你设定同样learning rate的时候,靠近input的地方,它参数的update是很慢的;而靠近output的地方,它参数的update是比较快的

所以在靠近input的地方,参数几乎还是random的时候,output就已经根据这些random的结果找到了一个local minima,然后就converge(收敛)了

这个时候你会发现,参数的loss下降的速度变得很慢,你就会觉得gradient已经接近于0了,于是把程序停掉了,由于这个converge,是几乎base on random的参数,所以model的参数并没有被训练充分,那在training data上得到的结果肯定是很差的

为什么会有这个现象发生呢?如果你自己把Backpropagation的式子写出来的话,就可以很轻易地发现用sigmoid function会导致这件事情的发生;但是,我们今天不看Backpropagation的式子,其实从直觉上来想你也可以了解这件事情发生的原因

某一个参数 w w w对total cost l l l的偏微分,即gradient ∂ l ∂ w \frac{\partial l}{\partial w} wl,它直觉的意思是说,当我今天把这个参数做小小的变化的时候,它对这个cost的影响有多大;那我们就把第一个layer里的某一个参数 w w w加上 Δ w \Delta w Δw,看看对network的output和target之间的loss有什么样的影响

Δ w \Delta w Δw通过sigmoid function之后,得到output是会变小的,改变某一个参数的weight,会对某个neuron的output值产生影响,但是这个影响是会随着层数的递增而衰减的,sigmoid function的形状如下所示,它会把负无穷大到正无穷大之间的值都硬压到0~1之间,把较大的input压缩成较小的output

因此即使 Δ w \Delta w Δw值很大,但每经过一个sigmoid function就会被缩小一次,所以network越深, Δ w \Delta w Δw被衰减的次数就越多,直到最后,它对output的影响就是比较小的,相应的也导致input对loss的影响会比较小,于是靠近input的那些weight对loss的gradient ∂ l ∂ w \frac{\partial l}{\partial w} wl远小于靠近output的gradient

那怎么解决这个问题呢?比较早年的做法是去train RBM,它的精神就是,先把第一个layer train好,再去train第二个,然后再第三个...所以最后你在做Backpropagation的时候,尽管第一个layer几乎没有被train到,但一开始在做pre-train的时候就已经把它给train好了,这样RBM就可以在一定程度上解决问题

但其实改一下activation function可能就可以handle这个问题了

ReLU
introduction

现在比较常用的activation function叫做Rectified Linear Unit(整流线性单元函数,又称修正线性单元),它的缩写是ReLU,该函数形状如下图所示,z为input,a为output,如果input>0则output = input,如果input<0则output = 0

选择ReLU的理由如下:
  • 跟sigmoid function比起来,ReLU的运算快很多
  • ReLU的想法结合了生物上的观察( Pengel的paper )
  • 无穷多bias不同的sigmoid function叠加的结果会变成ReLU
  • ReLU可以处理Vanishing gradient的问题( the most important thing )
handle Vanishing gradient problem

下图是ReLU的neural network,以ReLU作为activation function的neuron,它的output要么等于0,要么等于input

当output=input的时候,这个activation function就是linear的;而output=0的neuron对整个network是没有任何作用的,因此可以把它们从network中拿掉

拿掉所有output为0的neuron后如下图所示,此时整个network就变成了一个瘦长的**linear** network,linear的好处是,output=input,不会像sigmoid function一样使input产生的影响逐层递减

Q:这里就会有一个问题,我们之所以使用deep learning,就是因为想要一个non-linear、比较复杂的function,而使用ReLU不就会让它变成一个linear function吗?这样得到的function不是会变得很弱吗?

A:其实,使用ReLU之后的network整体来说还是non-linear的,如果你对input做小小的改变,不改变neuron的operation region的话,那network就是一个linear function;但是,如果你对input做比较大的改变,导致neuron的operation region被改变的话,比如从output=0转变到了output=input,network整体上就变成了non-linear function

注:这里的region是指input z<0和input z>0的两个范围

Q:还有另外一个问题,我们对loss function做gradient descent,要求neural network是可以做微分的,但ReLU是一个分段函数,它是不能微分的(至少在z=0这个点是不可微的),那该怎么办呢?

A:在实际操作上,当region的范围处于z>0时,微分值gradient就是1;当region的范围处于z<0时,微分值gradient就是0;当z为0时,就不要管它,相当于把它从network里面拿掉

ReLU-variant

其实ReLU还存在一定的问题,比如当input<0的时候,output=0,此时微分值gradient也为0,你就没有办法去update参数了,所以我们应该让input<0的时候,微分后还能有一点点的值,比如令 a = 0.01 z a=0.01z a=0.01z,这个东西就叫做Leaky ReLU

既然a可以等于0.01z,那这个z的系数可不可以是0.07、0.08之类呢?所以就有人提出了**Parametric ReLU**,也就是令$a=\alpha \cdot z$,其中$\alpha$并不是固定的值,而是network的一个参数,它可以通过training data学出来,甚至每个neuron都可以有不同的$\alpha$值

这个时候又有人想,为什么一定要是ReLU这样子呢,activation function可不可以有别的样子呢?所以后来有了一个更进阶的想法,叫做Maxout network

Maxout
introduction

Maxout的想法是,让network自动去学习它的activation function,那Maxout network就可以自动学出ReLU,也可以学出其他的activation function,这一切都是由training data来决定的

假设现在有input x 1 , x 2 x_1,x_2 x1,x2,它们乘上几组不同的weight分别得到5,7,-1,1,这些值本来是不同neuron的input,它们要通过activation function变为neuron的output;但在Maxout network里,我们事先决定好将某几个“neuron”的input分为一个group,比如5,7分为一个group,然后在这个group里选取一个最大值7作为output

这个过程就好像在一个layer上做Max Pooling一样,它和原来的network不同之处在于,它把原来几个“neuron”的input按一定规则组成了一个group,然后并没有使它们通过activation function,而是选取其中的最大值当做这几个“neuron”的output

当然,实际上原来的”neuron“早就已经不存在了,这几个被合并的“neuron”应当被看做是一个新的neuron,这个新的neuron的input是原来几个“neuron”的input组成的vector,output则取input的最大值,而并非由activation function产生

在实际操作上,几个element被分为一个group这件事情是由你自己决定的,它就是network structure里一个需要被调的参数,不一定要跟上图一样两个分为一组
Maxout -> RELU

Maxout是如何模仿出ReLU这个activation function的呢?

下图左上角是一个ReLU的neuron,它的input x会乘上neuron的weight w,再加上bias b,然后通过activation function-ReLU,得到output a

  • neuron的input为 z = w x + b z=wx+b z=wx+b,为下图左下角紫线
  • neuron的output为 a = z   ( z > 0 ) ;   a = 0   ( z < 0 ) a=z\ (z>0);\ a=0\ (z<0) a=z (z>0); a=0 (z<0),为下图左下角绿线
如果我们使用的是上图右上角所示的Maxout network,假设$z_1$的参数w和b与ReLU的参数一致,而$z_2$的参数w和b全部设为0,然后做Max Pooling,选取$z_1,z_2$较大值作为a
  • neuron的input为 [ z 1   z 2 ] \begin{bmatrix}z_1 \ z_2 \end{bmatrix} [z1 z2]
    • z 1 = w x + b z_1=wx+b z1=wx+b,为上图右下角紫线
    • z 2 = 0 z_2=0 z2=0,为上图右下角红线
  • neuron的output为 max ⁡ [ z 1   z 2 ] \max{\begin{bmatrix}z_1 \ z_2 \end{bmatrix}} max[z1 z2],为上图右下角绿线

你会发现,此时ReLU和Maxout所得到的output是一模一样的,它们是相同的activation function

Maxout -> More than ReLU

除了ReLU,Maxout还可以实现更多不同的activation function

比如 z 2 z_2 z2的参数w和b不是0,而是 w ′ , b ′ w',b' w,b,此时

  • neuron的input为 [ z 1   z 2 ] \begin{bmatrix}z_1 \ z_2 \end{bmatrix} [z1 z2]
    • z 1 = w x + b z_1=wx+b z1=wx+b,为下图右下角紫线
    • z 2 = w ′ x + b ′ z_2=w'x+b' z2=wx+b,为下图右下角红线
  • neuron的output为 max ⁡ [ z 1   z 2 ] \max{\begin{bmatrix}z_1 \ z_2 \end{bmatrix}} max[z1 z2],为下图右下角绿线
这个时候你得到的activation function的形状(绿线形状),是由network的参数$w,b,w',b'$决定的,因此它是一个**Learnable Activation Function**,具体的形状可以根据training data去generate出来
property

Maxout可以实现任何piecewise linear convex activation function(分段线性凸激活函数),其中这个activation function被分为多少段,取决于你把多少个element z放到一个group里,下图分别是2个element一组和3个element一组的activation function的不同形状

How to train Maxout

接下来我们要面对的是,怎么去train一个Maxout network,如何解决Max不能微分的问题

假设在下面的Maxout network中,红框圈起来的部分为每个neuron的output

其实Max operation就是linear的operation,只是它仅接在前面这个group里的某一个element上,因此我们可以把那些并没有被Max连接到的element通通拿掉,从而得到一个比较细长的linear network

实际上我们真正训练的并不是一个含有max函数的network,而是一个化简后如下图所示的linear network;当我们还没有真正开始训练模型的时候,此时这个network含有max函数无法微分,但是只要真的丢进去了一笔data,network就会马上根据这笔data确定具体的形状,此时max函数的问题已经被实际数据给解决了,所以我们完全可以根据这笔training data使用Backpropagation的方法去训练被network留下来的参数

所以我们担心的max函数无法微分,它只是理论上的问题;在具体的实践上,我们完全可以先根据data把max函数转化为某个具体的函数,再对这个转化后的thiner linear network进行微分

这个时候你也许会有一个问题,如果按照上面的做法,那岂不是只会train留在network里面的那些参数,剩下的参数该怎么办?那些被拿掉的直线(weight)岂不是永远也train不到了吗?

其实这也只是个理论上的问题,在实际操作上,我们之前已经提到过,每个linear network的structure都是由input的那一笔data来决定的,当你input不同data的时候,得到的network structure是不同的,留在network里面的参数也是不同的,由于我们有很多很多笔training data,所以network的structure在训练中不断地变换,实际上最后每一个weight参数都会被train到

所以,我们回到Max Pooling的问题上来,由于Max Pooling跟Maxout是一模一样的operation,既然如何训练Maxout的问题可以被解决,那训练Max Pooling又有什么困难呢?

Max Pooling有关max函数的微分问题采用跟Maxout一样的方案即可解决,至此我们已经解决了CNN部分的第一个问题

Adaptive learning rate

这个部分主要讲述的是关于Recipe of Deep Learning中Adaptive learning rate的一些理论

Review - Adagrad

我们之前已经了解过Adagrad的做法,让每一个parameter都要有不同的learning rate

Adagrad的精神是,假设我们考虑两个参数 w 1 , w 2 w_1,w_2 w1,w2,如果在 w 1 w_1 w1这个方向上,平常的gradient都比较小,那它是比较平坦的,于是就给它比较大的learning rate;反过来说,在 w 2 w_2 w2这个方向上,平常gradient都比较大,那它是比较陡峭的,于是给它比较小的learning rate

但我们实际面对的问题,很有可能远比Adagrad所能解决的问题要来的复杂,我们之前做Linear Regression的时候,我们做optimization的对象,也就是loss function,它是convex的形状;但实际上我们在做deep learning的时候,这个loss function可以是任何形状

RMSProp
learning rate

loss function可以是任何形状,对convex loss function来说,在每个方向上它会一直保持平坦或陡峭的状态,所以你只需要针对平坦的情况设置较大的learning rate,对陡峭的情况设置较小的learning rate即可

但是在下图所示的情况中,即使是在同一个方向上(如w1方向),loss function也有可能一会儿平坦一会儿陡峭,所以你要随时根据gradient的大小来快速地调整learning rate

所以真正要处理deep learning的问题,用Adagrad可能是不够的,你需要更dynamic的调整learning rate的方法,所以产生了Adagrad的进阶版——**RMSProp**

RMSprop还是一个蛮神奇的方法,因为它并不是在paper里提出来的,而是Hinton在mooc的course里面提出来的一个方法,所以需要cite(引用)的时候,要去cite Hinton的课程链接

how to do RMSProp

RMSProp的做法如下:

我们的learning rate依旧设置为一个固定的值 η \eta η 除掉一个变化的值 σ \sigma σ,这个 σ \sigma σ等于上一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值