目录
这节课围绕着如何加快训练速度这个现实问题,从理论上分析了学习过程中的问题,介绍了许多实践中有效的锦囊妙计。
复习
先复习一下优化理论中的几个概念。
weight space中的error surface
以误差为y轴,每个权值为x轴可以得到error surface。对square error的linear neuron 来讲,每个权值与误差的图像一定是下图这样的二次曲线:
对二维的weight space来讲,则可以做出如下碗状的“等高线”:
对多层非线性网络来讲,error surface更复杂。但只要weight不是太大,其局部都可用光滑的二次曲线来近似。
full batch learning
对二次碗状的目标函数来讲,梯度的方向大致指向最优解的方向,但椭圆越扁,偏离越多。只有在圆形时,梯度才精确地指向圆心。
梯度在正确方向的分量非常小,在与其垂直的错误方向上的分量非常大。所以对线性系统来讲,这种梯度下降不是个好主意。即便对非线性的多层神经网络来讲(哪怕其error surface整体上不是碗状),也存在这个问题。多层神经网络的error surface在一些方向上类似二次曲线,另一些方向上则不是。
学习出毛病的症状
如果学习率取得过大,权值将会在二次曲线中来回震荡。从立体的角度来讲,就是在峡谷里来回震荡。
而我们真正的目标不是在一个小区域内震荡,而是沿着峡谷下降的方向快速穿越峡谷。也就是说在梯度稳定的方向快速前进,而在梯度不稳定的方向缓慢移动。
随机梯度下降
在讲解如何达到目标之前,先看看SGD。
如果数据集中的数据高度重复,则从一半数据中得到的梯度和从另一半数据中得到的梯度几乎完全一致。这启发我们不用浪费时间在全集上算梯度,而只需在一个子集上算梯度。极端情况是只在一个实例上训练,然后马上更新权重,这被称作在线算法。通常我们不走极端,mini-batch就挺好。
mini-batch必须平衡每个类别的实例数,不然使模型产生偏见。最简单的算法是对整个数据集随机洗牌,然后从任意位置取出所需数量的实例。
太小的mini-batch也不好,因为现代硬件往往是针对矩阵运算、并行计算优化的,几个标量就丢过来算一通有点大材小用。
两种学习算法
全量梯度算法可以套用很多现有的非线性函数优化算法,但多层神经网络并不是现有算法的典型适用对象,所以还需要很多修改。
而如果数据集重复度很高,则mini-batch几乎是首选。如果要使用一些高级的优化算法,batch size必须大一点,不过这对现代硬件来讲没什么压力就是了。
基本的mini-batch梯度下降算法
-
猜一个初始学习率,如果误差变坏或反复震荡则减小学习率;如果误差稳定缓慢下降,则增大学习率。
-
把这种思路写成一个小的控制程序。
-
而在训练快结束的时候几乎每次都应该减小学习率,这样可以减小多个mini-batch切换带来的震荡。
-
在误差停止减小的时候减小学习率(误差由验证集得到)
mini-batch的锦囊妙计
权值初始化
如果两个单元的进出权值和bias都是相同的,则两者将得到相同的梯度。那它们其实是同一个feature detector,无法学习不同的feature。所以在初始化的时候要赋予不同的随机值,破坏这种对称性。
经验法则与CS229介绍的类似:http://www.hankcs.com/ml/neural-networks-learning-cs229.html#h3-5。原来出度和入度的黑话叫fan啊。
改变输入的均值
通过改变输入的每个维度的均值,比如加上一个常量,使均值为0会带来意想不到的惊喜。比如如下例子:
均值改变前error surface是很扁的椭圆,其中红绿两条线分别是两个训练case的weight vector,从数值上看两个weight很相似,所以两条直线几乎平行,它们之间夹着的区域非常小。
而将每个维度都减去100,则得到很漂亮的圆形,夹着的区域变大了。
除了输入外,激活函数也有讲究。双曲线切线$y=\tanh(x)$也能产生均值大约为0的激活值,从这点来看比logistic函数要好.
缩放输入
也就是同时乘以某个值,将方差调整为1。
从error surface上来看,与调整均值有类似的效果。
更彻底的方法
去掉输入维度之间的相关性,比如PCA之类的方法。PCA好处有两个:1、降维。2、把剩下的维度除以特征向量的平方根,对线性神经元来讲会得到圆形的error surface。
知识共享署名-非商业性使用-相同方式共享:码农场 » Hinton神经网络公开课6 Optimization: How to make the learning go faster