一、概述
这一集讲了一些列不同的梯度下降算法,做了一些比较。
之后,讲到了Dropout
机制,随机关闭一些neuron
的训练方式可以使整个模型更加有效。
然后讲到了一点关于Model Ensemble
的技巧。
最后,做了一个Convnet
的引入,介绍了Convnet
的历史起源,以及后人的一些成就。
二、梯度下降算法
- SGD
SGD
(Stochastic Gradient Descent
)就是之前一直在用的这种更新Weight
的方式。如图。 现实当中,sgd
是最慢的下降算法。先来看看问题所在。如图。 假设loss function
映射成是一个垂直面上很深,但是水平面上很浅的地形。这样说好抽象,就想象成一个V
字形好了。现在我就在这个V
字的左半坡上。假设我往下走一步的话,我在垂直方向上下降的距离,会大于我在水平方向上前进的距离。又因为我因此,sgd
会造成如下的问题,我在下降的过程中走很多的弯路,上下上下不断调整。如下图。 而每次在水平方向上前进的距离越大,我就能越快到达那个笑脸,也就是loss
最低点。sgd
的前进路线浪费了很多时间。 - Momentum
Momentum
的方法,借用了物理中的加速度的概念。把整个loss function
想象成一个碗,一个球从一侧滑落,朝最底部的会有一个加速度和摩擦力的累加。因此,当这个球找到一个下降的方向时,速度就会累加,并越来越快。如图。 上图中,learning_rate * dx
就是标准的sgd
,是一个下降的速度,mu * v
就相当于摩擦力。因为速度不能一直累加。如果一直累加,球根本停不下来,会over shot
偏离目标。v
就是要一直累加的下降加速度,用v
去更新W
。mu
通常设置成0.5 - 0.9
之间的数值。v
通常初始化成0
。 - Nesterov Momentum 下图是一个普通的
momentum
下降。gradient step
就是learning_rate * dx
;momentum step
就是v
;因此最终这次下降的值就是两个向量和actual step
。nesterov momentum
就是在momentum
的基础上,多想一步,在momentum step
的尽头,考虑下一步该怎么走。如下图。 公式上唯一的区别就是在计算dx
的时候要计算d(x + mu * vt-1)
。因此要有一个变量保留一下上一次的速率。如下图。 将 替换成 然后进行代数运算就可以得到最后的下降公式nag
(Nesterov Accelerated Gradient
)通常比momentum
表现好一些。 - AdaGrad
adagrad
所做的就是将历史的gradient
平方都累加起来,然后在update
的阶段,按照比例来缩放一下。 这样做就好像我记录下来之前所有走过的方向,然后综合一下,往某一个方向走一步。从代码看,我走的每一步距离都是在减小的。因此adagrad
也有一个问题。 在训练大规模的神经网络的时候,因为cache
是随时间一直不断增加的,因此总有一个时刻,gradient
会是0
。这时模型就停止学习了。 为了解决这个问题,Tieleman and Hinton
提出了RMSProp
。 - RMSProp 如上图,为了避免
cache
过大,引入了一个leaky
机制,就像leaky relu
那样。这个decay_rate
能保证cache
不会一直增大,避免了模型停止学习的困境。 - Adam
Adam
的思想是将RMSprop
和momentum
结合起来。m
是momentum
的计算方式,v
是RMSProp
的计算方式。
然后在update
的时候,将两个变量代入到公式中。 以上就是常用的梯度下降算法。目前为止,表现最好的是Adam
,可以尝试使用在各种模型当中。 - 其他梯度下降算法 上图中的牛顿法,也能用于梯度下降的计算。牛顿法的还能在没有
learning_rate
的情况下最小化loss
。 大致的原理就是,我在下降的时候,如果有办法知道这个loss function
的最低点在哪,那么我就能一步就到达这个最低点了。 但是牛顿法貌似涉及整个黑赛矩阵的反转,算法复杂度十分的高。虽然有BGFS
和L-BGFS
做优化,但是在实践中使用很罕见。 - 最佳实践 在实践中,绝大多数情况下默认选择
Adam
作为梯度下降算法。 如果内存等计算资源允许做全数据集的训练(full batch updates
),可以尝试以下L-BGFS
。 同时,可以利用Model Ensemble
的原理。训练多个独立的模型,在测试阶段,取所有模型分数的平均数。 点击这里看一篇关于Model Ensemble
的文章。 同样的,取一个模型的多个checkpoint
的平均值,也能使训练结果有所提升。 最后,可以保留一份运行时的参数的平均值用于测试,往往结果比原有的参数好。操作如下图。 关于泰勒公式和牛顿法,继续查资料学习体会一下,这里还没来得及深究。
三、Learning Rate的选择
几乎所有的梯度算法都用learning_rate
做hyperparameter
。因此选择一个好的learning_rate
对于模型的训练来说很重要。
上图问,图中最好的learning_rate
是哪一个?
不要说是红色的。这个问题视具体情况而定。
在选择learning_rate
时,一开始选择一个高数值的lr
。可以看到high learning rate
的曲线可以使loss
急速下降,但是之后就到达一个瓶颈。
然后,运用下图的几种方法之一,来不断削减lr
,再不断进行训练。
四、Dropout
Dropout
指的是,在forward pass
的过程当中,设置一个二进制的开关(就是随机一个数字,然后和一个门槛做比较),以这样的方式,随机选择一些neuron
将其值设置为0
,也就是将其关闭或者说成丢弃dropout
。
实现方式如下。
- Dropout的好处 做了
Dropout
之后,首先可以避免模型的overfitting
,因为每次dropout
之后,模型的参数都变少了,参数越少,overfitting
的可能性越低。 其次,dropout
能让模型有冗余的能力。这个是我翻译的,比较抽象。存储中有冗余代表数据更加安全,神经网络中有冗余,应该代表着神经网络的能力越强大。用下图说明。 上图中,如果没有dropout
的时候,模型有所有的5
个参数作为判断这张图片是否是猫的依据,然后打分。如果使用了dropout
,意味着有随机的几个参数会被丢弃(置为0
),这里是有3
个参数被丢弃了,那么这个模型只能依赖2
个参数来判断这张图片是否是猫。 如果模型能够在这样的参数很少的苛刻的情况下训练,并且做出正确的判断。那么这个模型在测试的时候的能力,肯定是高于没有dropout
的模型的。 另外,使用dropout
就是在使用model ensemble
。每一次dropout
,就训练了一个sub neural network
,这些子神经网络都共享着一份参数W
。如下图。 - 测试阶段 在测试阶段的时候,最好能够整合所有的噪音(这点没有懂诶,什么是噪音…),在随机
dropout
掉一些neuron
之后多次进行forward pass
,最后求出所有预测的平均值。 也可以不使用dropout
了,直接全开neuron
,然后只做一次forward pass
,然后求所有预测的平均值。如下图。 - Dropout注意事项 如上图,假设这个三个节点的模型设置了有
%50
的neuron
会被dropout
,那么在训练阶段有dropout
的一个输出x
,和测试阶段没有dropout
的输出x
会是什么关系? 答案是,测试阶段的x
会是训练阶段x
的两倍左右。如下图。 代码实现如下,可以在测试(predict
)的时候,将两个参数H1
和H2
减半,才能得到和训练阶段一样的输出。 可以像上图一样,在训练阶段dropout
,在测试阶段做scale
,将输出减半。 更加常用的是invert dropout
,如下图。 在训练阶段将输出除以dropout
的概率,测试阶段保持不变。
五、Convolutional Neural Network
- 历史
convnet
起源于1959
年,Hubel & Wiesel
这两人在研究猫的大脑神经对特定图像的反应。 点这里看这个实验的油管视频~ 他们发现猫的大脑对图像在特定朝向上,神经元会被激活。 基于此他们建立了视觉区域中的位置和大脑皮质上的神经元是有地形上的映射的理论。 又基于这个理论,他们创建了视觉神经成像的层级关系。 成像,是从简单到复杂逐级深入的。 - 前期工作
convnet
最早期的工作,是Fukushima
于1980年做出的。他的工作建立在Hubel & Wiesel
的理论之上。 他建立一个称为Neurocognitron
的神经网络,当时还没有backprop
的技术,只有forward pass
。 直到1998年的时候,LeCun, Bottou, Bengio, Haffner
开始了带有backprop
的convnet
。 2012年的时候,Alex Krizhevsky, Sutskever, Hinton
,创建了Deep Convolutional Neural Networks
。Alexnet
与前人的不同在于,拥有了更大的数据集,并且使用了GPU
计算,但是在网络架构方面,没有太大的差别。