1. 优化:
1.1 随机梯度下降法(Stochasitc Gradient Decent, SGD)的问题:
1)对于condition number(Hessian矩阵最大和最小的奇异值的比值)很大的loss function,一个方向梯度变化明显,另一个方向梯度变化很缓慢,SGD在优化过程中会震荡着下降,导致优化很慢。深度学习的网络会有上百万甚至更多的参数需要优化,在这个上百万维的空间里,更容易出现各个维度梯度变化差别很大的问题。
2)陷落在局部最小点或者鞍点(saddle point)。鞍点一个方向梯度下降,另一个方向梯度上升。对于上百万参数的深度学习,鞍点是更不愿意看到的,因为总是有一些参数的梯度是上升,另一些是下降,或者说鞍点是很常见的。而局部最小点还相对可以接受,因为它至少保证了在各个维度上,都没办法在小范围内使得结果更好。
3)由于计算所有样本的梯度再取平均太费时了,所以一般是计算一个batch的梯度,但这导致了我们得到的梯度只是真正想要的梯度的夹杂了噪音的小样本估计,这使得梯度下降的轨迹扭来扭曲,优化过程变慢。
1.2.SGD的改进:
SGD+Momentum:SGD是直接用梯度更新参数 xt+1 = xt - α▽f(xt),而Momentum的方法是用梯度构造速度 vt+1 = ρvt + ▽f(xt),然后用速度来更新参数 xt+1 = xt - αvt+1。ρ可以看成是摩擦力的影响,一般取0.9、0.99等。上一次的速度在摩擦力的影响下衰减了一部分,然后再和当前速度加权求和。这可以解决SGD的三个问题,对于局部最小点和鞍点,即使梯度降为0,依然有上一次的速度可以让优化继续往前迭代。
Nesterov Momentum:xt+1 = xt + vt+1 + ρ(vt+1 - vt)。直观地解释是,增加了一项调整速度。
AdaGrad:对优化得到的梯度在不同维度的平方求和,更新的时候除以这一项。直观地解释是梯度大的维度除以大的数,梯度小的维度除以小的数,所以解决了condition number大的问题。在深度学习中用的不多。
RMSProp:对AdaGrad的改进,在平方求和时增加了decay项。
Adam:综合了Momentum和AdaGrad/RMSProp两类方法。这是最好的,可以作为深度学习的默认优化方法。
这几种方法都需要learning rate作为超参数。Learning rate最好是越来越小的,有不同的decay的方式。Learning rate的decay也是超参数,最开始调教神经网络的时候,不用管decay,learning rate测试差不多了,再加入decay。
1.3 二阶优化方法:
之前的优化方法都是一阶的,二阶的方法比如高斯牛顿法,有个很大的好处是不需要设定learning rate(有时候也会设定一个学习率)。对于深度学习的不利因素是,Hessian的逆矩阵求解太费时。改进的方法是Quasi-Newton methods(BGFS最流行)、L-BFGS(Limited memory BFGS),主要改进的点都是求解Hessian的逆。L-BFGS对full batch表现的很不错,对于深度学习的mini-batch表现不太好,如何把L-BFGS用到深度学习是个研究方向。
总结:Adam是很好的默认选择,如果可以full batch则尝试L-BFGS。
2 让模型更好地泛化
2.1. Model ensembles:选择各种不同的模型,各自训练出一个结果,然后取所有模型的平均值。这种方法可以提高2%左右的准确度。
也有新的paper(Huang et al, "Snapshot ensembles: train 1, get M for free". ICLR 2017)提出只用一个模型,但是记录下优化中途的结果,也能得到很好的结果。
Polyak averaging。不常用。
2.2. 正则化:相比于Model ensembles,正则化针对单一模型。增加正则化项。
在测试阶段增加随机成分,而在测试阶段去掉随机成分。
Dropout:在前向计算时,随机的把一些神经元输出设为0。一般比例是50%。一般这种操作是在全连接层,有时也会用在卷积层。直观的解释是,这相当于用同一个模型的不同子集,所以模拟出了类似好多模型的效果。测试阶段,需要乘以dropout的比例。也有Inverted dropout的改进,把比例项放进训练过程,测试阶段不需要额外的乘法。
Batch Normalization:选子集操作。
Data Augmentation:根据已有的数据生成新的数据,比如把图片颠倒、随机的截取缩放图片、调整对比度亮度等。和新想法就是:如何改变数据而不改变数据的标签。
DropConnect:dropout是扔掉神经元的输出,这里是扔掉权重。
Fractional Max Pooling:随机选择对图像哪个部分做池化。
Stachastic Depth:随机的跳过一些层。很疯狂的想法。。。
3. 迁移学习:如果数据集不大(比如少于100万),那么可以找一个有类似数据的很大的数据集,训练一个CNN,然后把结果用在自己的数据集上。现在很多算法都是先用ImageNet训练处的结果然后再做后续的操作。