Skip to content

第6章 模型拟合

第 3 章和第 4 章描述了浅层和深度神经网络。它们代表分段线性函数族,其中参数决定了具体的函数。第 5 章引入了损失——一个标量值,表示网络预测与训练集真实值之间的不匹配程度。

损失取决于网络参数,本章考虑如何找到使该损失最小化的参数值。这被称为学习(learning)网络的参数,或简称训练(training)或拟合(fitting)模型。该过程是选择初始参数值,然后迭代执行以下两个步骤:(i) 计算损失对参数的导数(梯度),(ii) 基于梯度调整参数以降低损失。经过多次迭代后,我们希望能到达损失函数的全局最小值。

本章处理这两个步骤中的第二个——我们考虑根据梯度调整参数以降低损失的算法。第 7 章讨论如何初始化参数以及如何计算神经网络的梯度。

6.1 梯度下降

为拟合模型,我们需要一个输入/输出对的训练集 {xi,yi}。我们寻找模型 f[xi,ϕ] 的参数 ϕ,使输入 xi 尽可能准确地映射到输出 yi。为此,我们定义一个损失函数 L[ϕ],返回一个标量值来量化该映射中的不匹配程度。优化算法(optimization algorithm)的目标是找到使损失最小化的参数 ϕ^

(6.1)ϕ^=argminϕ[L[ϕ]].

优化算法有很多族,但训练神经网络的标准方法是迭代的。这些算法启发式地初始化参数,然后反复调整使损失下降。

这一类中最简单的方法是梯度下降(gradient descent)。它从初始参数 ϕ=[ϕ0,ϕ1,,ϕN]T 开始,迭代两个步骤:

步骤 1. 计算损失对参数的导数:

(6.2)Lϕ=[Lϕ0Lϕ1LϕN].

步骤 2. 按以下规则更新参数:

(6.3)ϕϕαLϕ,

其中正标量 α 决定了变化的幅度。

第一步计算当前位置处损失函数的梯度,确定上坡方向。第二步沿下坡方向(因此有负号)移动一小段距离 α。参数 α 可以是固定的(此时称为学习率(learning rate)),也可以通过线搜索(line search)尝试多个 α 值以找到最能降低损失的值。

在损失函数的最小值处,曲面必定是平坦的(否则我们还能通过下坡行走来改进)。因此,梯度将为零,参数将停止变化。在实践中,我们监测梯度的大小,当它变得足够小时终止算法。

6.1.1 线性回归示例

考虑将梯度下降应用于第 2 章的一维线性回归模型。模型 f[x,ϕ] 将标量输入 x 映射到标量输出 y,参数为 ϕ=[ϕ0,ϕ1]T,分别代表 y 轴截距和斜率:

(6.4)y=f[x,ϕ]=ϕ0+ϕ1x.

给定包含 I 个输入/输出对 {xi,yi} 的数据集,我们选择最小二乘损失函数:

(6.5)L[ϕ]=i=1Ii=i=1I(f[xi,ϕ]yi)2=i=1I(ϕ0+ϕ1xiyi)2,

其中 i=(ϕ0+ϕ1xiyi)2 是第 i 个训练样本对损失的单独贡献。

损失函数对参数的导数可以分解为各单独贡献的导数之和:

(6.6)Lϕ=ϕi=1Ii=i=1Iiϕ,

其中各项为:

(6.7)iϕ=[iϕ0iϕ1]=[2(ϕ0+ϕ1xiyi)2xi(ϕ0+ϕ1xiyi)].

图 6.1 展示了该算法的进展过程:我们依据方程 6.6 和 6.7 迭代计算导数,然后按方程 6.3 的规则更新参数。此处我们使用了线搜索来找到每次迭代中最能降低损失的 α 值。

图 6.1

