CS231N-Lecture6 Training Neural Network part-2

一、概述

这一集讲了一些列不同的梯度下降算法,做了一些比较。

之后,讲到了Dropout机制,随机关闭一些neuron的训练方式可以使整个模型更加有效。

然后讲到了一点关于Model Ensemble的技巧。

最后,做了一个Convnet的引入,介绍了Convnet的历史起源,以及后人的一些成就。

二、梯度下降算法

  1. SGD SGD(Stochastic Gradient Descent)就是之前一直在用的这种更新Weight的方式。如图。 现实当中,sgd是最慢的下降算法。先来看看问题所在。如图。 假设loss function映射成是一个垂直面上很深,但是水平面上很浅的地形。这样说好抽象,就想象成一个V字形好了。现在我就在这个V字的左半坡上。假设我往下走一步的话,我在垂直方向上下降的距离,会大于我在水平方向上前进的距离。又因为我因此,sgd会造成如下的问题,我在下降的过程中走很多的弯路,上下上下不断调整。如下图。 而每次在水平方向上前进的距离越大,我就能越快到达那个笑脸,也就是loss最低点。sgd的前进路线浪费了很多时间。
  2. Momentum Momentum的方法,借用了物理中的加速度的概念。把整个loss function想象成一个碗,一个球从一侧滑落,朝最底部的会有一个加速度和摩擦力的累加。因此,当这个球找到一个下降的方向时,速度就会累加,并越来越快。如图。 上图中,learning_rate * dx就是标准的sgd,是一个下降的速度,mu * v就相当于摩擦力。因为速度不能一直累加。如果一直累加,球根本停不下来,会over shot偏离目标。 v就是要一直累加的下降加速度,用v去更新Wmu通常设置成0.5 - 0.9之间的数值。 v通常初始化成0
  3. Nesterov Momentum 下图是一个普通的momentum下降。 gradient step就是learning_rate * dxmomentum step就是v;因此最终这次下降的值就是两个向量和actual stepnesterov momentum就是在momentum的基础上,多想一步,在momentum step的尽头,考虑下一步该怎么走。如下图。 公式上唯一的区别就是在计算dx的时候要计算d(x + mu * vt-1)。因此要有一个变量保留一下上一次的速率。如下图。 替换成 然后进行代数运算就可以得到最后的下降公式 nag(Nesterov Accelerated Gradient)通常比momentum表现好一些。
  4. AdaGrad adagrad所做的就是将历史的gradient平方都累加起来,然后在update的阶段,按照比例来缩放一下。 这样做就好像我记录下来之前所有走过的方向,然后综合一下,往某一个方向走一步。从代码看,我走的每一步距离都是在减小的。因此adagrad也有一个问题。 在训练大规模的神经网络的时候,因为cache是随时间一直不断增加的,因此总有一个时刻,gradient会是0。这时模型就停止学习了。 为了解决这个问题,Tieleman and Hinton提出了RMSProp
  5. RMSProp 如上图,为了避免cache过大,引入了一个leaky机制,就像leaky relu那样。这个decay_rate能保证cache不会一直增大,避免了模型停止学习的困境。
  6. Adam Adam的思想是将RMSpropmomentum结合起来。 mmomentum的计算方式,vRMSProp的计算方式。
    然后在update的时候,将两个变量代入到公式中。 以上就是常用的梯度下降算法。目前为止,表现最好的是Adam,可以尝试使用在各种模型当中。
  7. 其他梯度下降算法 上图中的牛顿法,也能用于梯度下降的计算。牛顿法的还能在没有learning_rate的情况下最小化loss。 大致的原理就是,我在下降的时候,如果有办法知道这个loss function的最低点在哪,那么我就能一步就到达这个最低点了。 但是牛顿法貌似涉及整个黑赛矩阵的反转,算法复杂度十分的高。虽然有BGFSL-BGFS做优化,但是在实践中使用很罕见。
  8. 最佳实践 在实践中,绝大多数情况下默认选择Adam作为梯度下降算法。 如果内存等计算资源允许做全数据集的训练(full batch updates),可以尝试以下L-BGFS。 同时,可以利用Model Ensemble的原理。训练多个独立的模型,在测试阶段,取所有模型分数的平均数。 点击这里看一篇关于Model Ensemble的文章。 同样的,取一个模型的多个checkpoint的平均值,也能使训练结果有所提升。 最后,可以保留一份运行时的参数的平均值用于测试,往往结果比原有的参数好。操作如下图。 关于泰勒公式和牛顿法,继续查资料学习体会一下,这里还没来得及深究。

