深度学习中最优化问题很重要,代价也很高,因此需要开发一组专门的优化技术。
在深度学习领域,即使在数据集和模型结构完全相同的情况下,选择不同的优化算法可能导致截然不同的训练效果。
甚至相同的优化算法,但是选择了不同的参数初始化策略,也可能会导致不同的训练结果。
机器学习通常是间接的,需要优化的是测试集上的某个性能度量 。这个度量 通常很难直接求解,甚至难以直接建模优化。如:在图像目标检测问题中,常见的 就是mAP:mean average precision
。
普遍的做法是:希望通过降低代价函数 来提高 。这不同于纯粹的最小化 本身,因为最终目标是提高 。
当代价函数 最小时是否 最大?这一结论是未知的。
实际任务中,可以采用训练集上的损失函数均值作为代价函数:
其中: 为每个样本的损失函数, 为对输入 的预测输出, 是经验分布, 为标记信息。
理论上,代价函数中的期望最好取自真实的数据生成分布 ,而不是有限个训练集上对应的经验分布 。即: , 称作泛化误差。
问题是对于绝大多数问题,样本的真实分布 是未知的,仅能提供训练集中的样本的分布 。
实际应用中,使用经验分布 来代替真实分布 。这就是为什么使用 作为代价函数的原因。
最小化训练集上的期望损失称作最小化经验风险empirical risk
。其缺点是:
很容易过拟合 。
某些类型的损失函数没有导数,无法使用基于梯度下降的优化算法来优化。
如 :0-1
损失函数,导数要么为零,要么没有定义。
有时候真正的代价函数无法有效优化,此时可以考虑使用替代损失函数
来代替真实的损失函数。
如:将正类的负对数似然函数作为 0-1
损失函数的替代。
一般的优化和机器学习优化的一个重要不同:机器学习算法通常并不收敛于代价函数的局部极小值。因为:
机器学习算法通常使用替代损失函数
。
算法终止时,可能出现:采用 替代损失函数
的代价函数的导数较小,而采用真实损失函数的代价函数的导数仍然较大(相比较于0值)。
机器学习算法可能会基于早停策略而提前终止。
早停发生时,可能出现:训练集上的代价函数的导数值仍然较大(相比较于0值)。
因为早停的规则是基于验证集上代价函数的值不再下降,它并不关心训练集上代价函数的导数值。
病态ill-conditioning
的黑塞矩阵 是凸优化或者其他形式优化中普遍存在的问题。
将 在 处泰勒展开: 。其中 为 处的梯度; 为 处的海森矩阵。
根据梯度下降法: 。应用在点 ,有:
因此沿着负梯度的方向,步长 将导致代价函数 增加: 。
当 时,黑塞矩阵的病态会成为问题。此时沿着负梯度的方向,代价函数 的值反而在增长!
理论上,随着训练的推进,梯度的平方范数 应该逐步降低并最终收敛到 0 。因为代价函数 取极小值时,梯度为 0 。
实际上在很多问题中,梯度的平方范数 并不会在训练过程中显著缩小,而是随着时间的延长在增加,且并不随着训练过程收敛到临界点而减小。
下面左图为梯度的范数随着时间的变化,右图为验证集上的分类误差随着时间的变化。
这是因为 会更快速的增长(相对于 ) 。它带来两个结果:
对于非凸函数,如神经网络,可能存在多个局部极小值。实际上这并不是一个严重的问题。
如果一个训练集可以唯一确定一组模型参数,则该模型称作可辨认的identifiable
。
带有隐变量的模型通常是不可辨认的。因为可以批量交换隐变量,从而得到等价的模型。如:交换隐单元 和 的权重向量。
这种不可辨认性称作权重空间对称性weight space symmetry
。
也可以放大权重和偏置 倍,然后缩小输出 倍,从而保持模型等价。
模型可辨认性问题意味着:神经网络的代价函数具有非常多、甚至是无限多的局部极小解。
由可辨认性问题产生的局部极小解都具有相同的代价函数值,它并不是代价函数非凸性带来的问题。
如果局部极小解和全局极小解相差很大时,此时多个局部极小解会带来很大隐患。它将给基于梯度的优化算法带来很大的问题。
实际中的网络,是否存在大量严重偏离全局极小解的局部极小解、优化算法是否会遇到这些局部极小解?
这些都是未决的问题。
目前学者们猜想:对于足够大的神经网络,大部分局部极小值都具有很小的代价函数值。
是否找到全局极小值并不重要,实际上只需要在参数空间中找到一个使得损失函数很小的点。
目前很多人将神经网络优化中的所有困难都归结于局部极小值。
有一种方案是排除局部极小值导致的困难(说明是其他原因导致的困难):绘制梯度范数随着时间的变化:
神经网络训练中,通常不关注代价函数的精确全局极小值,而是关心将代价函数值下降到足够小,从而获得一个很好的泛化误差。
关于优化算法能否到达这个目标的理论分析是极其困难的。
鞍点是另一类梯度为零的点。鞍点附近的某些点的函数值比鞍点处的值更大,鞍点附近的另一些点的函数值比鞍点处的值更小。
在鞍点处,黑塞矩阵同时具有正负特征值:
通常在低维空间中,局部极小值很普遍;在高维空间中,局部极小值很少见,鞍点更常见。
对于函数 ,鞍点和局部极小值的数量之比的期望随着 呈指数级增长。
假如黑塞矩阵的特征值的正负号由抛硬币来决定的话:
当位于函数值较低的区间时,黑塞矩阵的特征值为正的可能性更大。这意味着:
鞍点对于训练算法的影响:
对于只使用了梯度的一阶优化算法而言:情况不明。
对于牛顿法而言,鞍点是个大问题。
因为梯度下降的原则是:朝着下坡路的方向移动。而牛顿法的原则是:明确寻找梯度为零的点。如果不做任何修改,则牛顿法会主动跳入一个鞍点。
也可能出现一个恒值的、平坦的宽区域:在这个区域中,梯度和黑塞矩阵都为零。
多层神经网络通常有像悬崖一样的区域,悬崖是指代价函数斜率较大的区域。
产生悬崖的原因:由于几个较大的权重相乘,导致求导的时候,其梯度异常巨大。
在RNN
网络的代价函数中悬崖结构很常见,因为RNN
这一类模型会涉及到多个时间步长中的因子的相乘,导致产生了大量的权重相乘。
悬崖的影响:在梯度更新时,如果遇到悬崖,则会导致参数更新的步长非常大(因为此时梯度非常大),从而跨了非常大的一步,使得参数弹射的非常远。这样可能会使得已经完成的大量优化工作无效。
因为当弹射非常远时,可能横跨了参数空间的很多个区域而进入到另一个区域。这样已经探索的参数区域就被放弃了。
下图是一个悬崖的例子:第二根路径就是由于遇到悬崖,导致参数更新的步长非常大。
解决悬崖问题的方案:使用梯度截断策略。
梯度下降法只是指明了参数更新的方向(负梯度的方向),但是未指明最佳步长。当常规的梯度下降算法建议更新一大步时,梯度截断会干涉并缩减步长,从而使其基本上贴着悬崖来更新。如上图的第一根路径所示。
当计算图非常深时,容易产生另一种优化困难:长期依赖。
假设计算图中包含一条重复地、与矩阵 相乘的路径。经过 步,则相当于与 相乘。在第 步有:。
根据反向传播原理,有: 。
考虑到权重 参与到每个时间步的计算,因此有: 。
其中记 。假设矩阵 ,则有:
假设 有特征值分解 ,则: 。其中:
考虑特征值 ,当它不在 1 附近时:
如果量级大于 1, 非常大,这称作梯度爆炸问题exploding gradient problem
。
梯度爆炸使得学习不稳定,悬崖结构是梯度爆炸的一个例子。
如果量级小于 1, 非常小,这称作梯度消失问题 vanishing gradient problem
。
梯度消失使得学习难以进行,此时学习的推进会非常缓慢。
循环网络在每个时间步上使用相同的矩阵 ,因此非常容易产生梯度爆炸和梯度消失问题。
前馈神经网络并没有在每一层使用相同的矩阵 ,因此即使是非常深层的前馈神经网络也能很大程度上避免梯度爆炸和梯度消失问题。
对于梯度爆炸,可以通过梯度裁剪来缓解:限定梯度的范数的上限。
对于梯度消失,不能够简单的通过放大来解决。因为有两个问题:
当梯度很小的时候,无法分辨它是梯度消失问题,还是因为抵达了极小值点。
当梯度很小的时候,噪音对梯度的影响太大。获得的梯度很可能由于噪音的影响,导致它的方向是随机的。
此时如果放大梯度,则无法确保此时的方向就是代价函数下降的方向。而对于梯度爆炸,如果缩小梯度,仍然可以保证此时的方向就是代价函数下降的方向。
大多数优化算法都假设知道精确的梯度或者Hessian
矩阵,实际中这些量都有躁扰,甚至是有偏的估计。如:mini-batch
随机梯度下降中,用一个batch
的梯度来估计整体的梯度。
各种神经网络优化算法的设计都考虑到了梯度估计的不精确。
另外,实际情况中的目标函数是比较棘手的,甚至难以用简洁的数学解析形式给出。
此时可以选择替代损失函数
来避免这个问题。
对于最优化问题,即使克服了以上的所有困难,但是并没有到达代价函数低得多的区域,则表现仍然不佳。这就是局部优秀,全局不良。
大多数优化研究的难点集中于:目标函数是否到达了全局最小值、局部最小值、鞍点。
但是实践中,神经网络不会到达任何一种临界点,甚至不会到达梯度很小的区域,甚至这些临界点不是必然存在的。
如:损失函数 没有全局极小点,而是趋向于某个极限值。
下图的例子说明:即使没有局部极小值和鞍点,还是无法使用梯度下降得到一个好的结果。
原因是:初始化在山的左侧。左侧向左趋向于一条渐近线,此时梯度的负方向会不停向左来逼近这条渐进线。
理论上,优化算法要向右跨过山头,从而沿着右侧下降才能到达一个较低的函数值。
在局部结构中执行梯度下降(称作局部梯度下降
)的问题:
局部梯度下降或许能找出一条解路径,但是该路径可能包含了很多次梯度更新,遵循该路径会带来很高的计算代价。
如果目标函数是类似 函数:没有任何鞍点、极值点,而是具有一个宽而平坦的区域(这个区域逼近某个极限)。
此时,若要寻求一个精确的临界点,则局部梯度下降无法给出解路径。这意味着算法难以收敛。
局部梯度下降可能太过贪心,使得训练虽然朝着梯度下降的方向移动,但是远离了真正的解。
如果存在某个参数区域,当遵循局部梯度下降就能够合理地直接到达最优解,且参数初始化点就位于该区域,则局部梯度下降的问题就得到解决。
现有的很多研究方法在求解局部结构复杂的最优化问题时,解决方案为:寻求良好的初始化点,而不再是寻求良好的全局参数更新算法。
机器学习算法和一般最优化算法不同的一点:机器学习算法的目标函数通常可以分解为每个训练样本上的损失函数的求和。如: 。
最大化这个总和,等价于最大化训练集在经验分布上的期望:
当使用基于梯度的优化算法求解时,需要用到梯度:
这个梯度本质上也是一个期望,要准确的求解这个期望的计算量非常大,因为需要计算整个数据集上的每一个样本。
实践中,可以从数据集中随机采样少量的样本,然后计算这些样本上的梯度的均值,将这个均值作为该期望的一个估计。
使用小批量样本来估计梯度的原因:
使用更多样本来估计梯度的方法的收益是低于线性的。
独立同分布的 个样本的均值 是个随机变量,其标准差为 ,其中 为样本的真实标准差。
如果能够快速计算出梯度的估计值(而不是费时地计算准确值),则大多数优化算法会更快收敛。
大多数优化算法基于梯度下降,如果每一步中计算梯度的时间大大缩短,则它们会更快收敛。
训练集存在冗余。
实践中可能发现:大量样本都对梯度做出了非常相似的贡献。
最坏情况下, 训练集中的 个样本都是相同的拷贝。此时基于小批量样本估计梯度的策略也能够计算正确的梯度,但是节省了大量时间。
使用整个训练集的优化算法被称作batch
梯度算法(或者确定性deterministic
梯度算法)。
每次只使用单个样本的优化算法被称作随机stochastic
算法(或者在线online
算法)。
大多数深度学习的优化算法介于两者之间:使用一个以上、又不是采用全部的训练样本,称作mini-batch
或者mini-batch
随机算法。
当使用小批量样本来估计梯度时,由于估计的梯度往往会偏离真实的梯度,这可以视作在学习过程中加入了噪声扰动。这种扰动会带来一些正则化效果。
mini-batch
的大小由下列因素决定:
不能太大。更大的batch
会使得训练更快,但是可能导致泛化能力下降。
训练更快是因为:
更大的batch size
只需要更少的迭代步数就可以使得训练误差收敛。
因为batch size
越大,则小批量样本来估计总体梯度越可靠,则每次参数更新沿着总体梯度的负方向的概率越大。
另外,训练误差收敛速度快,并不意味着模型的泛化性能强。
更大的batch size
可以利用大规模数据并行的优势。
泛化能力下降是因为:更大的batch size
计算的梯度估计更精确,它带来更小的梯度噪声。此时噪声的力量太小,不足以将参数推出一个尖锐极小值的吸引区域。
解决方案为:提高学习率,从而放大梯度噪声的贡献。
不能太小。因为对于多核架构来讲,太小的batch
并不会相应地减少计算时间(考虑到多核之间的同步开销)。
如果batch
中所有样本可以并行地预处理,则内存消耗和batch
大小成正比。
对于许多硬件设备来说,这就是batch
大小的限制因素。
在有些硬件上,特定大小的效果更好。
在使用GPU
时,通常使用 2 的幂作为batch
大小。
泛化误差通常在batch
大小为 1 时最好,但此时梯度估计值的方差非常大,因此需要非常小的学习速率以维持稳定性。如果学习速率过大,则导致步长的变化剧烈。
由于需要降低学习速率,因此需要消耗更多的迭代次数来训练。虽然每一轮迭代中,计算梯度估计值的时间大幅度降低了(batch size
为 1),但是总的运行时间还是非常大。
某些算法对采样误差非常敏感,此时mini-batch
效果较差。原因可能有两个:
通常仅仅基于梯度 的更新方法相对更稳定,它能够处理更小的batch
(如100)。
如果使用了黑塞矩阵 (如需要计算 的二阶方法) 通常需要更大的 batch
(如 10000)。
batch
需要更大从而降低梯度估计的方差。mini-batch
是随机抽样的也非常重要。从一组样本中计算出梯度期望的无偏估计要求:组内的样本是独立的。
另外,也希望两个连续的梯度估计也是相互独立的。这要求:两个连续的mini-batch
样本集合也应该是彼此独立的。
实际应用中,采集的数据样本很可能出现这样的情况:连续的样本之间具有高度相关性。
如:统计人群的偏好,很可能连续的样本就是同一个家庭、同一个职业、同一个地域...。
解决方法是:将样本随机混洗之后存储,训练时按照混洗之后的顺序读取。
这种打乱顺序不会对mini-batch
产生严重的影响,不打乱顺序的mini-batch
才会极大降低算法泛化能力。
mini-batch
可以异步并行分布式更新:在计算mini-batch
样本集合 上梯度更新时,也可以同时计算其他mini-batch
样本集合 上的更新。
当 都是离散时,泛化误差的期望:
其梯度为:
泛化误差的梯度的无偏估计可以通过从数据生成分布 抽取 mini-batch
样本 以及对应的标签 ,然后计算mini-batch
上的损失函数对于 的梯度:
它就是 的无偏估计。
因此,mini-batch
随机梯度下降中,只要没有重复使用样本,它就是真实泛化误差梯度的无偏估计。
如果是在线学习,则每个样本或者mini-batch
都不会重复。每次更新都是独立地从真实分布 中采样获得。
如果训练集不大,通常需要多次遍历训练集,此时只有第一遍满足泛化误差的梯度的无偏估计。
后续的遍历中,泛化误差的梯度估计不再是无偏的。但是后续的遍历会减小训练误差,从而抵消了训练误差和测试误差之间gap
的增加。最终效果是:减小了测试误差。
随着数据集规模的爆炸性增长,超过了计算能力的增长速度,现在普遍地对每个样本只使用一次,甚至不完整地使用训练集。
此时过拟合不再是问题,欠拟合以及计算效率成为主要问题。
随机梯度下降沿着随机挑选的mini-batch
数据的梯度下降方向推进,可以很大程度的加速训练过程。
随机梯度下降SGD
及其变种可能是机器学习中用的最多的优化算法。
算法:
输入:学习率
初始参数:
算法步骤:
迭代,直到满足停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为 。
计算mini-batch
上的梯度作为训练集的梯度的估计:
更新参数:
在深度学习中,通常的停止条件是:运行指定数量的迭代步或者epoch
, 或者在验证集上的某个度量(如:损失函数、错误率、auc
等)不再提升。
SGD
中一个关键参数是学习率。前面介绍的SGD
算法步骤使用固定的学习率 ,实践中有必要随着时间的推移而降低学习率。
使用标准的梯度下降到达极小点时,整个代价函数的真实梯度非常小,甚至为零。由于SGD
使用mini-batch
的梯度作为整体梯度的估计,因此引入了噪源。
该噪源并不会在极小值处消失,使得在极小点时,梯度的估计可能会比较大。因此:标准的梯度下降可以使用固定的学习率,而SGD
必须使用逐渐降低的学习率。
假设在极小点时,梯度的估计值 由于引入了噪源导致较大:
第 步的学习率记做 ,则对于学习率,保证SGD
收敛的一个充分条件是: ,且 。
在实践中,学习率一般线性衰减到第 次迭代,之后由于学习率足够小则可以保持不变:
其中: 是预先指定的(如 1000
), 为常数。
学习率不能够衰减到零,因为一旦 衰减到零,则很难说明模型收敛是因为学习率为零,还是梯度为零。
可以通过试验来选取。
通常被设置为 的大约 1%
, 即降低到足够低的位置。
决定了学习率衰减的速度:经过多少个迭代步,使得学习率降低到足够低的位置。
被称作初始学习率,它的选择是个重要因素:
如果太大,则学习曲线将会剧烈震荡,代价函数值会明显增加。因为学习率太大,则容易发生超调现象。即:参数剧烈震荡,导致代价函数发散或者震荡。
注意:温和的震荡是良好的。
如果太小,则学习过程会非常缓慢,学习可能会卡在一个相当高的代价函数值上。
通常最好检测最早的几轮迭代,使用一个高于此时效果最佳学习率的一个学习率,但是又不能太高以至于导致严重的不稳定性。
学习速率的选择更像是一门艺术,而不是科学。
SGD
以及其它的mini-batch
算法的最重要性质是:每一步参数更新的计算时间(就是计算梯度的时间)不会随着训练样本数量的增加而增加。
SGD
可能在处理整个训练集的所有样本之前就收敛到测试集误差的允许范围之内了研究优化算法的收敛率,会衡量额外误差excess error
: 。它刻画了:目标函数当前值到目标函数最小值的距离。
SGD
应用于凸问题时, 步迭代之后的额外误差量级是 ,在强凸情况下是 。除非给定额外条件,否则这些界限无法进一步改进。Cramer-Rao
界限指出:泛化误差的下降速度不会快于 。Bottou and Bousquet
认定:对于机器学习任务,不值得探寻收敛快于 的优化算法。更快的收敛可能对应于过拟合。本章中剩余介绍的大多数算法都实现了实践中的好处,但是丢失了常数倍 的渐进收敛率。
可以结合标准梯度下降和SGD
两者的优点,在学习过程中逐渐增大mini-batch
的大小。
应用了学习率衰减的SGD
算法存在一个问题:有些时候学习率会很小,但是明明可以应用一个较大的学习率,而SGD
并不知道这一情况。
其解决方法是采用动量方法。
动量方法积累了之前梯度的指数级衰减的移动平均,然后继续沿着该方向移动。
动量方法是一种框架,它可以应用到随机梯度下降SGD
算法中。
动量方法引入了变量 充当速度的角色:它刻画了参数在参数空间移动的方向和速度。
定义速度为负梯度的指数衰减平均,其更新规则为:
超参数 描述了衰减权重的底数,从近期到远期的衰减权重为
令 为位移, 为参数空间的势能,作用力 。根据动量定理:
令粒子为单位质量,时间间隔为单位时间,则有 ,即: 。
则得到更新公式: 。
引入一个速度衰减系数 ,它对上一刻的速度进行降权,则有: 。
这段时间位移的增量为: ,因此有位移更新公式: 。
动量方法更新规则的物理意义为:速度更新,位移更新。
下图给出了非动量的方法与动量方法的路径图。代价函数为一个二次函数,它的黑塞矩阵具有不良的条件数。
红色路径表示动量方法的路径图,黑色箭头给出了在这些点非动量方法的更新方向和步长。
可以看到:动量方法能够快速、正确地到达极小值,而非动量方法会浪费大量的时间在某些方向上宽幅震荡。
原因是:动量方法中,经过加权移动平均之后,在指向极小值的方向上的速度 不断加强,在垂直于极小值的方向上速度 不断抵消。
最终参数会沿着极小值方向快速到达极小值,而在垂直极小值方向波动很小。
使用动量的SGD
算法:
输入:
算法步骤:
迭代,直到满足停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为 。
计算mini-batch
上的梯度作为训练集的梯度的估计:
更新速度:
更新参数:
非动量方法的步长只是梯度范数乘以学习率。采用动量之后,步长取决于梯度序列、衰减因子、学习率。
当有许多连续的梯度指向相同的方向时,步长最大。
可以理解为:不同单位时刻的作用力沿着同一个方向连续的次数越多,则质点的速度会较大(不停沿着同一个方向加速)。而步长就是质点的速度。
动量方法中,如果梯度始终为常量 ,则它会在方向 上不停地加速,直到最终的步长为: 。
通过求解速度序列 的解析表达式可以得到
实践中, 取值一般为 0.5、0.9、0.99。
Nesterov
动量是动量方法的变种,也称作Nesterov Accelerated Gradient
(NAG
)。区别在于:计算mini-batch
的梯度时,采用更新后的参数 。
它可以视作向标准动量方法中添加了一个校正因子:
在凸batch
梯度情况下,Nesterov
动量将额外误差收敛率从 改进到 。
但是在随机梯度的情况下,Nesterov
动量并没有改进收敛率。
假设代价函数高度敏感于参数空间中的某些方向,则优化算法最好针对不同的参数设置不同的学习率。
对于标准的batch
梯度下降优化算法,沿着负梯度的方向就是使得代价函数下降的方向。
mini-batch
梯度下降,由于对梯度引入了躁扰,因此可以针对不同的方向设置不同的学习率。选择哪个算法并没有一个统一的共识,并没有哪一个算法表现的最好。
目前流行的优化算法包括:SGD
,具有动量的SGD
,RMSProp
,AdaDelta
,Adam
。选用哪个算法似乎主要取决于使用者对于算法的熟悉程度,以便调节超参数。
delta-bar-delta
算法是一个自适应学习率的算法,其策略是:对于代价函数,如果其偏导数保持相同的符号,则该方向的学习率应该增加;如果偏导数变化了符号,则该方向的学习率应该减小。
偏导数符号变化,说明更新的方向发生了反向。如果此时降低了学习率,则会对震荡执行衰减,会更有利于到达平衡点(偏导数为0的位置)。
delta-bar-delta
算法只能用于标准的梯度下降中。mini-batch
算法对于梯度的估计不是精确的,因此对于正负号的判断会出现较大偏差。
对于mini-batch
随机梯度下降,有一些自适应学习率的算法。包括:AdaGrad、RMSProp、Adam
等算法。
AdaGrad
算法会独立设置参数空间每个轴方向上的学习率。
AdaGrad
算法的思想是:参数空间每个方向的学习率反比于某个值的平方根。这个值就是该方向上梯度分量的所有历史平方值之和。
其中 表示两个向量的逐元素的相乘。
AdaGrad
算法:
输入:
算法步骤:
初始化梯度累计变量
迭代,直到停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为 。
计算mini-batch
上的梯度作为训练集的梯度的估计:
累计平方梯度:
计算更新(逐元素):
更新参数:
由于随迭代次数的增加, 的值也会增加,因此 随着迭代的推进而降低。这起到了一个学习率衰减的效果。
另一方面,不同方向的分量 不同,平均来说梯度分量越大的方向的学习率下降的最快。这起到了一个自适应的效果。
效果:
在凸优化中,AdaGrad
算法效果较好。
AdaGrad
算法在某些深度学习模型上效果不错,但大多数情况下效果不好。
在训练深度神经网络模型的实践中发现:AdaGrad
学习速率减小的时机过早,且减小的幅度过量。因为学习率与历史梯度的平方和的开方成反比,导致过快、过多的下降。
RMSProp
是AdaGrad
的一个修改:将梯度累计策略修改为指数加权的移动平均。
其中 为衰减速率,它决定了指数加权移动平均的有效长度。
标准的RMSProp
算法:
输入:
算法步骤:
初始化梯度累计变量
迭代,直到停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为 。
计算mini-batch
上的梯度作为训练集的梯度的估计:
累计平方梯度:
计算更新(逐元素):
更新参数:
实践证明RMSProp
是一种有效、实用的深度神经网络优化算法,目前它是深度学习业界经常采用的优化方法之一。
假设迭代过程中,梯度刚好是固定的某个量,令 。对于某个方向,假设其分量为 。
对于RMSProp
算法:根据等比数列求和公式,该方向的比例因子为: ,其中 为迭代次数。
该方向的学习率为:
当某个方向的导数 相对于 较大时,更新步长为(考虑到 ):
RMSProP
算法确保了在梯度较大时,学习的步长不会很小。当导数 非常小以至于和 相差无几时,此时更新步长与梯度有关。
但是由于此时梯度非常小,算法可能已经收敛。
对于AdaGrad
算法的情况:根据等差数列的求和公式,该方向的比例因子为: ,其中 为迭代次数。
该方向的学习率为:
当该方向的梯度对于 较大时,更新步长为:
它与梯度无关,只与迭代次数 有关。随着 增大,从 降低到 。
因此,即使此时的梯度仍然较大,学习的步长仍然接近 0 。
RMSProp
算法 vs AdaGrad
算法:
AdaGrad
算法中,随着迭代次数的增加,其学习率降低到 0。 而RMSProp
算法中,学习率降低到一个较大的渐进值 。AdaGrad
算法中,随着迭代次数的增加,更新步长降低到 0 。而RMSProp
算法中,更新步长降低到一个较大的值 。RMSProp
也可以结合 Nesterov
动量算法。
本质上 Nesterov
算法(包括其他的动量算法)是关于如何更新参数 的算法,它并不涉及任何学习率 的选取。RMSProp
算法是关于如何选取学习率 的算法,它并不涉及如何更新参数 。因此二者可以结合。
RMSProp
动量算法
输入:
算法步骤:
初始化梯度累计变量
迭代,直到停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为
计算临时更新:
这是因为
Nesterov
动量算法使用更新后的参数来计算代价函数。如果使用原始的动量算法,则不需要这一步。
计算mini-batch
上的梯度作为训练集的梯度的估计:
累计平方梯度:
计算速度更新(逐元素):
更新参数:
AdaDelta
也是 AdaGrad
的一个修改。
AdaDelta
将梯度平方和的累计策略修改为:只考虑过去窗口 内的梯度。
RMSProp
可以认为是一种软化的AdaDelta
,衰减速率 决定了一个软窗口: 。
Adam
来自于Adaptive moments
,它是另一种引入了动量的RMSProp
算法。Adam
算法:
输入:
算法步骤:
初始化一阶和二阶矩变量
初始化时间步
迭代,直到停止条件。迭代步骤为:
从训练集中随机采样 个样本 构成mini-batch
,对应的标记为
计算mini-batch
上的梯度作为训练集的梯度的估计:
更新有偏一阶矩估计: 。
它是梯度的指数加权平均,用于计算梯度。
更新有偏二阶矩估计: 。
它是梯度平方的指数加权平均,用于计算学习率。
修正一阶矩的偏差: 。
它使得修正之后的结果更接近真实的梯度。
修正二阶矩的偏差: 。
它使得修正之后的结果更接近真实的梯度平方。
计算更新(逐元素):
更新参数:
RMSProp
算法中,通过累计平方梯度(采用指数移动平均)来修正学习率。
而 Adam
算法中,不仅采用同样的方式来修正学习率,还通过累计梯度(采用指数移动平均) 来修正梯度。
动量的计算可以类似Nesterov
动量的思想:计算mini-batch
的梯度时,采用更新后的参数 。
此时称作NAdam
算法。
假设迭代过程中,梯度刚好是固定的某个量,则有: 。对于某个方向,假设其分量为 ,则对于 Adam
算法有:
无论梯度的大小如何,Adam
算法的参数更新步长几乎都是
相比较而言,AdaGrad
和 RMSProp
算法的参数更新步长随时间在减少。
虽然最终结果不包含 ,但是这是由于假定梯度保持不变这一特殊情况推导的。
实际中梯度很少保持不变,因此 还是比较重要。
Adam
算法之所以需要使用一阶矩的修正和二阶矩的修正,是为了剔除时间因子 的影响。
在某些情况下,Adam
可能导致训练不收敛。主要原因是:随着时间窗口的变化,遇到的数据可能发生巨变。这就使得 可能会时大时小,从而使得调整后的学习率 不再是单调递减的。
这种学习率的震荡可能导致模型无法收敛。
AdaDelta
、RMSProp
算法也都存在这样的问题。
解决方案为:对二阶动量的变化进行控制,避免其上下波动(确保 是单调递增的):
实践证明,虽然在训练早期Adam
具有很好的收敛速度,但是最终模型的泛化能力并不如使用朴素的SGD
训练得到的模型好:Adam
训练的模型得到的测试集误差会更大。
其主要原因可能是:训练后期,Adam
的更新步长过小。
一种改进策略为:在训练的初期使用Adam
来加速训练,并在合适的时期切换为SGD
来追求更好的泛化性能。
这种策略的缺陷是:切换的时机不好把握,需要人工经验来干预。
下图为SGD
及其不同的变种在代价函数的等高面中的学习过程。这里batch-size
为全体样本大小。
AdaGrad
、Adadelta
、RMSprop
从最开始就找到了正确的方向并快速收敛。SGD
找到了正确的方向,但是收敛速度很慢。SGD
的动量算法、Netsterov
动量算法(也叫做NAG
) 最初都偏离了正确方向,但最终都纠正到了正确方向。下图为SGD
及其不同的变种在代价函数的鞍点上的学习过程。这里batch-size
为全体样本大小。
SGD
、SGD
的动量算法、Netsterov
动量算法(也叫做NAG
) 都受到鞍点的严重影响。
SGD
最终停留在鞍点。
如果采用mini-batch
,则mini-batch
引入的梯度噪音,可以使得SGD
能够逃离鞍点。
SGD
的动量算法、Netsterov
动量算法最终逃离了鞍点。
Adadelta
、Adagrad
、RMSprop
都很快找到了正确的方向。
为了简化问题,这里考察目标函数为经验风险函数(即:不考虑正则化项):
.
牛顿法在某点 附近,利用二阶泰勒展开来近似 :
其中 为 对于 的海森矩阵在 处的值。
如果求解这个函数的临界点,根据 ,则得到牛顿法的更新规则:
如果 为 的二次函数,则牛顿法会直接跳到极值或者鞍点。
如果 为 的高阶的,则需要迭代。
牛顿法:
输入:
算法步骤:
迭代,直到到达停止条件。迭代步骤为:
只要海森矩阵保持正定,牛顿法就能够迭代的使用。
在深度学习中目标函数具有很多鞍点,海森矩阵的特征值并不全为正的,因此使用牛顿法有问题:在靠近鞍点附近,牛顿法会导致参数更新主动朝着鞍点的方向移动,这是错误的移动方向。
解决的办法是:使用正则化的海森矩阵。
常用的正则化策略是:在海森矩阵的对角线上增加常数 。
于是更新过程为: 。
这个正则化策略是牛顿法的近似。
只要海森矩阵的负特征值都在零点附近,则可以起到效果。
当有很强的负曲率存在时(即存在绝对值很大的负的特征值), 可能需要特别大。
但是如果 增大到一定程度,则海森矩阵就变得由对角矩阵 主导。此时,牛顿法选择的方向就是 的方向。
海森矩阵的元素的数量是参数数量的平方。如果参数数量为 ,则牛顿法需要计算一个 矩阵的逆,计算一次参数更新的复杂度为 。
由于每次参数更新时都将改变参数,因此每轮迭代训练都需要计算海森矩阵的逆矩阵,计算代价非常昂贵。因此只有参数很少的网络才能够在实际中应用牛顿法训练,绝大多数神经网络不能采用牛顿法训练。
综上所述,牛顿法有两个主要缺点:
BFGS
算法具有牛顿法的一些优点,但是没有牛顿法的计算负担。
大多数拟牛顿法(包括 BFGS
)采用矩阵 来近似海森矩阵的逆矩阵,当 更新时,下降方向为 。
在该方向上的线性搜索到的最佳学习率为 ,则参数更新为: 。
BFGS
算法迭代了一系列线性搜索,其方向蕴含了二阶信息。
与共轭梯度不同,BFGS
的成功并不需要线性搜索真正找到该方向上接近极小值的一点(而是探索一部分点)。因此BFGS
在每个线性搜索上花费更少的时间。
BFGS
算法必须存储海森矩阵逆矩阵的近似矩阵 ,需要 的存储空间。因此BFGS
不适用于大多数具有百万级参数的现代深度学习模型。
L-BFGS
通过避免存储完整的海森矩阵的逆的近似矩阵 来降低存储代价,它假设起始的 为单位矩阵,每步存储一些用于更新 的向量,并且每一步的存储代价是 。
最速下降法是梯度下降法的一个特例:在每次梯度下降时,学习率的选择是使得当前函数值下降最快的那个学习率。
梯度下降法仅仅指明:负梯度的方向是使得代价函数值下降的方向。它并没有说明沿着负梯度的方向推进多少步长。
最速下降法通过显式对学习率建模,求解沿着负梯度的方向需要推进多少步长。
在最速下降法中,假设上一次搜索方向是 ,当前搜索方向是 。可以证明有:
即:前后两次搜索的方向是正交的。
证明过程:
已知 的梯度 ,根据 ,则有:
在最速下降法中,前进过程是锯齿形的。在某种意义上,这意味着消除了之前的线性搜索方向上取得的进展:
如果前一次搜索已经找出了某个方向上的最小值,最速下降法不会保持这一方向。
对于线性空间 ,如果能找到 个向量 ,且它们满足: ,则可以证明这一组向量是线性无关的。
此时这一组向量可以作为线性空间的一组基向量,空间中任意向量 都可以用这组向量表示: 。
对于二次函数极值问题(其中 为正定矩阵): ,将 代入上式,令 :
根据 ,有:
现在变量 已经被分开,可以分别优化。
于是求解第 项的最小值:
直接求导即可得到:
最优解为:
上述最优解可以这样理解:
现在的问题是: 个关于 共轭的向量组 未知。
共轭梯度法通过迭代来搜索关于 共轭的向量组 。
令梯度 ,由于 ,则有:
假设 为对称的正定矩阵,则有: 。因此有: 。
任取一个初始点 。
如果 ,则停止计算。因为此时 就是极值点。
否则,令 ,即: 沿着点 的梯度方向。
沿着 方向搜索: ,使得沿着这个方向,目标函数下降最多。
解得:
由于 ,因此有:
选择第二个迭代点:
注意:这里有 ,但是不保证后面的 。
构建下一个搜索方向,使得 与 关于 共轭。
令:,代入 ,有:
同理:得到 时,计算梯度 ,同时用 和 来构建下一个搜索方向:
得到:
.
共轭梯度法的搜索方向 会保持前一次线性搜索方向上 取得的进展:
其中 的大小控制了:要保留多大比例的上一次搜索方向。
在实际应用中,目标函数往往是高于二次的函数。此时为非线性共轭梯度, 就是海森矩阵 。
直接计算 也需要计算海森矩阵的逆矩阵,比较复杂。有两个计算 的流行方法(不需要计算海森矩阵的逆矩阵):
这里不再保证 和 关于 是共轭的。
Fletcher-Reeves
:
Polak_Ribiere
:
目标函数在高于二次的函数时,往往可能存在局部极值。此时共轭梯度法不能在 维空间内依靠 步搜索到达极值点。
此时需要重启共轭梯度法,继续迭代,以完成搜索极值点的工作。
共轭梯度法:
输入:
算法步骤:
初始化:
迭代,直到到达停止条件。迭代步骤为:
计算梯度:
计算
如果是非线性共轭梯度:则可以以一定的频率重置 为零(如每当 为 5 的倍数时)。
计算搜索方向:
执行线性搜索:
在前面推导过程中,并没有出现这一步。这是因为:在非线性共轭梯度下,以及修改的 的情况下,不再满足 和 关于 是共轭的。
对于真正的二次函数:存在 的解析解,无需显式搜索。
神经网络的目标函数比二次函数复杂得多,但是共轭梯度法在这种情况下仍然适用。此时非线性共轭梯度算法会偶尔采取一些重置操作(重置 为零)。
尽管共轭梯度算法是批方法(需要所有的样本来计算梯度),目前也开发出了mini-batch
版本。
理论上,对于二次函数的目标函数,需要迭代 步, 为参数的个数。每一步中都需要计算梯度。
在神经网络中,这样有两个问题:
最小化 可以采取如下的步骤:
这种做法被称作坐标下降。
还有一种块坐标下降:它对于全部变量的一个子集同时最小化。
当优化问题中的不同变量能够清晰地划分为相对独立的组,或者优化一组变量明显比优化所有变量的效率更高时,坐标下降最有意义。
当一个变量值很大程度影响另一个变量的最优值时,坐标下降不是个好办法。如:
第一项鼓励两个变量具有相近的值;第二项鼓励它们接近零。
牛顿法可以一步解决该问题(它是一个正定二次问题),解为零。
对于较小的 ,此时函数值由第一项决定。
此时采用坐标下降法非常缓慢,因为第一项不允许两个变量相差太大。
坐标下降算法可以用于求解稀疏编码的代价函数最小化问题。
给定训练集 ,稀疏编码的目标是:寻求一个权重矩阵 (未知的) 和一个解码字典矩阵 (也是未知的)来重构训练集 ,其中要求字典矩阵 尽量稀疏 。
代价函数为: 。
虽然代价函数 不是凸的,但是可以将输入分成两个集合:权重 和字典 。 关于权重 是凸的, 关于字典 也是凸的。
因此可以使用块坐标下降(其中可以使用高效的凸优化算法):交替执行:固定 优化 ,以及固定 优化 。
Polyak
平均的基本思想是:优化算法可能因为震荡,反复穿越极值点而没有落在极值点。因此可以考虑路径的均值来平滑输出。
假设 次迭代,梯度下降的参数迭代路径为 ,则Polyak
平均算法的输出为:
在非凸问题中,优化轨迹的路径可能非常复杂。因此当Polyak
应用于非凸问题时,通常会使用指数衰减来计算平均值: 。
有时模型太复杂难以优化,直接训练模型可能太过于困难。此时可以训练一个较简单的模型,然后逐渐使模型复杂化来求解原始问题。
在直接训练目标模型、求解目标问题之前,训练简单模型求解简化问题的方法统称为预训练。
预训练,尤其是贪心预训练,在深度学习中是普遍存在的。
贪心监督预训练将复杂的监督学习问题分解成简化的监督学习问题。
贪心监督预训练的一个例子如下图所示:
a
所示。图 b
是另一个画法。c
所示。图 d
是另一个画法。贪心监督预训练有效的原因,Bengio et al.
提出的假说是:它有助于更好地指导深层结构的中间层的学习。
改进优化的最好方法是选择一个好的模型,选择一族容易优化的模型比使用一个强大的优化算法更重要。
relu
激活函数。现代神经网络更多使用线性函数,如relu
单元、maxout
单元。
许多优化挑战都来自于:因为并不知道代价函数的全局结构,所以不知道最优解所在的区域。
解决该问题的主要方法是:尝试初始化参数到某个区域内,该区域可以通过局部下降很快达到参数空间中的解。
连续方法的原理:挑选一系列的初始化点,使得在表现良好的区域中执行局部优化。
方法为:构造一系列具有相同参数的目标函数 ,其中满足:
这样:首先解决一个简单的问题,然后改进解来解决逐步变难的问题,直到求解真正问题的解。
传统的连续方法(非神经网络的)通常是基于平滑目标函数,主要用于克服局部极小值的问题。它用于在有许多局部极小值的情况下,求解一个全局极小值。
它通过“模糊”原始的代价函数来构建更加容易的代价函数。这种模糊操作可以用采样来近似:
它背后的思想是:某些非凸函数,在模糊之后会近似凸的。
通常这种模糊保留了关于全局极小值的足够多的信息。那么可以通过逐步求解更少模糊的问题,来求解全局极小值。
这种方法有三种失败的可能:
对于神经网络,局部极小值已经不是神经网络优化中的主要问题,但是连续方法仍然有所帮助。
连续方法引入的简化的目标函数能够消除平坦区域、减少梯度估计的方差、提高海森矩阵的条件数,使得局部更新更容易计算,或者改进局部更新方向朝着全局解。
有些优化算法是非迭代的,可以直接解析求解最优解;有些优化算法是迭代的,但是它们是初始值无关的。
深度学习不具有这两类性质,通常是迭代的,且与初始值相关。
深度学习中,大多数算法都受到初始值的影响。初始值能够决定:算法最终是否收敛、以及收敛时的收敛速度有多快、以及收敛到一个代价函数较高还是较低的值。
深度学习中,初始值也会影响泛化误差,而不仅仅是目标函数的最优化。
因为如果选择一个不好的初始值,则最优化的结果会落在参数空间的一个较差的区域。此时会导致模型一个较差的泛化能力。
目前深度学习中,选择初始化策略是启发式的。
度学习中,初始值的选择目前唯一确定的特性是:需要在不同单元之间破坏对称性。
如果具有相同激励函数的两个隐单元连接到相同的输入,则这些单元必须具有不同的初始化参数。
如果它们具有相同的初始化参数,则非随机的学习算法将一直以同样的方式更新这两个单元。
通常鼓励每个单元使用和其他单元不一样的函数,如选择不同的权重或者偏置。
通常的参数初始化策略为:随机初始化权重,偏置通过启发式挑选常数,额外的参数也通过启发式挑选常数。
也可以使用机器学习来初始化模型的参数。
在同样的数据集上,即使是用监督学习来训练一个不相关的任务,有时也能够得到一个比随机初始化更好的初始值。原因是:监督学习编码了模型初始参数分布的某些信息。
通常权重的初始化是从高斯分布或者均匀分布中挑选出来的值。
初始权重的大小很重要,下面的因素决定了权重的初始值的大小:
关于如何初始化网络,正则化和最优化有两种不同的角度:
有些启发式方法可用于选择权重的初始化大小。
假设有 个输入, 个输出的全连接层。
常见的做法是建议使用均匀分布的随机初始化: 。
Glorot et al.
建议使用均匀分布的随机初始化: 。
这种方法使网络在相同激励方差和相同的梯度方差之间折中。
激励就是前向传播中,各信号(如权重、偏置等)的值。梯度就是它们的导数值。
不幸的是上述启发式初始化权重的策略往往效果不佳。有三个可能的原因:
Martens
提出了一种称作稀疏初始化的替代方案:每个单元初始化为恰好具有 个非零的权重。
这个方案有助于单元之间在初始化时就具有更大的多样性。
实践中,通常需要将初始权重范围视作超参数。
如果计算资源允许,可以将每层权重的初始数值范围设置为一个超参数,然后使用超参数搜索算法来挑选这些超参数。
偏置的初始化通常更容易。大多数情况下,可以设置偏置初始化为零。
有时可以设置偏置初始化为非零,这发生在下面的三种情况:
如果偏置是作为输出单元,则初始化偏置为非零值。
假设初始权重足够小,输出单元的输出仅由初始化偏置决定,则非零的偏置有助于获取正确的输出边缘统计。
有时选择偏置的初始值以免初始化引起激活函数饱和。如:ReLU
激活函数的神经元的偏置设置为一个小的正数,从而避免ReLU
初始时就位于饱和的区域。
有时某个单元作为开关来决定其他单元是使用还是不使用。此时偏置应该非零,从而打开开关。
batch normalization
是优化神经网络的一大创新。
深度神经网络训练困难的一个重要原因是:深度神经网络涉及很多层的叠加,而每一层的参数更新会导致上一层的输入数据分布发生变化。这会带来两个问题:
下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区,使得学习过早停止。
通过层层叠加,高层的输入分布变化会非常剧烈。这就使得高层需要不断去适应底层的参数更新变化。
这就要求我们需要非常谨慎的设定学习率、初始化权重、参数更新策略。
在机器学习中,如果数据是独立同分布的,则可以简化模型的训练,提升模型的预测能力。所以通常需要对输入数据进行白化whitening
。 白化主要实现两个目的:
白化操作:
PCA
降维,这称作PCA
处理。理论上可以对神经网络的每一层的输入执行白化来解决输入数据分布的问题。但是有两个困难:
白化操作代价高昂,算法复杂度太大。因为PCA
处理涉及到协方差矩阵 的特征值求解,而计算协方差矩阵的算法复杂度为 (不考虑Strassen
算法优化),其中 为数据集样本数量, 为特征数量。
对于神经网络的训练集,通常 都数以万计甚至百万计,如果在每一层、每一次参数更新都执行白化操作,则不可接受。
白化操作不可微,这样反向传播算法无法进行。
因此batch normalization
就退而求其次,执行简化版的白化:将神经网络的每一层的输入的分布限定其均值和方差。
对于一个深层的神经网络,如果同时更新所有层的参数,则可能会发生一些意想不到的后果。
假设有一个深层神经网络,一共有 层,每层只有一个单元,且每个隐层不使用激励函数。则输出为:
其中 为第 层的权重。第 层的输出为: 。
令 ,其中:
利用梯度下降法更新参数,则有:
如果使用 的一阶泰勒近似,则有: 。即: 的值下降了 。因此梯度下降法一定能够降低 的值。
如果直接按多项式乘法展开,则会考虑 的二阶、三阶甚至更高阶的项,有:
考虑到 ,则有:
如果 都比较小,则 很小,则二阶项可以忽略不计。
如果 都比较大,则该二阶项可能会指数级大。此时很难选择一个合适的学习率,使得 。
因此某一层中参数更新的效果会取决于其他所有层(即:其它层的权重是不是较大)。
虽然二阶优化算法会利用二阶项的相互作用来解决这个问题,但是还有三阶项甚至更高阶项的影响。
batch normalization
解决了多层之间协调更新的问题,它可以应用于网络的任何输入层或者隐层。
设 为神经网络某层的一个mini-batch
的输入, 为输入的维度。
首先计算这个mini-batch
输入的均值和每维特征的标准差:
然后对输入进行归一化:
其中 表示逐元素的除法: 。
最后执行缩放: 。其中 是网络从数据中自动学习到的参数,用于调整 的均值和方差, 为逐元素积。
虽然 的每个维度不是零均值、单位方差的,但是可以保证它的每个维度的均值、方差不再依赖于低层的网络。
归一化一个神经元的均值和标准差会降低包含该神经元的神经网络的表达能力。
若每个神经元的输出都是均值为0、标准差为 1 ,则会产生两个问题:
无论底层的神经元如何学习 ,其输出在提交给上层神经元处理之前,都被粗暴的归一化。导致底层神经元的学习毫无意义。
sigmoid
等激活函数通过区分饱和区、非饱和区(线性区),使得神经网络具有非线性计算的能力。
输入归一化使得数据几乎都被映射到激活函数的线性区,从而降低了模型的表达能力。
因此执行缩放的原因是:保证模型的容量不会被降低。
当网络学到的参数且好是 时, ,因此BN
可以还原原来的输入。这样,模型既可以改变、也可以保持原输入,这就提升了网络的表达能力。
batch normalization
算法
输入:
mini-batch
的输入 输出:经过batch normalization
得到的新的输入
算法步骤:
计算输入的每个维度的均值和方差:
对输入的每个维度执行归一化:
执行缩放:
根据梯度的链式法则,反向传播规则为(假设代价函数为 ):
考虑到 出现在 中,因此有:
由于 出现在 中,因此有:
由于 出现在多条路径中,因此有:
大多数神经网络隐层采用 的形式,其中 是非线性激励函数(如relu
)。
在batch normalization
中推荐使用 ,因为参数 会被 batch normalization
中的参数 吸收:无论 的值是多少,在归一化的过程中它将被减去。
BN
表现良好的一个解释是:内部协方差偏移Internal Covariate Shift:ICS
会对训练产生负面影响,BN
能够减少ICS
。
内部协方差偏移:低层网络的更新对当前层输入分布造成了改变。
统计学习中一个经典假设是源空间source domain
和目标空间target domain
的数据分布一致。协方差偏移covariate shift
就是分布不一致假设之下的一个分支问题。它指的是:源空间和目标空间的条件概率是一致的,但是其边缘概率不同。即:对所有的 ,有 ,但是 。
在神经网络中经过各层的作用,各层输出与其输入分布会不同。这种差异随着网络深度的增大而增大,但是它们能够“指示”的样本标记仍然不变,这就符合covariate shift
的定义。
由于是对层间信号的分析,这就是internal
的由来。
ICS
带来的问题是:各个神经元的输入数据不再是独立同分布的。
论文《How Does Batch Normalization Help Optimization》 2018 Shibani Santurkar etc.
说明BN
对训练带来的增益与ICS
的减少没有任何联系,或者说这种联系非常脆弱。研究发现:BN
甚至不会减少ICS
。
论文说明 BN
的成功的真正原因是:它使得优化问题的解空间更加平滑了。这确保梯度更具有预测性,从而允许使用更大范围的学习率,实现更快的网络收敛。
BN
独立地归一化每个输入维度,它要求每个mini batch
的统计量是整体统计量的近似估计。
因此BN
要求每个mini-batch
都比较大,而且每个mini-batch
的数据分布比较接近。所以在训练之前,需要对数据集进行充分混洗,否则效果可能很差。
当验证或者测试的batch size
较小时(如:只有一个测试样本),此时无法得到mini batch
的统计量,或者mini batch
统计量无法作为整体统计量的近似估计。
此时的做法是:先通过训练集上得到的所有 mini batch
的统计量的移动平均值,然后将它们作为验证或者测试时的mini batch
的统计量。
但是当训练数据、验证数据、测试数据的数据分布存在差别时(如:训练数据从网上爬取的高清图片,测试数据是手机拍照的图片),训练集上预先计算好的mini batch
的统计量的移动平均值并不能代表验证集、测试集的相应的统计量。这就导致了训练、验证、测试三个阶段存在不一致性。
BN
存在两个明显不足:
高度依赖于mini batch
的大小。它要求每个mini-batch
都比较大,因此不适合batch size
较小的场景,如:在线学习(batch size=1
)。
不适合RNN
网络。
因为不同样本的 sequence
的长度不同,因此RNN
的深度是不固定的。同一个batch
中的多个样本会产生不同深度的RNN
,因此很难对同一层的样本进行归一化。
设 ,则BN
具有权重伸缩不变性,以及数据伸缩不变性。
权重伸缩不变性:假设 ,则有:
其中因为 很小几乎可以忽略不计,因此有 ,则有: 。
因此权重缩放前后, 保持不变。 是BN
层的输入, 就是高层流向低层的梯度,因此权重缩放不影响梯度的流动。
另外,由于 ,因此权重越大,则该权重的梯度越小,这样权重更新就越稳定。这相当与实现了参数正则化的效果,避免了参数的大幅震荡。
通常并不会把
batch normalization
当作一种正则化的手段,而是作为加速学习的方式。
数据伸缩不变性:假设 ,同理有:
因此数据的伸缩变化不会影响到对该层的权重更新,简化了对学习率的选择。
究竟是在激活函数之前、还是之后进行batch normalization
, 这个问题在文献中有一些争论。
实践中,通常都是在激活函数之前进行的。
在测试阶段,如果需要对单一样本评估,此时测试集只有单个样本,无法给出均值和标准差。
解决的方式为:将 设置为训练阶段收集的运行均值(或者是指数加权均值)。
除了batch normalization
之外,还有layer normalization、 instance normalization、group normalization、 weight normalization
。
下图给出了BN、LN、IN、GN
的示意图(出自论文《Group Normalization》 Kaiming He etc.
)。其中蓝色部分表示:通过这些蓝色区域计算均值和方差,然后蓝色区域中的每个单元都使用这些均值、方差来归一化。
注意:这里的BN
是网络某层中,对每个通道进行归一化;而前面的BN
是对每个神经元进行归一化。
如果是对每个神经元进行归一化,则BN
示意图中,蓝色区域只有最底下的一行。
与 BN
不同,LN
是对单个样本的同一层的神经元进行归一化,同层神经元使用相同的均值和方差。
对于该层神经元,不同样本可以使用的均值和方差不同。
与之相比,BN
是对每个神经元在mini batch
样本之间计算均值和方差。对每个神经元,mini batch
中的所有样本在该神经元上都使用相同的均值和方差。但是不同神经元使用不同的均值和方差。
因此LN
不依赖于batch size
,也不依赖于网络深度。因此它适合在线学习,也适合于RNN
网络。
设神经网络第 层的输入为 , , 为该层神经元的数量。则LN
的步骤为:
首先计算该层所有神经元的均值和方差:
然后对神经元进行归一化:
其中 都是标量。
最后执行缩放: 。
与 BN
相同, 也是网络从数据中自动学习到的参数,用于调整 的均值和方差, 为逐元素积。
这一步的作用也是提升神经网络的表达能力。
layer normalization
算法
输入:
输出:经过layer normalization
得到的新的输入
算法步骤:
计算该层所有神经元的均值和方差:
对该层神经元进行归一化:
执行缩放:
根据梯度的链式法则,反向传播规则为(假设代价函数为 ):
由于 出现在多条路径中,因此有:
其中出现标量与向量的加法,它等价于将标量扩充为向量,扩充向量在每个维度上的取值就是该标量。如: 。
其计算图如下所示,与BN
相同。
LN
的特点是:针对单个样本进行,不依赖于mini batch
中的其它样本。
与IN
与LN
相同,它们都是对单个样本进行操作。与LN
不同的是:IN
对同一层神经元中的同一个通道进行归一化。
IN
主要用于图像处理任务中,此时每一层网络都有 N、H、W、C
四个维度。其中N
代表batch
维度,H、W
代表 feature map
的宽度和高度, C
代表通道数量。
LN
使得同一层神经元中的同一个通道上的神经元使用相同的均值和方差。对于该通道中的神经元,不同的样本使用的均值和方差不同。
设单张图片在网络第 层的输入张量为 。 为了防止名字冲突,这里用 标记第 层的输入。其中 为通道数, 为feature map
的高度和宽度。
三个索引分别代表: 代表通道维的索引, 分别代表高度和宽度维度的索引。
则 LN
的步骤为:
首先计算样本在第 个通道的神经元的均值和方差:
然后对神经元进行归一化:
最后执行缩放:
其中 表示第 个通道位于) 的神经元的缩放因子和平移因子。
instance normalization
算法
输入:
输出:经过instance normalization
得到的新的输入
算法步骤:
计算样本在第 个通道的神经元的均值和方差:
对神经元进行归一化:
执行缩放: 。
instance normalization
的反向传播规则的推导类似layer normalization
。
BN
对mini batch
中所有图片求均值和方差,计算得到的统计量会受到mini batch
中其它样本的影响。而IN
是对单个图片求均值和方差,与其它样本无关。
GAN
、风格迁移这类任务上,IN
效果要优于BN
。其普遍解释为:这类生成式方法,每张图片自己的风格比较独立,不应该与batch
中其它图片产生太大联系。IN
也不依赖于batch size
,也不依赖于网络深度。因此它适合在线学习,也适合于RNN
网络。GN
首先将通道分组。假设有C
个通道,分成G
个组,则:通道1,...,C/G
为一个组,通道C/G+1,...,2C/G
为一个组.... 。
然后GN
对每个通道组进行归一化。
因此可以看到:GN
介于LN
和IN
之间。如果G=1
,即只有一个分组,则GN
就是LN
;如果G=C
,即每个通道构成一个组,则GN
就是IN
。
group normalization
算法
输入:
输出:经过group normalization
得到的新的输入
算法步骤:
计算每个分组的通道数
计算样本在第 个分组的神经元的均值和方差:
对神经元进行归一化:
执行缩放: 。
GN
有效的可能原因是:在网络的每一层中,多个卷积核学到的特征并不是完全独立的。某些特征具有类似的分布,因此可以被分到同一组。
根据论文《Group Normalization》 Kaiming He etc.
得到的结论:
BN
很容易受到batch size
的影响,而GN
不容易受到batch size
的影响。
如下图/表 所示为BN
和GN
的比较,模型为resnet-50
、训练集为ImageNet
、训练硬件为8个带GPU
的 worker
、指标为它们在验证集上的验证误差。
batch size | 32 | 16 | 8 | 4 | 2 |
---|---|---|---|---|---|
BN | 23.6 | 23.7 | 24.8 | 27.3 | 34.7 |
GN | 24.1 | 24.2 | 24.0 | 24.2 | 24.1 |
提升 | 0.5 | 0.5 | -0.8 | -3.1 | -10.6 |
在较大的batch size
上,BN
的表现效果最好。
resnet-50
模型在ImageNet
训练中,当采用batch size=32
时,采取各种normalization
的模型的表现(验证误差)为:
BN | LN | IN | GN | |
---|---|---|---|---|
验证误差 | 23.6 | 25.3 | 28.4 | 24.1 |
相比 BN 的提升 | - | -1.7 | -4.8 | -0.5 |
下图为这些模型在各个epoch
事训练、验证的表现:
常见的梯度下降法、牛顿法、拟牛顿法属于批学习batch
方法,每次迭代都需要对全量训练样本重新学习一遍。
当面临搜索、推荐等高维度(数十亿甚至上百亿维度)、大尺度(百亿规模甚至千亿规模)数据的场景时,传统的批学习方法效率太低。
解决该问题的方法是:在线学习 online learning
。
最简单的在线学习策略是在线梯度下降Oneline Gradient Descent:OGD
。它是当 batch size = 1
的 mini-batch
随机梯度下降法的特殊情形。
该算法每次迭代仅训练最新的样本,每个样本只被训练一次。
不同于 mini-batch
随机梯度下降,在 OGD
中,算法每次梯度更新并不是沿着全局梯度的负方向进行前进,而是带有非常大的随机性。
这样即使采用 L1
正则化,模型也很难产生稀疏解。而在线学习过程中,稀疏性是一个主要追求目标,因为稀疏解有以下优点:
为得到稀疏解,最简单的方式是进行梯度截断:每隔 步,当权重低于阈值 时截断为 0 。
其中:
该方法容易理解、实现简单,但是实际中很少应用。因为权重系数较小的原因,很可能是因为该维度训练不足(如出现该特征的样本太少)引起的,并不是因为该特征不重要引起的。简单的截断可能造成该部分特征丢失。
梯度截断法 Truncated Gradient:TG
是对简单截断的一种改进。当权重低于阈值 时,它不是直接降低到 0 ,而是慢慢降低到 0 。
其中:
TG
法退化到简单截断法。下图中,
x
表示z
, 表示
前向后向切分FOBOS:Forward-Backward Splitting
将权重更新分为两个步骤:
其中 用于对参数进行正则化。
该更新过程分为两步:
第一步为标准的梯度下降
第二步对梯度下降的结果进行微调。其中:
将第一步方程代入第二步,有:
为求得最优解,根据梯度为零有:
因此有:
可以看到:
FOBOS
与常规梯度下降在于 FOBOS
多了一项: 。当在 L1
正则化下, 。令 ,记 则有:
由于求和项中每一项都是非负的,因此当每一项都最小时,整体最小。即:
设 是最优解,则必有 。如果 ,则有:
因此 必然不是最优解,矛盾。
既然有 ,则分情况讨论:
当 时,则有 ,则原始问题转化为:
解得:
当 时,有 ,则原始问题转化为:
解得:
因此得到 FOBOS
在 L1
正则化条件下的更新方程:
其中 为符号函数:当 时取值为 -1
;当 时取值为 1
;当 时取值为 0
。
重新调整更新公式:
当一条样本产生的梯度 不足以对维度 的权重产生足够大的变化时,权重 被截断为 0 。
当 ,,TG
更新方程退化为:
因此当 时 ,TG
退化为 L1-FOBOS
。
TG,FOBOS
等算法都是基于随机梯度下降 SGD
算法而来,而正则对偶平均 Regularized Dual Averaging: RDA
算法是基于简单对偶平均法 Simple Dual Averaging Scheme
而来。
RDA
的权重特新方程为:
其中:
在 L1
正则化的情况下, 。设 ,它满足严格凸函数的条件。设 ,它满足非负非递减。则有:
将其拆解为各维度的最小化问题,则有:
其中 为所有梯度的均值。
求解该方程,得到权重更新公式:
因此当维度 上的累积梯度均值的绝对值小于 时,发生阈值截断。
L1-RDA
和 L1-FOBOS
的比较:
对于L1-FOBOS
,当 时执行梯度截断。通常选择 时随着时间 下降的,因此 L1-FOBOS
的截断阈值是随着时间变化的。
而 L1-RDA
的截断阈值 是固定的常数,因此相比 L1-FOBOS
更激进,也更容易产生稀疏性。
L1-RDA
基于梯度的累积均值 来判断,而 L1-FOBOS
基于最近的单次梯度 来判断。
而梯度累积均值比单次梯度更稳定。
L1-RDA
的更新过程中, 与前一时刻的 无关,仅仅由梯度累积均值 来决定。
而 L1-FOBOS
的更新过程中, 由前一时刻的 、 共同决定。
实验证明:L1-FOBOS
这类基于梯度下降的方法具有较高的精度,但是 L1-RDA
却具有更好的稀疏性。Follow the Regularized Leader : FTRL
结合了两者的优点:即具有较好的稀疏性,又具有较高的精度。
FTRL
综合考虑了 FOBOS
和 RDA
,其特征权重更新公式为:
其中 为超参数。
重新调整最优化目标为:
令 ,考虑到最后一项与 无关,因此有:
将其拆解为各维度的最小化问题,则有:
求解该最优化问题,得到 FTRL
的参数更新方程:
因此 L1
正则化项引入稀疏性,L2
正则化项平滑求解结果。
对于TG,FOBOS
等基于随机梯度下降的算法,学习率通常是全局的:每个维度的学习率都是相同的。如: 。
RDA
算法没有学习率的概率,该算法未用到学习率。
在 FTRL
算法中,不同维度的学习率是单独考虑的 Per-Coordinate Learning Rates
。
这是由于:
同时 也是每个维度不同。令:
则有:
.