图 6.1 线性回归模型的梯度下降。a) 包含 I=12 个输入/输出对 {xi,yi} 的训练集。b) 展示梯度下降迭代过程的损失函数。从点 0 开始,沿最陡下降方向移动,直到无法再改进,到达点 1。然后重复此过程。c) 可视化为热力图更清晰,亮度表示损失大小。仅经过四次迭代,就已经接近最小值。d) 点 0 处参数对应的模型(最浅色线)对数据描述很差,但每次迭代都改善了拟合。点 4 处参数对应的模型(最深色线)已是训练数据的合理描述。

6.1.2 Gabor 模型示例

线性回归问题的损失函数(图 6.1c)总是具有一个定义明确的全局最小值。更正式地说,它们是的(convex),即曲面上任意两点之间的弦(线段)位于函数上方且不与之相交。凸性意味着无论我们从哪里初始化参数,只要持续下坡行走就一定能到达最小值;训练过程不会失败。

不幸的是,大多数非线性模型(包括浅层和深度网络)的损失函数是非凸的(non-convex)。由于参数数量庞大,可视化神经网络损失函数具有挑战性。因此,我们先探索一个更简单的非线性模型——具有两个参数的 Gabor 模型,以了解非凸损失函数的性质:

(6.8)f[x,ϕ]=sin[ϕ0+0.06ϕ1x]exp((ϕ0+0.06ϕ1x)232.0).

该模型将标量输入 x 映射到标量输出 y,由正弦分量(形成振荡函数)乘以负指数分量(使振幅随远离中心而衰减)组成。它有两个参数 ϕ=[ϕ0,ϕ1]T,其中 ϕ0R 决定函数中心的位置,ϕ1R+ 沿 x 轴拉伸或压缩函数(图 6.2)。

考虑包含 I 个样本 {xi,yi} 的训练集(图 6.3)。对 I 个训练样本的最小二乘损失函数定义为:

(6.9)L[ϕ]=i=1I(f[xi,ϕ]yi)2.

目标同样是找到使该损失最小化的参数 ϕ^

图 6.2

图 6.2 Gabor 模型。该非线性模型将标量输入 x 映射到标量输出 y,参数为 ϕ=[ϕ0,ϕ1]T。它描述一个正弦函数,其振幅随离中心距离增大而衰减。参数 ϕ0R 决定中心位置。参数 ϕ1R+ 沿 x 轴相对于中心拉伸函数。a–c) 不同参数下的模型。

图 6.3

图 6.3 拟合 Gabor 模型的训练数据。训练数据集包含 28 个输入/输出样本 {xi,yi}。这些数据通过在 [15,15] 内均匀采样 xi,用参数 ϕ=[0.0,16.6]T 的 Gabor 模型计算后加入正态分布噪声生成。

6.1.3 局部极小值和鞍点

图 6.4 描绘了该数据集上 Gabor 模型的损失函数。其中有大量局部极小值(local minima)(青色圆圈)。在这些位置,梯度为零,沿任何方向移动损失都会增加,但我们并未处于函数的全局最低点。损失最低的点称为全局最小值(global minimum),以灰色圆圈标记。

如果我们从一个随机位置开始使用梯度下降下坡行走,无法保证最终到达全局最小值并找到最佳参数(图 6.5a)。算法同样甚至更可能终止于某个局部极小值。而且无法知道是否存在更好的解。

此外,损失函数还包含鞍点(saddle points)(例如图 6.4 中的蓝色十字)。在鞍点处,梯度为零,但函数在某些方向上增加而在其他方向上减少。如果当前参数不是恰好在鞍点上,梯度下降可以通过下坡移动来逃离。然而,鞍点附近的曲面接近平坦,因此很难确定训练是否已收敛;如果在梯度很小时就终止算法,可能会错误地停在鞍点附近。

图 6.4

图 6.4 Gabor 模型的损失函数。a) 损失函数是非凸的,除全局最小值(灰色圆圈)外还有多个局部极小值(青色圆圈)。它还包含鞍点,梯度局部为零但函数在一个方向上增加而在另一个方向上减少。蓝色十字是鞍点的例子。b–f) 不同极小值对应的模型。每种情况下都没有能够降低损失的微小变化。面板 (c) 展示了全局最小值,损失为 0.64。

图 6.5