三、Learning Rate的选择

几乎所有的梯度算法都用learning_ratehyperparameter。因此选择一个好的learning_rate对于模型的训练来说很重要。

上图问,图中最好的learning_rate是哪一个?

不要说是红色的。这个问题视具体情况而定。

在选择learning_rate时,一开始选择一个高数值的lr。可以看到high learning rate的曲线可以使loss急速下降,但是之后就到达一个瓶颈。

然后,运用下图的几种方法之一,来不断削减lr,再不断进行训练。

四、Dropout

Dropout指的是,在forward pass的过程当中,设置一个二进制的开关(就是随机一个数字,然后和一个门槛做比较),以这样的方式,随机选择一些neuron将其值设置为0,也就是将其关闭或者说成丢弃dropout

实现方式如下。

  1. Dropout的好处 做了Dropout之后,首先可以避免模型的overfitting,因为每次dropout之后,模型的参数都变少了,参数越少,overfitting的可能性越低。 其次,dropout能让模型有冗余的能力。这个是我翻译的,比较抽象。存储中有冗余代表数据更加安全,神经网络中有冗余,应该代表着神经网络的能力越强大。用下图说明。 上图中,如果没有dropout的时候,模型有所有的5个参数作为判断这张图片是否是猫的依据,然后打分。如果使用了dropout,意味着有随机的几个参数会被丢弃(置为0),这里是有3个参数被丢弃了,那么这个模型只能依赖2个参数来判断这张图片是否是猫。 如果模型能够在这样的参数很少的苛刻的情况下训练,并且做出正确的判断。那么这个模型在测试的时候的能力,肯定是高于没有dropout的模型的。 另外,使用dropout就是在使用model ensemble。每一次dropout,就训练了一个sub neural network,这些子神经网络都共享着一份参数W。如下图。
  2. 测试阶段 在测试阶段的时候,最好能够整合所有的噪音(这点没有懂诶,什么是噪音…),在随机dropout掉一些neuron之后多次进行forward pass,最后求出所有预测的平均值。 也可以不使用dropout了,直接全开neuron,然后只做一次forward pass,然后求所有预测的平均值。如下图。
  3. Dropout注意事项 如上图,假设这个三个节点的模型设置了有%50neuron会被dropout,那么在训练阶段有dropout的一个输出x,和测试阶段没有dropout的输出x会是什么关系? 答案是,测试阶段的x会是训练阶段x的两倍左右。如下图。 代码实现如下,可以在测试(predict)的时候,将两个参数H1H2减半,才能得到和训练阶段一样的输出。 可以像上图一样,在训练阶段dropout,在测试阶段做scale,将输出减半。 更加常用的是invert dropout,如下图。 在训练阶段将输出除以dropout的概率,测试阶段保持不变。

五、Convolutional Neural Network

  1. 历史 convnet起源于1959年,Hubel & Wiesel这两人在研究猫的大脑神经对特定图像的反应。 点这里看这个实验的油管视频~ 他们发现猫的大脑对图像在特定朝向上,神经元会被激活。 基于此他们建立了视觉区域中的位置和大脑皮质上的神经元是有地形上的映射的理论。 又基于这个理论,他们创建了视觉神经成像的层级关系。 成像,是从简单到复杂逐级深入的。
  2. 前期工作 convnet最早期的工作,是Fukushima于1980年做出的。他的工作建立在Hubel & Wiesel的理论之上。 他建立一个称为Neurocognitron的神经网络,当时还没有backprop的技术,只有forward pass 直到1998年的时候,LeCun, Bottou, Bengio, Haffner开始了带有backpropconvnet 2012年的时候,Alex Krizhevsky, Sutskever, Hinton,创建了Deep Convolutional Neural Networks Alexnet与前人的不同在于,拥有了更大的数据集,并且使用了GPU计算,但是在网络架构方面,没有太大的差别。