下文将简单介绍训练卷积神经网络中使用到的权重初始化、梯度下降优化器的选择及计算原理、常用的正则化方法、超参数的调节。
1. 权重初始化
权重初始化是训练人工神经网络很重要的一部分。有一种想法是:由于我们知道能通过梯度下降反向传播来优化、更新权重,只要经过大量训练总能找到合适的权重,其实不然。假若同一层所有神经元都初始化为同一个常数,那么同一层所有神经元的前向推断和反向传播会完全相同,这样就导致隐含层中只有一个节点起作用,同一层里其他节点行为都完全相同。这样导致隐含层中无论含有多少神经元都是学习到同一个特征和只含有一个神经元没有任何区别。因此多层神经网络不能将权重初始化为同一个数,否则就无法打破对称性。假若初始化为符合标准正态分布的随机数并进行幅度缩放,如果缩放幅度过小或过大,在较深的神经网络中都会出现梯度消失无法更新优化模型。因此就需要使用与输入维度挂钩的惩罚系数(如Xavier、He init)来进行幅度缩放,来解决缩放幅度大小带来的梯度消失的问题。
2. 梯度下降优化器
权重优化的策略就是根据前向传播计算的的损失函数,进行反向传播求出损失函数针对每一个权重的梯度,再以一定的学习率更新权重一步步优化权重。
最简单的随机梯度优化器(SGD)就是求得一批数据的损失函数,再求得这一批数据损失函数对应每一个权重的梯度,让权重按照梯度的反方向变化来优化权重。但这种传统的随机梯度下降优化器存在一个缺点,这种优化方法会让权重在梯度较大的方向进行震荡,可能会被困在局部鞍点,而且这个缺点无法单纯的通过减小学习率来解决。为解决这个问题后来就引入了动量,引入动量之后每次权重更新不止考虑当前梯度方向,还会考虑前一次权重优化的方向。正是有了动量权重就不会在梯度大的方向进行震荡,这是因为震荡中每次更新梯度方向都相反,会与上一次更新的动量抵消,动量在其中起到了平滑作用能够在更好的方向上更新权重。
引入动量后SGD优化方向
在原先引入动量的SGD上可以稍作改进,不求当前的梯度,而是假设按照速度方向更新,求得终点处的梯度与速度方向做矢量和,以这个方向更新权重,从而更早感知到最低点。这就是引入Nesterov动量方法。
引入Nesterov动量后SGD优化方向
梯度下降优化器中另一个重要的参数是学习率,一个合适的学习率能够使损失函数快速收敛于一个较低的值。通常我们先使用较大的学习率再将学习率逐渐减小,这样能在前期快速降低损失函数,在后期学习率逐渐减小使权重的更新更细致,使神经网络更优秀。
3. 正则化
网络在训练过程中过分追求网络模型对训练集的贴合程度会让网络过拟合,在网络中神经元经过大量的数据训练很容易使相邻的神经元之间产生联系,然而我们希望每一个神经元都能够独当一面而不是过分的相互依赖,因此我们要使用随机失活的方法将这些神经元之间的联系强行切断,这就是Dropout正则化。网络在训练过程中,每一个batch的训练都会重新洗牌,让不同的神经元失活。这一个看似简单的技巧能够有效地防止过拟合。
神经元之间的联合适应性会被Dropout打破,正常训练过程中不同的神经元之间会产生联系相互协作,引入Dropout后这些神经元直接的依赖关系随时都有可能被抹消,这样就能使每一个神经元被迫独立出来。比如一在个识别老虎的神经网络中,有些神经元是识别尾巴,有些神经元是识别耳朵,有些神经元是识别花纹等等,不同神经元识别不同的特征,每次训练中都会随机屏蔽掉部分特征的神经元,让神经元每次都与不同的神经元协作,避免了神经元之间的过分依赖。从另一个角度来看,Dropout也起到了模型集成的效果。假若某一层存在N个神经元,每个神经元失活的概率为0.5,这样就达到了对2的N次方个模型进行集成的效果。Dropout的灵感来源于有性繁殖,细菌的分裂是无性繁殖,每一个个体都保留了上一代的全部DNA,细菌的DNA除了进行概率非常低的变异之外没有发生交叉融合。在有性繁殖中雄体和雌体经过减数分裂产生精子和卵细胞并融合在一起形成新的个体,这样基因片段就与其他的基因片段相互协作。传统的神经网络由于层叠臃肿的架构在训练集上能有不错的效果,但对于新的测试集就无法适应变化的外部环境。
使用图像增广也是解决模型过拟合的一种手段,图像增广的方法主要有水平翻转、颜色偏移、随机裁剪等。随机裁剪能够分割图像,让图像的特征出现在图片不同的位置上,从而解决了模型对于特征的空间分布的依赖。颜色偏移就是对图片的RGB通道进行主成分分析,将图片像素的颜色进行偏移或者反转,颜色偏移将图片中每一个像素都加减了同一个数,图像的矩阵虽然变化很大但是图片的语义并没有变化。
4. 超参数的选择
在神经网络的训练过程中,我们需要调节很多的超参数。在开始训练一个网络的时候我们应该遵循一个顺序:首先我们要检测初始的损失函数值,计算初始的损失函数值大致的数量级以确保神经网络没有额外的错误。第二步我们使用一个小数据集进行训练,尝试让神经网络在这个数据集上产生过拟合,如果神经网络能在小的子数据集上产生过拟合就说明神经网络在大的数据集上能够很好的完成训练任务。第三步找到一个能够使得损失函数较快下降的学习率,并随着学习轮次上升逐渐减小学习率。同时我们应当密切关注损失函数的曲线,如果损失函数开头不变然后突然下降就说明权重初始化不好,权重可能被困在局部鞍点;如果损失函数下降到某一值陷入了瓶颈不在下降,我们就应当减小学习率,让神经网络沉下心来,精耕细作。观察训练准确率和有效准确率曲线,如果两条曲线共同提高则可以增大训练轮次;如果训练准确率提高有效准确率降低就出现了过拟合,应当提前结束训练。
5. 迁移学习
机器学习中有一个很传统的观念就是:我们需要大量的数据、很强大的算力、优秀的算法我们才能训练出一个好的神经网络模型。迁移学习则打破了这种传统的观念,我们可以借助前人使用大量数据训练出来的模型,将这些模型泛化到我们自己的数据集上,借助这些模型预训练用于解决我们自己的问题。这样我们就不需要使用大量的数据来从头训练模型,只需要使用相对少量的数据来泛化。举一个简单的例子,原本VGG16是解决1000种分类问题,而我们只需要10种分类,我们就可以将VGG16的最后一层全连接层的1000个神经元改成10个神经元,冻结之前层的网络结构和权重参数。我们再用自己的数据集训练最后一层10个神经网络的权重。如果我们的数据集较大,则可以多向前训练几层,但底层模型的结构和权重还是冻结住的。迁移学习的原理可以简单理解为,利用已经训练好的预训练模型将底层冻结住的网络结构来做特征提取。但迁移学习并不是万能的,需要具体问题具体分析,2018年何恺明发表了一篇论文指出:使用预训练模型相对于随机初始化的模型可以在早期加速收敛,但随着训练轮次加深最终两个模型的最终效果相差不大。