图 6.5 梯度下降与随机梯度下降的比较。a) 带线搜索的梯度下降。只要算法初始化在损失函数的正确"谷"中(如点 1 和 3),参数估计就会稳步走向全局最小值。但如果初始化在该谷之外(如点 2),它将下降到某个局部极小值。b) 随机梯度下降为优化过程添加了噪声,因此有可能从错误的谷中逃出(如点 2)并仍然到达全局最小值。

6.2 随机梯度下降

Gabor 模型只有两个参数,因此可以通过 (i) 穷举搜索参数空间,或 (ii) 从不同位置多次启动梯度下降并选择损失最低的结果来找到全局最小值。然而,神经网络模型可能有数百万个参数,上述两种方法都不可行。简而言之,使用梯度下降在高维损失函数中找到全局最优解是困难的。我们可以找到某个最小值,但无法判断它是否是全局最小值,甚至不知道它是否足够好。

梯度下降算法的一个主要问题是其最终结果完全取决于起始点。随机梯度下降(stochastic gradient descent, SGD)通过在每一步的梯度中添加噪声来解决此问题。解在平均意义上仍然是下坡移动,但在任何给定的迭代中,所选方向不一定是最陡下降方向,甚至可能不是下坡方向。SGD 算法有可能暂时上坡移动,从而从损失函数的一个"谷"跳到另一个(图 6.5b)。

6.2.1 批次和轮次

引入随机性的机制很简单。每次迭代时,算法随机选择训练数据的一个子集,仅基于这些样本计算梯度。这个子集称为小批量(minibatch)或简称批次(batch)。第 t 次迭代的模型参数 ϕt 的更新规则为:

(6.10)ϕt+1ϕtαiBti[ϕt]ϕ,

其中 Bt 是当前批次中输入/输出对的索引集,i 与之前一样是第 i 对对应的损失。α 是学习率,与梯度大小一起决定了每次迭代移动的距离。学习率在训练开始时选定,不依赖于函数的局部性质。

批次通常从数据集中无放回地抽取。算法遍历训练样本直到用完所有数据,然后重新从完整训练数据集中开始采样。一次遍历整个训练数据集称为一个轮次(epoch)。批次可以小到单个样本,也可以大到整个数据集。后者称为全批梯度下降(full-batch gradient descent),与常规的(非随机)梯度下降相同。

SGD 的另一种理解方式是:它在每次迭代中计算不同损失函数的梯度;损失函数取决于模型和训练数据,因此对于每个随机选择的批次都不同。从这个角度看,SGD 是对不断变化的损失函数执行确定性梯度下降(图 6.6)。然而,尽管存在这种变化性,期望损失和期望梯度与梯度下降的情况相同。

图 6.6

图 6.6 批量大小为三的 Gabor 模型 SGD 的另一视角。a) 整个训练数据集的损失函数。每次迭代时,存在可能的参数变化的概率分布(内嵌图展示样本)。这些对应于三个批次元素的不同选择。b) 某一个可能批次的损失函数。SGD 算法在该函数上沿下坡方向移动一段距离,距离由学习率和局部梯度大小决定。当前模型(内嵌图中的虚线函数)变化为更好地拟合批次数据(实线函数)。c) 不同的批次产生不同的损失函数和不同的更新。d) 对于该批次,算法相对于批次损失函数下坡移动,但相对于面板 (a) 中的全局损失函数局部上坡移动。这就是 SGD 能够逃离局部极小值的机制。

6.2.2 随机梯度下降的性质

SGD 具有若干吸引人的特性。第一,虽然它为轨迹添加了噪声,但每次迭代仍然改善了对数据子集的拟合。因此,即使更新不是最优的,也趋向于合理。第二,由于它从数据集中无放回地抽取并遍历所有数据,训练样本的贡献仍然是平等的。第三,仅从训练数据的子集计算梯度在计算上更廉价。第四,它可以(原则上)逃离局部极小值。第五,它降低了陷在鞍点附近的概率;在损失函数的任何位置,至少某些可能的批次很可能具有显著的梯度。最后,有证据表明 SGD 能为神经网络找到使其在实践中对新数据泛化良好的参数(参见第 9.2 节)。

SGD 在传统意义上不一定"收敛"。然而,我们希望当接近全局最小值时,所有数据点都能被模型很好地描述。因此,无论选择哪个批次,梯度都会很小,参数也不会有太大变化。在实践中,SGD 通常配合学习率调度(learning rate schedule)使用。学习率 α 从一个较高的值开始,每 N 个轮次按常数因子递减。其逻辑是:在训练早期,我们希望算法探索参数空间,在不同的谷之间跳跃以找到合理的区域。在后期阶段,我们大致处在正确的位置,更关注精细调整参数,因此减小 α 以做出更小的改变。

6.3 动量

对随机梯度下降的一个常见改进是添加动量(momentum)项。我们用当前批次计算的梯度与上一步移动方向的加权组合来更新参数:

mt+1βmt+(1β)iBti[ϕt]ϕ(6.11)ϕt+1ϕtαmt+1,

其中 mt 是动量(驱动第 t 次迭代更新的量),β[0,1) 控制梯度随时间平滑的程度,α 是学习率。

动量计算的递归形式意味着梯度步长是所有先前梯度的无限加权和,权重随时间回溯越远越小。如果所有这些梯度在多次迭代中方向一致,有效学习率会增大;而如果梯度方向反复变化,求和中的项会相互抵消,有效学习率会减小。总体效果是更平滑的轨迹和在谷中减少的振荡行为(图 6.7)。

图 6.7

图 6.7 带动量的随机梯度下降。a) 常规随机梯度下降走了一条非常间接的路径到达最小值。b) 使用动量项后,当前步的变化是上一次变化和从批次计算的梯度的加权组合。这使得轨迹更平滑并提高了收敛速度。

6.3.1 Nesterov 加速动量

动量项可以被视为对 SGD 算法下一步将要移动到哪里的粗略预测。Nesterov 加速动量(Nesterov accelerated momentum)(图 6.8)在这个预测点而非当前点计算梯度:

mt+1βmt+(1β)iBti[ϕtαβmt]ϕ(6.12)ϕt+1ϕtαmt+1,

其中梯度现在在 ϕtαβmt 处计算。这可以理解为梯度项现在修正了仅靠动量提供的路径。

图 6.8

图 6.8 Nesterov 加速动量。解沿虚线行进到达点 1。传统动量更新在点 1 处测量梯度,沿该方向移动一段距离到点 2,然后加上前一次迭代的动量项(即沿虚线方向),到达点 3。Nesterov 动量更新首先应用动量项(从点 1 到点 4),然后在那里测量梯度并应用更新,到达点 5。

6.4 Adam

固定步长的梯度下降有一个不良特性:它对具有大梯度的参数(也许我们应该更谨慎)做出大幅调整,而对具有小梯度的参数(也许我们应该进一步探索)做出小幅调整。当损失曲面在一个方向上比另一个方向陡峭得多时,很难选择一个在两个方向上都 (i) 取得良好进展且 (ii) 保持稳定的学习率(图 6.9a–b)。

一种直接的方法是归一化梯度,使我们在每个方向上移动固定距离(由学习率决定)。为此,我们首先测量梯度 mt+1 和逐分量的平方梯度 vt+1

mt+1L[ϕt]ϕ(6.13)vt+1(L[ϕt]ϕ)2.

然后应用更新规则:

(6.14)ϕt+1ϕtαmt+1vt+1+ϵ,

其中平方根和除法都是逐分量的,α 是学习率,ϵ 是防止梯度为零时除以零的小常数。vt+1 是平方梯度,取其正平方根用于归一化梯度本身,因此剩下的只是每个坐标方向上的符号。结果是算法沿每个坐标移动固定距离 α,方向由哪边是下坡决定(图 6.9c)。这个简单算法在两个方向上都取得良好进展,但除非恰好落在最小值上,否则不会收敛。相反,它会在最小值附近来回振荡。

自适应矩估计(Adaptive moment estimation),即 Adam,采用这一思想并对梯度和平方梯度的估计都添加动量:

mt+1βmt+(1β)L[ϕt]ϕ(6.15)vt+1γvt+(1γ)(L[ϕt]ϕ)2,

其中 βγ 是两个统计量的动量系数。

使用动量等价于对每个统计量的历史取加权平均。在训练开始时,所有先前的测量值实际上为零,导致不切实际的小估计值。因此,我们使用以下规则修正这些统计量:

m~t+1mt+11βt+1(6.16)v~t+1vt+11γt+1.

由于 βγ[0,1) 范围内,随着时间步增加,t+1 次幂的项变得越来越小,分母趋近于一,这种修正的影响逐渐消失。

最后,我们像之前一样更新参数,但使用修正后的项:

(6.17)ϕt+1ϕtαm~t+1v~t+1+ϵ.

结果是一个能够收敛到整体最小值、且在参数空间每个方向上都取得良好进展的算法。注意 Adam 通常在随机设置下使用,其中梯度及其平方从小批量计算:

mt+1βmt+(1β)iBti[ϕt]ϕ(6.18)vt+1γvt+(1γ)(iBti[ϕt]ϕ)2,

因此轨迹在实践中是有噪声的。

正如我们将在第 7 章中看到的,神经网络参数的梯度大小可能取决于其在网络中的深度。Adam 有助于补偿这种趋势并平衡不同层之间的变化。在实践中,Adam 还具有对初始学习率不那么敏感的优势,因为它避免了图 6.9a–b 中那样的情况,所以不需要复杂的学习率调度。

图 6.9

图 6.9 自适应矩估计(Adam)。a) 该损失函数在垂直方向变化快而在水平方向变化慢。如果使用在垂直方向上取得良好进展的学习率运行全批梯度下降,则算法需要很长时间才能到达最终的水平位置。b) 如果选择使水平方向取得良好进展的学习率,则在垂直方向上过冲并变得不稳定。c) 一种直接方法是每步沿每个轴移动固定距离以在两个方向上都下坡移动。通过归一化梯度大小仅保留符号来实现。但这通常不会收敛到精确最小值,而是在其周围来回振荡(此处在最后两个点之间)。d) Adam 算法在估计梯度和归一化项中都使用动量,产生更平滑的路径。

6.5 训练算法超参数

学习算法、批量大小、学习率调度和动量系数的选择都被视为训练算法的超参数(hyperparameters);它们直接影响最终模型性能,但与模型参数不同。选择这些超参数更多的是艺术而非科学,通常需要用不同超参数训练许多模型并选择最好的一个。这被称为超参数搜索(hyperparameter search)。我们将在第 8 章重新讨论这一问题。

6.6 总结

本章讨论了模型训练。该问题被表述为找到对应损失函数 L[ϕ] 最小值的参数 ϕ。梯度下降方法测量当前参数处损失函数的梯度(即当我们对参数做小幅改变时损失如何变化),然后沿损失下降最快的方向移动参数。这一过程重复直到收敛。

对于非线性函数,损失函数可能同时具有局部极小值(梯度下降会被困住)和鞍点(梯度下降可能表现为已收敛但实际上未收敛)。随机梯度下降有助于缓解这些问题。每次迭代使用不同的随机数据子集(批次)来计算梯度。这为过程添加了噪声,有助于防止算法陷入参数空间的次优区域。每次迭代的计算成本也更低,因为只使用了数据的子集。我们看到添加动量项可以使收敛更高效。最后,我们介绍了 Adam 算法。

本章的思想适用于优化任意模型。下一章处理训练过程中两个专门针对神经网络的方面。首先,我们讨论如何计算损失对神经网络参数的梯度,这通过著名的反向传播(backpropagation)算法实现。其次,我们讨论如何在优化开始前初始化网络参数。如果不仔细初始化,优化过程中使用的梯度可能变得极大或极小,从而阻碍训练过程。

基于 CC-BY-NC-ND 许可协议