↓跳到主要内容

机器学习模型究竟在优化什么?——从梯度下降到大语言模型

··20956 字·42 分钟
可视化展示梯度下降、牛顿法和 BFGS 算法在椭圆等高线上迭代收敛到最小点的轨迹。
目录

先看一个最优解几乎一眼可见的问题:在二维实向量空间中寻找参数向量 \(\mathbf{w}\),使目标函数 \(f(\mathbf{w})\) 取得最小值。

\[ \begin{aligned} \underset{\mathbf{w}\in\mathbb{R}^2}{\operatorname{minimize}} \quad f(\mathbf{w}) &=\frac{1}{2}w_1^2+10w_2^2,\\ \mathbf{w} &=\begin{bmatrix}w_1\\w_2\end{bmatrix}。 \end{aligned} \]
变量或记号含义
\(\operatorname{minimize}\)表示需要寻找使右侧目标函数尽可能小的参数
\(\mathbb{R}^2\)由两个实数组成的二维参数空间,也是本例中 \(\mathbf{w}\) 的取值范围
\(\mathbf{w}\)需要调整的二维参数向量
\(w_1,w_2\)参数向量在横轴和纵轴方向上的两个分量
\(f(\mathbf{w})\)参数取 \(\mathbf{w}\) 时的目标函数值;优化的任务是让它尽可能小
\(1/2,10\)两个平方项的系数;当 \(\lvert w_1\rvert=\lvert w_2\rvert\) 时,第二个平方项对函数值的贡献是第一个平方项的 20 倍

两个平方项都不会小于零,所以当 \(w_1=0\)、\(w_2=0\) 时,函数取得全局最小值 \(0\)。最低点在哪里并不难判断,真正的问题是:如果参数从 \((-8,4)\) 出发,算法要怎样走过去,又需要走多少步?

\[ \mathbf{w}_0=\begin{bmatrix}-8\\4\end{bmatrix},\qquad f(\mathbf{w}_0)=192。 \]
变量或记号含义
\(\mathbf{w}_0\)优化开始时的参数位置;下标 \(0\) 表示尚未执行第一次更新
\(f(\mathbf{w}_0)\)初始位置对应的目标函数值,本例为 \(192\)

下面的互动图让梯度下降、牛顿法和 BFGS(一种拟牛顿法)从这个起点同时出发。切换算法并拖动迭代进度,可以直接比较它们的搜索方向、收敛速度和每一步的目标函数值。

三种算法从同一个初始点出发,寻找同一个最低点,却走出了不同的路径。

图中一圈圈封闭的曲线称为等高线。同一条线上的所有位置具有相同的目标函数值,就像地形图上的同一条等高线代表相同的海拔。这个函数的等高线不是圆,而是沿水平方向拉长的椭圆:参数在 \(w_2\) 方向稍微移动,函数值就会发生较大变化;沿 \(w_1\) 方向移动相同距离,函数值的变化相对较小。

描述这种“函数在某个方向上弯曲得有多快”的量叫作曲率。可以先把它直观地理解为碗壁的陡峭程度:曲率越大,碗壁越陡、越窄,参数稍微移动就会明显改变斜率。这里暂时只需从图中观察到,\(w_2\) 方向比 \(w_1\) 方向更陡。

要把这个直觉写成数学公式,需要区分一阶导数和二阶导数。一阶导数描述函数在当前位置的斜率;对于有多个参数的函数,每个方向的一阶偏导数组合起来,就是梯度。二阶导数则继续追问:“参数移动以后,斜率变化得有多快?”因此,它可以用来描述曲率。二阶导数较大,表示斜率随位置变化得更快。

对于只有一个参数的函数,二阶导数只是一个数;对于有多个参数的函数,可以对每一对参数依次求偏导,从而得到相应的二阶偏导数。把这些二阶偏导数按照参数顺序排列成方阵,就得到海森矩阵(Hessian matrix)。矩阵对角线上的元素描述各参数自身方向的曲率,非对角线元素描述两个参数共同变化时的相互影响。本例没有 \(w_1w_2\) 交叉项,所以相应的非对角线元素为零。第 2.1 节会把这些概念代入当前函数,逐步计算梯度和海森矩阵。

最低点相同,并不意味着求解效率相同。梯度下降只使用当前的一阶梯度;牛顿法进一步使用海森矩阵提供的二阶曲率信息;BFGS 不直接计算真实海森矩阵,而是根据相邻迭代之间的参数位移和梯度变化,逐步构造逆海森矩阵的近似。三种算法利用的信息不同,因此走出的路径也不同。

许多机器学习模型的训练都可以表述为类似的优化问题,只是目标函数通常更复杂,待学习参数的数量也可能从几个增长到数百万甚至更多。在代码中,数据科学家和工程师通常只需调用一次 model.fit(X, y),但 fit 只是一个统一接口:模型定义如何根据输入生成预测,目标函数定义什么结果算好,优化算法则负责寻找使完整目标尽可能小的参数。

数据科学家和工程师通常不需要从头实现优化器。不过,当训练收敛缓慢、数值不稳定或结果过拟合时,理解 model 的初始化配置参数,以及背后的模型、目标函数、正则化和优化算法之间的关系,往往能更快定位和解决问题。

下文会先回到这个可以手动计算的二维二次型,解释梯度下降、牛顿法和 BFGS 为什么产生不同轨迹;随后再沿着同一条主线,讨论最小二乘、岭回归(Ridge)、Lasso 回归、弹性网络(Elastic Net)、XGBoost、LightGBM、神经网络和 Prophet 各自在优化什么,以及它们怎样寻找答案。全文的大部分问题都可以借助下面这个结构理解:

\[ \min_{\theta} \underbrace{\mathcal{L}(\theta;X,y)}_{\text{拟合数据}} +\lambda\underbrace{\Omega(\theta)}_{\text{约束模型}}。 \]
变量或记号含义
\(\min_\theta\)在所有允许的 \(\theta\) 中,寻找能使后面表达式取得最小值的参数
\(X\)全部输入特征;第四章会进一步说明它的矩阵维度
\(y\)全部真实观测或标签
\(\mathcal{L}(\theta;X,y)\)给定数据和参数后的拟合损失
\(\Omega(\theta)\)对参数或模型复杂度的惩罚
\(\lambda\)数据拟合与模型约束之间的权衡强度

并非所有模型都能严格表示为这种形式,但我们可以借助它来理解本文讨论的大多数模型。

下面这张图把目标函数放在中心,并补上决定训练能否落地的计算规模与验证反馈。后文会沿着这张地图逐步展开:第二、三章讨论求解方法与计算代价,第四至七章比较不同模型怎样定义预测、损失与更新,第五、八、九章进一步解释约束与先验。

机器学习优化统一地图:模型结构产生预测,数据损失衡量拟合,约束或先验限制解,求解器更新参数;计算规模和验证结果构成外围工程条件与反馈。

图 1:机器学习训练不仅要让目标函数下降,还要同时考虑模型结构、约束与先验、求解成本和验证结果。

阅读前:本文的符号约定 #

不同教材、论文和软件库常使用不同符号表示同一概念。例如,学习率可能写作 \(\alpha\)、\(\eta\) 或 learning_rate;正则化强度可能写作 \(\lambda\),但在某些 API 中却被称为 alpha。为避免读者在不同记号间频繁切换,本文遵循以下三条规则:

  1. 同一个概念在全文只使用一个主符号;
  2. 在同一局部上下文中,一个主符号只承担一个含义;跨章节复用符号时,明确说明含义变化;
  3. 第一次引入公式时说明变量、维度和作用,遇到常见异名时再给出映射。

全文采用以下基本约定:

本文记号固定含义形式或维度其他资料中的常见写法
\(i\)样本索引\(i=1,\ldots,n\)row index、observation index
\(j\)特征、叶节点或变点的局部索引含义由所在章节明确说明feature/leaf/changepoint index
\(k\)数值优化的迭代编号\(k=0,1,2,\ldots\)iteration、step
\(t\)Boosting 轮次、神经网络更新步数或时间点含义由所在章节明确说明round、step、time
\(\theta\)模型全部待学习参数标量、向量或参数集合\(w\)、\(\beta\)、parameters
\(\mathcal{L}\)只包含数据拟合误差的损失标量loss、data loss、empirical risk
\(\mathcal{J}\)优化器实际最小化的完整目标标量objective、cost、risk
\(\Omega\)正则项或复杂度惩罚标量函数penalty、regularizer
\(\eta\)学习率或预先设定的更新步长正标量\(\alpha\)、step size、learning_rate
\(\lambda\)正则化强度非负标量alpha、penalty weight

本文用粗体小写字母表示向量(如 \(\mathbf{x}\)),用大写字母表示矩阵(如 \(X\)),而普通斜体小写字母通常表示标量。上标 \(\mathsf{T}\) 表示转置,\(\lVert\cdot\rVert_1\) 和 \(\lVert\cdot\rVert_2\) 分别表示 L1 范数和 L2 范数,符号上方的帽子表示估计值或预测值。后续的变量表仅解释各章新引入或含义变化的符号,不再重复此全局约定表。

全文阅读路线 #

全文可以分成四个阶段。下面的路线图展示了十章各自回答的问题,以及“求解方法—模型训练—概率解释—大模型工程”这条逐步展开的主线。

机器学习优化全文阅读地图:第 1 至 3 章建立目标、求解路径与计算代价的基础;第 4 至 7 章比较不同模型的训练方式;第 8 至 9 章用先验解释正则化与 Prophet;第 10 章统一模型分析并延伸到大语言模型。

图 2:全文从基础优化方法出发,依次进入经典模型、概率解释与大模型训练工程。

1. 优化问题由什么组成? #

预测模型 \(f_\theta(\mathbf{x})\) 根据输入计算预测值。单个样本的损失函数 \(\ell(y_i,f_\theta(\mathbf{x}_i))\) 衡量此次预测的误差。训练集的经验风险通常是所有样本损失的平均值:

\[ \mathcal{L}(\theta)=\frac{1}{n}\sum_{i=1}^{n}\ell\left(y_i,f_\theta(\mathbf{x}_i)\right)。 \]
变量或记号含义
\(n\)训练样本总数
\(i\)当前样本索引,从 \(1\) 到 \(n\)
\(\mathbf{x}_i\)第 \(i\) 条样本的输入特征向量
\(y_i\)第 \(i\) 条样本的目标值或标签
\(f_\theta(\mathbf{x}_i)\)参数为 \(\theta\) 时,模型对 \(\mathbf{x}_i\) 的预测
\(\ell(y_i,f_\theta(\mathbf{x}_i))\)第 \(i\) 条样本的损失
\(\sum\)将全部样本的损失相加
\(1/n\)把损失总和换算为每条样本的平均损失

完整的优化目标函数还可能包含正则项:

\[ \mathcal{J}(\theta)=\mathcal{L}(\theta)+\lambda\Omega(\theta)。 \]

在这里,\(\mathcal{J}\) 代表优化器处理的完整目标函数,而 \(\mathcal{L}\) 仅指数据损失。尽管一些文献会将两者都表示为 \(L\) 或 loss,本文为避免忽略正则项,将两者明确区分。

优化算法利用目标函数提供的信息更新参数。例如,梯度下降只使用一阶导数,牛顿法还会利用二阶曲率,BFGS 则根据相邻两次迭代之间的梯度变化来近似曲率。

这些概念承担的任务不同。最小二乘定义优化目标;正规方程、基于 QR 分解的方法和梯度下降,则提供不同的求解路径。类似地,反向传播负责计算神经网络的梯度,SGD、动量法(momentum)和 Adam 再利用梯度更新参数。

1.1 从一维抛物线理解梯度 #

考虑最简单的函数:

\[ f(w)=\frac{1}{2}w^2。 \]

其导数为 \(f'(w)=w\)。当 \(w>0\) 时,向左移动可降低函数值;当 \(w<0\) 时,向右移动可降低函数值。因此,梯度下降法总是沿梯度的反方向进行更新:

\[ w_{k+1}=w_k-\eta f'(w_k)。 \]
变量含义
\(w_k\)第 \(k\) 次迭代时的标量参数位置
\(f(w)\)需要最小化的一维目标函数
\(f'(w_k)\)目标函数在 \(w_k\) 处的导数,即局部斜率
\(\eta\)学习率,控制一次更新的幅度
\(w_{k+1}\)更新一次以后得到的新位置

此处 \(\eta>0\)。学习率过小,算法前进缓慢;学习率过大,参数可能反复越过最低点,甚至发散。一维函数隐藏了现实问题中最麻烦的部分:不同方向的曲率可能相差很大。

2. 二维二次型:不同算法怎样寻找最低点? #

文章开头的互动图使用的正是这个二维二次型。下面从目标函数、初始点和曲率开始,逐步解释三条轨迹为什么不同。

考虑目标函数:

\[ f(\mathbf{w})=\frac{1}{2}w_1^2+10w_2^2,\qquad \mathbf{w}=\begin{bmatrix}w_1\\w_2\end{bmatrix}。 \]
变量含义本例取值或维度
\(\mathbf{w}\)需要优化的参数向量二维列向量
\(w_1,w_2\)参数向量在两个坐标方向上的分量标量
\(f(\mathbf{w})\)参数取 \(\mathbf{w}\) 时的目标函数值标量,越小越好
\(1/2,10\)两个平方项的系数;对应方向的二阶导数分别为 \(1\) 和 \(20\)作者设定的教学示例,不是经验数据

它的极小值位于 \((0,0)\)。三种算法都从同一个初始点出发。把初始参数代入目标函数,可得初始函数值:

\[ \begin{aligned} \mathbf{w}_0&=\begin{bmatrix}-8\\4\end{bmatrix},\\ f(\mathbf{w}_0) &=\frac{1}{2}(-8)^2+10(4)^2\\ &=32+160\\ &=192。 \end{aligned} \]

2.1 梯度、海森矩阵与条件数 #

这一节依次回答三个问题:目标函数在当前位置朝哪个方向变化最快?不同方向的斜率变化得有多快?这些方向之间的尺度差异会给优化和数值计算带来什么影响?对应的数学工具分别是梯度、海森矩阵和条件数。

从一阶偏导到梯度 #

先分别对两个参数求一阶偏导:

\[ \begin{aligned} \frac{\partial f}{\partial w_1} &=\frac{\partial}{\partial w_1} \left(\frac{1}{2}w_1^2+10w_2^2\right) =w_1,\\ \frac{\partial f}{\partial w_2} &=\frac{\partial}{\partial w_2} \left(\frac{1}{2}w_1^2+10w_2^2\right) =20w_2。 \end{aligned} \]

把两个偏导数按照参数 \(w_1,w_2\) 的顺序组合成列向量,就得到梯度:

\[ \begin{aligned} \mathbf{g}(\mathbf{w}) &=\nabla f(\mathbf{w})\\ &=\begin{bmatrix} \partial f/\partial w_1\\ \partial f/\partial w_2 \end{bmatrix}\\ &=\begin{bmatrix}w_1\\20w_2\end{bmatrix}。 \end{aligned} \]

梯度给出函数在当前位置最陡上升的方向,其模长表示该方向上的最大局部变化率;但它没有说明梯度本身会怎样随位置改变。要回答这个问题,需要继续对梯度求导。

从梯度变化到海森矩阵 #

本文把梯度写成列向量,并采用以下排列规则:海森矩阵(Hessian matrix)的第 \(i\) 行对应梯度的第 \(i\) 个分量 \(g_i\),第 \(j\) 列表示对第 \(j\) 个参数 \(w_j\) 求偏导。因此,第 \(i\) 行、第 \(j\) 列的元素定义为:

\[ H_{ij} =\frac{\partial g_i}{\partial w_j} =\frac{\partial}{\partial w_j} \left(\frac{\partial f}{\partial w_i}\right)。 \]

按照“行对应梯度分量、列对应求导参数”的顺序,二维海森矩阵为:

\[ \begin{aligned} \mathbf{H} &=\nabla^2 f(\mathbf{w})\\ H_{11}&=\frac{\partial w_1}{\partial w_1}=1,\\ H_{12}&=\frac{\partial w_1}{\partial w_2}=0,\\ H_{21}&=\frac{\partial(20w_2)}{\partial w_1}=0,\\ H_{22}&=\frac{\partial(20w_2)}{\partial w_2}=20,\\ \mathbf{H} &=\begin{bmatrix}1&0\\0&20\end{bmatrix}。 \end{aligned} \]

例如,第一行第二列先取梯度的第一个分量 \(g_1=w_1\),再对第二个参数 \(w_2\) 求偏导,所以 \(H_{12}=\frac{\partial w_1}{\partial w_2}=0\)。第二行第二列则由 \(g_2=20w_2\) 对 \(w_2\) 求偏导,得到 \(H_{22}=\frac{\partial(20w_2)}{\partial w_2}=20\)。对于二阶偏导连续的函数,混合偏导满足 \(H_{12}=H_{21}\),所以海森矩阵是对称矩阵。

变量含义本例取值或维度
\(\mathbf{g}(\mathbf{w})\)目标函数对各参数的一阶偏导组成的梯度二维列向量
\(\nabla\)对参数求一阶偏导的算子不适用
\(H_{ij}\)海森矩阵第 \(i\) 行、第 \(j\) 列的元素;先选择梯度分量 \(g_i\),再对参数 \(w_j\) 求偏导标量
\(\mathbf{H}\)梯度对参数的导数,即海森矩阵(Hessian)\(2\times2\) 矩阵

海森矩阵已经给出了全部二阶偏导,但我们还需要从矩阵中识别主要的曲率方向。这正是特征向量和特征值的作用。

用特征值比较不同方向的曲率 #

对于一个非零向量 \(\mathbf v\),如果矩阵 \(\mathbf H\) 作用在它上面以后,向量仍然位于原来的直线上,只是按倍数 \(\nu\) 缩放,即:

\[ \mathbf H\mathbf v=\nu\mathbf v, \]

那么 \(\mathbf v\) 称为 \(\mathbf H\) 的特征向量,缩放倍数 \(\nu\) 称为对应的特征值。当 \(\nu>0\) 时,方向不变;当 \(\nu<0\) 时,向量会反向。本例的海森矩阵是对称正定矩阵,所有特征值都为正。它的特征向量给出彼此正交的曲率方向,特征值则表示目标函数沿相应方向弯曲得有多快。

本例的海森矩阵是对角矩阵,因此两个坐标轴方向就是它的特征向量。先看 \(w_1\) 轴方向:

\[ \begin{aligned} \mathbf e_1&=\begin{bmatrix}1\\0\end{bmatrix},\\ \mathbf H\mathbf e_1 &=\begin{bmatrix}1&0\\0&20\end{bmatrix} \begin{bmatrix}1\\0\end{bmatrix}\\ &=\begin{bmatrix}1\\0\end{bmatrix}\\ &=1\mathbf e_1。 \end{aligned} \]

矩阵没有改变 \(\mathbf e_1\) 的方向,只把它乘以 \(1\),所以第一个特征值是 \(\nu_1=1\)。再看 \(w_2\) 轴方向:

\[ \begin{aligned} \mathbf e_2&=\begin{bmatrix}0\\1\end{bmatrix},\\ \mathbf H\mathbf e_2 &=\begin{bmatrix}1&0\\0&20\end{bmatrix} \begin{bmatrix}0\\1\end{bmatrix}\\ &=\begin{bmatrix}0\\20\end{bmatrix}\\ &=20\mathbf e_2。 \end{aligned} \]

因此,第二个特征值是 \(\nu_2=20\)。对于二次型,如果只沿某个单位特征向量 \(\mathbf e_i\) 移动距离 \(z\),令 \(\mathbf w=z\mathbf e_i\),目标函数就会化为:

\[ \begin{aligned} f(z\mathbf e_i) &=\frac{1}{2}(z\mathbf e_i)^\mathsf{T} \mathbf H(z\mathbf e_i)\\ &=\frac{1}{2}z^2\mathbf e_i^\mathsf{T} (\nu_i\mathbf e_i)\\ &=\frac{1}{2}\nu_i z^2。 \end{aligned} \]
新变量或记号含义
\(\mathbf v\)用于定义特征向量的任意非零向量
\(\mathbf e_i\)第 \(i\) 个单位特征向量;单位向量的长度为 \(1\)
\(\nu_i\)海森矩阵沿 \(\mathbf e_i\) 方向的特征值,也是该方向的曲率尺度
\(z\)沿单位特征向量移动的有符号距离
\(\mathbf e_i^\mathsf{T}\mathbf e_i=1\)单位特征向量与自身的内积等于 \(1\)

这里使用了单位向量的性质 \(\mathbf e_i^\mathsf{T}\mathbf e_i=1\)。因此,特征值越大,沿对应方向移动相同距离时,函数值增加得越快,曲率也越大。

用条件数衡量尺度差异和数值敏感性 #

条件数(condition number)衡量一个数值问题对输入误差的敏感程度。它回答的不是“矩阵中的元素有多大”,而是“输入发生很小的相对变化时,结果的相对变化在最坏情况下可能被放大到什么程度”。条件数接近 \(1\) 的问题称为良态问题(well-conditioned problem),输入的小误差通常不会被显著放大;条件数很大的问题称为病态问题(ill-conditioned problem),微小的测量误差或浮点舍入误差也可能造成明显的结果变化。

以线性方程组 \(\mathbf H\mathbf x=\mathbf b\) 为例。如果右侧输入出现小扰动 \(\delta\mathbf b\),并导致解发生变化 \(\delta\mathbf x\),那么在矩阵 \(\mathbf H\) 保持不变、只扰动 \(\mathbf b\) 的条件下,相对误差满足以下上界:

\[ \frac{\lVert\delta\mathbf x\rVert_2}{\lVert\mathbf x\rVert_2} \leq \kappa_2(\mathbf H) \frac{\lVert\delta\mathbf b\rVert_2}{\lVert\mathbf b\rVert_2}。 \]
新变量或记号含义
\(\mathbf x\)线性方程组需要求解的未知向量
\(\mathbf b\)线性方程组右侧的输入向量
\(\delta\mathbf b\)输入 \(\mathbf b\) 中的微小扰动,例如测量误差或舍入误差
\(\delta\mathbf x\)输入扰动引起的解的变化
\(\lVert\cdot\rVert_2\)向量的二范数,即通常所说的欧几里得长度
\(\kappa_2(\mathbf H)\)使用二范数定义的矩阵条件数;下标 \(2\) 表示误差大小用二范数衡量

这个不等式给出的是最坏情况下的上界,并不表示每一次误差都会达到这个放大倍数。条件数本身也不等于“损失的有效数字位数”。它只是提供一个敏感度尺度,帮助我们判断当前问题是否容易受到输入误差和浮点计算的影响。

回到本文的优化问题。对于对称正定海森矩阵,二范数条件数可以由最大特征值除以最小特征值计算。最大特征值代表最陡方向的曲率,最小特征值代表最平缓方向的曲率,因此它们的比值同时衡量不同优化方向之间的尺度差异:

\[ \kappa_2(\mathbf H) =\frac{\nu_{\max}}{\nu_{\min}}。 \]
新变量或记号含义
\(\nu_{\max}\)最大特征值,对应曲率最大的方向
\(\nu_{\min}\)最小特征值,对应曲率最小的方向
\(\kappa_2(\mathbf H)\)海森矩阵的二范数条件数;对称正定时等于 \(\nu_{\max}/\nu_{\min}\)

本例已经求得 \(\nu_{\max}=20\) 和 \(\nu_{\min}=1\)。代入条件数公式:

\[ \begin{aligned} \kappa_2(\mathbf H) &=\frac{\nu_{\max}}{\nu_{\min}}\\ &=\frac{20}{1}\\ &=20。 \end{aligned} \]

这个结果表示本例最大曲率是最小曲率的 20 倍。它不表示数值误差必然放大 20 倍,也不表示计算会损失 20 位有效数字;它表示问题在不同方向上的尺度并不均衡,而且在最不利的情况下,输入的相对误差可能被放大到更明显的程度。与 \(\kappa_2=1\) 的各向同性问题相比,这个优化问题更难处理。

当 \(\kappa_2(\mathbf H)=1\) 时,各特征方向的曲率相同,二次型的等高线是圆。条件数越大,不同方向的尺度差异越明显,等高线也越狭长。如果梯度下降让所有方向共用一个学习率,稳定性上限就由曲率最大的方向决定,参数通常会在陡峭方向振荡,同时在平缓方向缓慢前进。

至此,互动图中的狭长椭圆就有了定量解释:\(w_2\) 方向的特征值为 \(20\),\(w_1\) 方向的特征值为 \(1\),两者相差 20 倍。本文用 \(\nu\) 表示特征值,避免它与表示正则化强度的 \(\lambda\) 冲突。下一节将继续利用这两个特征值,推导梯度下降学习率为什么必须受到最大曲率的限制。

2.2 学习率为什么存在上限? #

学习率决定每次沿负梯度方向移动多远。它太小时,参数下降得很慢;它太大时,一次更新可能越过最低点,下一次又跳回另一侧。学习率的上限并不是需要背诵的经验规则,而是由这种反复跳动是否会逐步衰减决定的。

对于二次型,沿海森矩阵的每个特征方向观察,梯度下降都会化成一个等比数列。因此,可以先在一个方向上推导收敛条件,再把同样的结论推广到全部特征方向。

先只看本例的 \(w_2\) 方向。暂时固定其他方向后,目标函数可简化为一维函数:

\[ f_2(w_2)=10w_2^2。 \]

它的一阶导数为:

\[ g_2(w_2)=\frac{\mathrm{d}f_2}{\mathrm{d}w_2}=20w_2。 \]
变量或记号含义
\(f_2(w_2)\)只观察 \(w_2\) 方向时的一维目标函数
\(g_2(w_2)\)\(f_2\) 对 \(w_2\) 的一阶导数
\(20\)\(w_2\) 方向的二阶导数,也就是这个方向的曲率

把这个方向的梯度代入梯度下降公式:

\[ \begin{aligned} w_{2,k+1} &=w_{2,k}-\eta g_2(w_{2,k})\\ &=w_{2,k}-20\eta w_{2,k}\\ &=(1-20\eta)w_{2,k}。 \end{aligned} \]

等式中的 \(1-20\eta\) 决定每一步怎样缩放当前参数。为了看清多次更新的结果,将递推式连续展开:

\[ \begin{aligned} w_{2,1}&=(1-20\eta)w_{2,0},\\ w_{2,2}&=(1-20\eta)w_{2,1} =(1-20\eta)^2w_{2,0},\\ &\ \vdots\\ w_{2,k}&=(1-20\eta)^k w_{2,0}。 \end{aligned} \]

因此,从初始值 \(w_{2,0}\) 开始连续更新 \(k\) 次,可以写成:

\[ w_{2,k}=(1-20\eta)^k w_{2,0}。 \]
变量或记号含义
\(w_{2,k}\)第 \(k\) 次迭代时,参数在 \(w_2\) 方向上的分量
\(w_{2,0}\)\(w_2\) 方向的初始值,本例为 \(4\)
\(q=1-20\eta\)这个等比数列的公比,也是每次更新的缩放因子
\(q^k\)连续更新 \(k\) 次以后,初始值被累计缩放的倍数

当 \(k\to\infty\) 时,只有公比的绝对值严格小于 \(1\),\(q^k\) 才会趋近于零。因此,要让 \(w_{2,k}\) 收敛到最低点 \(0\),必须满足:

\[ \lvert 1-20\eta\rvert<1。 \]

逐步解这个不等式:

\[ \begin{aligned} \lvert1-20\eta\rvert<1 &\Longleftrightarrow -1<1-20\eta<1\\ &\Longleftrightarrow -2<-20\eta<0\\ &\Longleftrightarrow 0<\eta<\frac{2}{20}\\ &\Longleftrightarrow 0<\eta<0.1。 \end{aligned} \]

最后一步除以负数 \(-20\) 时,不等号方向需要反转。左端的 \(\eta>0\) 保证更新沿负梯度方向进行;右端的 \(\eta<0.1\) 保证 \(w_2\) 的绝对值会随迭代逐步缩小。等号不能保留:当 \(\eta=0.1\) 时,公比恰好为 \(-1\),参数只会在原点两侧等幅跳动,不会趋近于零。

设 \(w_{2,0}=4\)。以 \(\eta=0.08\) 为例,先计算公比,再逐步代入递推公式:

\[ q=1-20\eta =1-20\times0.08 =-0.6。 \]\[ \begin{aligned} w_{2,1}&=q w_{2,0}=(-0.6)\times4=-2.4,\\ w_{2,2}&=q w_{2,1}=(-0.6)\times(-2.4)=1.44,\\ w_{2,3}&=q w_{2,2}=(-0.6)\times1.44=-0.864。 \end{aligned} \]

这个例子也说明公比的符号和绝对值分别控制两件事:符号决定参数是否跨越最低点,绝对值决定振幅是缩小、保持不变还是增大。按照同样的方法代入其他学习率,可以得到四种具有代表性的轨迹:

学习率 \(\eta\)公比 \(q=1-20\eta\)\(w_2\) 的迭代轨迹结果
\(0.05\)\(0\)\(4\to0\)一步到达该方向的极小值
\(0.08\)\(-0.6\)\(4\to-2.4\to1.44\to-0.864\to\cdots\)跨越原点振荡,但振幅逐步缩小
\(0.10\)\(-1\)\(4\to-4\to4\to-4\to\cdots\)等幅振荡,不收敛
\(0.12\)\(-1.4\)\(4\to-5.6\to7.84\to-10.976\to\cdots\)只要初始分量不为零,振幅就会不断增大

一维推导只处理了 \(w_2\) 方向。要保证整个二维参数向量收敛,还必须同时检查其他方向。对于一般的多维二次型:

\[ f(\mathbf{w}) =\frac{1}{2}\mathbf{w}^{\mathsf{T}}\mathbf{H}\mathbf{w}, \qquad \nabla f(\mathbf{w})=\mathbf{H}\mathbf{w}。 \]

将梯度 \(\mathbf H\mathbf w_k\) 代入更新公式:

\[ \mathbf{w}_{k+1} =\mathbf{w}_k-\eta\mathbf{H}\mathbf{w}_k =(\mathbf{I}-\eta\mathbf{H})\mathbf{w}_k。 \]

如果海森矩阵在第 \(i\) 个特征方向上的特征值为 \(\nu_i\),那么该方向与前面的一维例子完全相同:曲率 \(20\) 被替换为 \(\nu_i\),单步缩放因子变为:

\[ q_i=1-\eta\nu_i。 \]

要让任意初始向量都收敛到零,每个特征方向都必须满足 \(\lvert q_i\rvert<1\)。只要其中一个方向不满足,参数在该方向上的分量就不会消失,整个向量也无法收敛。用矩阵语言概括这个要求,就是更新矩阵的谱半径必须严格小于 \(1\):

\[ \operatorname{spr}(\mathbf{I}-\eta\mathbf{H}) =\max_i\lvert1-\eta\nu_i\rvert<1。 \]
变量或记号含义
\(\nu_i\)海森矩阵在第 \(i\) 个特征方向上的特征值,也代表该方向的曲率
\(q_i\)梯度下降在第 \(i\) 个特征方向上的单步缩放因子
\(\operatorname{spr}(\cdot)\)矩阵的谱半径,即所有特征值绝对值中的最大值;其他资料通常写成 \(\rho(\cdot)\)
\(\nu_{\max}\)所有方向中最大的曲率

对于正定海森矩阵,所有特征值都为正。每个方向分别要求:

\[ 0<\eta<\frac{2}{\nu_i}。 \]

一个全局学习率必须同时满足全部方向的限制,因此最严格的上限来自最大的特征值 \(\nu_{\max}\):

\[ 0<\eta<\frac{2}{\nu_{\max}}。 \]

在本例中,\(w_1\) 方向要求 \(0<\eta<2/1=2\),而 \(w_2\) 方向要求 \(0<\eta<2/20=0.1\)。两项条件的交集是 \(0<\eta<0.1\),所以全局学习率的上限由曲率最大的 \(w_2\) 方向决定。换句话说,只要所有方向共用一个学习率,稳定性限制就由最陡峭的方向决定。

下一节将取满足这个条件的 \(\eta=0.08\),把二维参数的前三次更新完整算出来。这样可以直接看到:同一个学习率虽然能保证整体收敛,却会让两个方向表现出完全不同的速度和轨迹。

其他教材常用 \(\alpha\) 表示学习率,用 \(\lambda_i\) 表示海森矩阵的特征值。本文统一写成 \(\eta\) 和 \(\nu_i\),但推导和结论完全相同。

2.3 梯度下降:一个学习率照顾所有方向 #

上一节给出了学习率的稳定区间,但“能够收敛”并不等于“每个方向都收敛得一样快”。现在回到完整的二维参数向量,观察固定学习率怎样同时作用于两个曲率相差 20 倍的方向。

梯度下降的更新式为:

\[ \mathbf{w}_{k+1}=\mathbf{w}_k-\eta\mathbf{g}_k。 \]
变量含义
\(\mathbf{w}_k\)第 \(k\) 次迭代时的参数向量
\(\mathbf{g}_k=\nabla f(\mathbf{w}_k)\)目标函数在当前位置的梯度
\(\eta\)本节固定学习率;其他资料常写成 \(\alpha\)

上一节已经推导出收敛条件 \(0<\eta<2/\nu_{\max}=0.1\)。这里选择 \(\eta=0.08\),它位于稳定区间内。这个学习率在两个方向上的缩放因子分别为:

\[ \begin{aligned} q_1&=1-\eta\nu_1=1-0.08\times1=0.92,\\ q_2&=1-\eta\nu_2=1-0.08\times20=-0.6。 \end{aligned} \]

\(q_1=0.92\) 为正,表示 \(w_1\) 不会跨越零点,但每次只缩小 \(8\%\);\(q_2=-0.6\) 为负,表示 \(w_2\) 每一步都会跨越零点,但振幅缩小为上一轮的 \(60\%\)。下面用完整的向量更新验证这个判断。

第一次更新。 先把初始点代入梯度公式:

\[ \begin{aligned} \mathbf{g}_0 &=\mathbf{g}(\mathbf{w}_0)\\ &=\begin{bmatrix}w_{0,1}\\20w_{0,2}\end{bmatrix}\\ &=\begin{bmatrix}-8\\20\times4\end{bmatrix}\\ &=\begin{bmatrix}-8\\80\end{bmatrix}。 \end{aligned} \]

再把初始梯度代入更新式:

\[ \begin{aligned} \mathbf{w}_1 &=\mathbf{w}_0-\eta\mathbf{g}_0\\ &=\begin{bmatrix}-8\\4\end{bmatrix} -0.08\begin{bmatrix}-8\\80\end{bmatrix}\\ &=\begin{bmatrix}-7.36\\-2.40\end{bmatrix}。 \end{aligned} \]

参数已经从 \((-8,4)\) 移动到 \((-7.36,-2.40)\)。其中,\(w_2\) 从正数变为负数,说明更新跨过了该方向的最低点;\(w_1\) 仍为负数,只向零点靠近了一小段距离。目标函数值则从 \(192\) 降为:

\[ \begin{aligned} f(\mathbf{w}_1) &=\frac{1}{2}w_{1,1}^2+10w_{1,2}^2\\ &=\frac{1}{2}(-7.36)^2+10(-2.40)^2\\ &=27.0848+57.6\\ &=84.6848。 \end{aligned} \]

第二次更新。 先计算当前位置的梯度,再更新参数:

\[ \begin{aligned} \mathbf{g}_1 &=\mathbf{g}(\mathbf{w}_1)\\ &=\begin{bmatrix}-7.36\\20(-2.40)\end{bmatrix}\\ &=\begin{bmatrix}-7.36\\-48\end{bmatrix},\\[6pt] \mathbf{w}_2 &=\mathbf{w}_1-\eta\mathbf{g}_1\\ &=\begin{bmatrix}-7.36\\-2.40\end{bmatrix} -0.08\begin{bmatrix}-7.36\\-48\end{bmatrix}\\ &=\begin{bmatrix}-6.7712\\1.4400\end{bmatrix}。 \end{aligned} \]

此时 \(w_2\) 又从负数变为正数,继续跨越零点;它的绝对值从 \(2.40\) 缩小为 \(1.44\)。目标函数值继续下降:

\[ \begin{aligned} f(\mathbf{w}_2) &=\frac{1}{2}(-6.7712)^2+10(1.44)^2\\ &=22.92457472+20.736\\ &=43.66057472。 \end{aligned} \]

第三次更新。 按照相同顺序计算:

\[ \begin{aligned} \mathbf{g}_2 &=\mathbf{g}(\mathbf{w}_2)\\ &=\begin{bmatrix}-6.7712\\20(1.44)\end{bmatrix}\\ &=\begin{bmatrix}-6.7712\\28.8\end{bmatrix},\\[6pt] \mathbf{w}_3 &=\mathbf{w}_2-\eta\mathbf{g}_2\\ &=\begin{bmatrix}-6.7712\\1.44\end{bmatrix} -0.08\begin{bmatrix}-6.7712\\28.8\end{bmatrix}\\ &=\begin{bmatrix}-6.229504\\-0.864\end{bmatrix}。 \end{aligned} \]

\(w_2\) 再次变号,绝对值从 \(1.44\) 缩小为 \(0.864\);\(w_1\) 则仍然保持负号,绝对值只从 \(6.7712\) 缩小为 \(6.229504\)。目标函数值为:

\[ \begin{aligned} f(\mathbf{w}_3) &=\frac{1}{2}(-6.229504)^2+10(-0.864)^2\\ &=19.403360043008+7.46496\\ &=26.868320043008。 \end{aligned} \]

三次更新验证了开头对两个缩放因子的判断:

  • \(w_2\) 按照 \(4\to-2.4\to1.44\to-0.864\) 在零点两侧振荡,但振幅持续缩小;
  • \(w_1\) 按照 \(-8\to-7.36\to-6.7712\to-6.229504\) 从同一侧缓慢接近零点;
  • 目标函数按照 \(192\to84.6848\to43.66057472\to26.868320043008\) 持续下降。

因此,\(\eta=0.08\) 虽然能够保证整体收敛,却不能同时成为两个方向的理想步长。同一个学习率让陡峭方向反复越过谷底,也让平缓方向只能缓慢前进。这正是条件数较大时,普通梯度下降容易出现之字形轨迹的原因。下一节的牛顿法将利用海森矩阵分别校正两个方向的尺度。

2.4 牛顿法:用曲率重新缩放梯度 #

牛顿法采用以下公式:

\[ \mathbf{w}_{k+1}=\mathbf{w}_k-\mathbf{H}_k^{-1}\mathbf{g}_k。 \]

本例的海森矩阵是对角矩阵,因此可以分别对两个对角元素取倒数:

\[ \begin{aligned} \mathbf{H}^{-1} &=\begin{bmatrix}1/1&0\\0&1/20\end{bmatrix}\\ &=\begin{bmatrix}1&0\\0&0.05\end{bmatrix}。 \end{aligned} \]

把逆海森矩阵和初始梯度代入牛顿步:

\[ \begin{aligned} \Delta\mathbf{w}_0 &=-\mathbf{H}^{-1}\mathbf{g}_0\\ &=-\begin{bmatrix}1&0\\0&0.05\end{bmatrix} \begin{bmatrix}-8\\80\end{bmatrix}\\ &=-\begin{bmatrix}-8\\4\end{bmatrix}\\ &=\begin{bmatrix}8\\-4\end{bmatrix},\\[6pt] \mathbf{w}_1 &=\mathbf{w}_0+\Delta\mathbf{w}_0\\ &=\begin{bmatrix}-8\\4\end{bmatrix} +\begin{bmatrix}8\\-4\end{bmatrix}\\ &=\begin{bmatrix}0\\0\end{bmatrix},\\[6pt] f(\mathbf{w}_1) &=\frac{1}{2}(0)^2+10(0)^2\\ &=0。 \end{aligned} \]

在此例中,牛顿法一步就到达全局极小值,因为目标函数恰好是严格凸二次型,且算法使用了精确的海森矩阵。一般的非线性问题没有这种保证。在工程实现中,程序通常通过求解线性方程组来计算牛顿方向,而不会显式求矩阵的逆;对于稠密的 \(d\times d\) 系统,直接分解的典型计算成本为 \(O(d^3)\)。

2.5 BFGS:从梯度变化中学习曲率 #

名字、目标与初始近似 #

BFGS 由 Broyden、Fletcher、Goldfarb 和 Shanno 四个姓氏的首字母组成,这个名称用于标识与四位研究者相关的拟牛顿更新方法[1]。这四个字母本身并不描述算法的计算步骤;理解 BFGS 的关键,是先看它怎样近似牛顿法需要的曲率信息。

牛顿法使用真实海森矩阵的逆来重新缩放梯度,但在参数很多时,构造、存储和分解完整海森矩阵可能非常昂贵。BFGS 属于拟牛顿法(quasi-Newton method):它不直接计算真实海森矩阵,而是利用相邻两次迭代之间的参数变化和梯度变化,逐步更新一个逆海森矩阵的近似。

具体来说,BFGS 先记录前后两步的位置差和梯度差:

\[ \mathbf{s}_k=\mathbf{w}_{k+1}-\mathbf{w}_k,\qquad \mathbf{y}_k=\mathbf{g}_{k+1}-\mathbf{g}_k。 \]
变量含义
\(\mathbf{s}_k\)第 \(k\) 步产生的参数位移
\(\mathbf{y}_k\)同一步前后的梯度变化;不是监督学习标签 \(y\)
\(\mathbf{V}_k\)第 \(k\) 步对逆海森矩阵的近似
\(\mathbf{p}_k\)第 \(k\) 步的搜索方向

第一次搜索方向与精确线搜索 #

将逆海森矩阵的初始近似设为单位矩阵,并写出文章开头已经计算过的初始梯度:

\[ \begin{aligned} \mathbf{V}_0=\mathbf{I} &=\begin{bmatrix}1&0\\0&1\end{bmatrix},\\ \mathbf{g}_0 &=\begin{bmatrix}-8\\80\end{bmatrix}。 \end{aligned} \]

第一个搜索方向由“逆海森矩阵近似乘以负梯度”得到。把矩阵和梯度的具体数值代入:

\[ \begin{aligned} \mathbf{p}_0 &=-\mathbf{V}_0\mathbf{g}_0\\ &=-\begin{bmatrix}1&0\\0&1\end{bmatrix} \begin{bmatrix}-8\\80\end{bmatrix}\\ &=\begin{bmatrix}8\\-80\end{bmatrix}。 \end{aligned} \]

由于 \(\mathbf{V}_0=\mathbf{I}\),此时 \(\mathbf{p}_0\) 就是初始负梯度方向。向量的第一个分量为正,表示参数沿 \(w_1\) 轴向右移动;第二个分量为负,表示参数沿 \(w_2\) 轴向下移动。

接下来需要决定沿 \(\mathbf{p}_0\) 走多远。为避免与全文学习率 \(\eta\) 混淆,本节把线搜索中的临时标量记为 \(a\);不少教材会把它写成 \(\alpha_k\)。从起点 \(\mathbf{w}_0\) 沿搜索方向移动 \(a\) 倍后,新的候选位置为:

\[ \begin{aligned} \mathbf{w}(a) &=\mathbf{w}_0+a\mathbf{p}_0\\ &=\begin{bmatrix}-8\\4\end{bmatrix} +a\begin{bmatrix}8\\-80\end{bmatrix}\\ &=\begin{bmatrix}-8+8a\\4-80a\end{bmatrix}。 \end{aligned} \]

原来的目标函数有两个变量。将 \(\mathbf{w}(a)\) 代入后,可以把它化为只包含线搜索变量 \(a\) 的一元函数:

\[ \begin{aligned} \phi(a) &=f(\mathbf{w}(a))\\ &=\frac{1}{2}(-8+8a)^2+10(4-80a)^2\\ &=\left(32-64a+32a^2\right) +\left(160-6400a+64000a^2\right)\\ &=64032a^2-6464a+192。 \end{aligned} \]
变量含义
\(a\)沿固定方向试探距离的线搜索变量
\(\mathbf{p}_0\)第一次迭代的搜索方向,本例为 \([8,-80]^\mathsf{T}\)
\(a\mathbf{p}_0\)从起点出发的实际位移;\(a\) 决定沿搜索方向移动多少
\(\mathbf{w}(a)=\mathbf{w}_0+a\mathbf{p}_0\)从 \(\mathbf{w}_0\) 出发,沿 \(\mathbf{p}_0\) 移动 \(a\) 倍后得到的候选位置
\(\phi(a)\)把多变量目标限制在搜索直线上以后得到的一元函数
\(a_0\)第一次线搜索选出的最优步长

精确线搜索要寻找使 \(\phi(a)\) 最小的 \(a\)。由于 \(\phi(a)\) 是开口向上的二次函数,可以令一阶导数等于零:

\[ \begin{aligned} \phi'(a)&=128064a-6464,\\ \phi'(a_0)=0 &\quad\Longrightarrow\quad a_0=\frac{6464}{128064} =\frac{101}{2001} \approx0.050475。 \end{aligned} \]

用参数变化和梯度变化更新曲率 #

将 \(a_0\) 代回 \(\mathbf{w}(a)\),得到第一次迭代后的参数;再代入梯度公式 \(\mathbf{g}(\mathbf{w})=[w_1,20w_2]^\mathsf{T}\),得到新的梯度:

\[ \begin{aligned} \mathbf{w}_1 &=\mathbf{w}(a_0) =\mathbf{w}_0+a_0\mathbf{p}_0\\ &=\begin{bmatrix}-8\\4\end{bmatrix} +\frac{101}{2001} \begin{bmatrix}8\\-80\end{bmatrix}\\ &=\begin{bmatrix}-15200/2001\\-76/2001\end{bmatrix}\\ &\approx\begin{bmatrix}-7.596202\\-0.037981\end{bmatrix}。 \end{aligned} \]\[ \begin{aligned} \mathbf{g}_1 &=\mathbf{g}(\mathbf{w}_1) =\begin{bmatrix}w_{1,1}\\20w_{1,2}\end{bmatrix}\\ &=\begin{bmatrix}-15200/2001\\20(-76/2001)\end{bmatrix}\\ &=\begin{bmatrix}-15200/2001\\-1520/2001\end{bmatrix}\\ &\approx\begin{bmatrix}-7.596202\\-0.759620\end{bmatrix}。 \end{aligned} \]

其中,\(w_{1,1}\) 和 \(w_{1,2}\) 分别表示向量 \(\mathbf{w}_1\) 的第一个和第二个分量。现在可以继续计算位置差和梯度差:

\[ \begin{aligned} \mathbf{s}_0 &=\mathbf{w}_1-\mathbf{w}_0\\ &=\begin{bmatrix}-15200/2001\\-76/2001\end{bmatrix} -\begin{bmatrix}-8\\4\end{bmatrix}\\ &=\begin{bmatrix}808/2001\\-8080/2001\end{bmatrix}\\ &\approx\begin{bmatrix}0.403798\\-4.037981\end{bmatrix}。 \end{aligned} \]\[ \begin{aligned} \mathbf{y}_0 &=\mathbf{g}_1-\mathbf{g}_0\\ &=\begin{bmatrix}-15200/2001\\-1520/2001\end{bmatrix} -\begin{bmatrix}-8\\80\end{bmatrix}\\ &=\begin{bmatrix}808/2001\\-161600/2001\end{bmatrix}\\ &\approx\begin{bmatrix}0.403798\\-80.759620\end{bmatrix}。 \end{aligned} \]

令 \(c_k=1/(\mathbf{y}_k^\mathsf{T}\mathbf{s}_k)\),BFGS 按照下式更新逆海森矩阵的近似:

\[ \begin{aligned} \mathbf{A}_k&=\mathbf{I}-c_k\mathbf{s}_k\mathbf{y}_k^\mathsf{T},\\ \mathbf{B}_k&=\mathbf{I}-c_k\mathbf{y}_k\mathbf{s}_k^\mathsf{T},\\ \mathbf{C}_k&=c_k\mathbf{s}_k\mathbf{s}_k^\mathsf{T},\\ \mathbf{V}_{k+1}&=\mathbf{A}_k\mathbf{V}_k\mathbf{B}_k+\mathbf{C}_k。 \end{aligned} \]
变量含义
\(c_k\)位置变化与梯度变化内积的倒数;BFGS 文献常记为 \(\rho_k\)
\(\mathbf{I}\)与 \(\mathbf{V}_k\) 同维度的单位矩阵
\(\mathbf{s}_k\mathbf{y}_k^\mathsf{T}\)两个向量的外积,结果是矩阵
\(\mathbf{A}_k,\mathbf{B}_k\)BFGS 更新中位于 \(\mathbf{V}_k\) 左右两侧的修正矩阵
\(\mathbf{C}_k\)由本轮参数位移产生的补偿矩阵
\(\mathbf{V}_{k+1}\)加入最新曲率信息后的逆海森矩阵近似

上述更新还要求曲率内积满足 \(\mathbf{y}_k^\mathsf{T}\mathbf{s}_k>0\)。当 \(\mathbf{V}_k\) 正定时,这个条件使标准 BFGS 更新继续保持正定;合适的线搜索通常有助于满足该条件。如果内积非正或过小,工程实现可能跳过、阻尼或修正这次更新,避免除以不稳定的数值。

如果暂时不需要复核精确分数,可以先抓住后面推导的三个结果:第一步从负梯度方向开始;一次 BFGS 更新后,\(\mathbf{V}_1\) 的右下角已经接近真实逆曲率 \(1/20=0.05\);第二次精确线搜索随后到达最低点。下面的分数运算用于展示这三个结果怎样得到。

先把本例的 \(\mathbf{s}_0\) 和 \(\mathbf{y}_0\) 代入 \(c_0\):

\[ \begin{aligned} c_0 &=\frac{1}{\mathbf{y}_0^\mathsf{T}\mathbf{s}_0}\\ &= \frac{1}{ \begin{bmatrix}808/2001&-161600/2001\end{bmatrix} \begin{bmatrix}808/2001\\-8080/2001\end{bmatrix}}\\ &=\frac{2001}{652864}\\ &\approx\frac{1}{0.403798\times0.403798 +(-80.759620)\times(-4.037981)}\\ &\approx\frac{1}{326.268866}\\ &\approx0.003064957。 \end{aligned} \]

然后在 BFGS 更新公式中令 \(k=0\)。为了让矩阵乘法的中间过程更清楚,先分别计算公式中的三个矩阵项:

\[ \begin{aligned} \mathbf{A}_0 &=\mathbf{I}-c_0\mathbf{s}_0\mathbf{y}_0^\mathsf{T}\\ &\approx\mathbf{I} -0.003064957 \begin{bmatrix}0.403798\\-4.037981\end{bmatrix} \begin{bmatrix}0.403798&-80.759620\end{bmatrix}\\ &\approx \begin{bmatrix}0.999500&0.099950\\0.004998&0.000500\end{bmatrix},\\[6pt] \mathbf{B}_0 &=\mathbf{I}-c_0\mathbf{y}_0\mathbf{s}_0^\mathsf{T}\\ &\approx\mathbf{I} -0.003064957 \begin{bmatrix}0.403798\\-80.759620\end{bmatrix} \begin{bmatrix}0.403798&-4.037981\end{bmatrix}\\ &\approx \begin{bmatrix}0.999500&0.004998\\0.099950&0.000500\end{bmatrix},\\[6pt] \mathbf{C}_0 &=c_0\mathbf{s}_0\mathbf{s}_0^\mathsf{T}\\ &\approx0.003064957 \begin{bmatrix}0.403798\\-4.037981\end{bmatrix} \begin{bmatrix}0.403798&-4.037981\end{bmatrix}\\ &\approx \begin{bmatrix}0.000500&-0.004998\\-0.004998&0.049975\end{bmatrix}。 \end{aligned} \]

这里,\(\mathbf{A}_0\) 和 \(\mathbf{B}_0\) 是更新公式左右两侧的修正矩阵,\(\mathbf{C}_0\) 是由本轮参数位移产生的补偿项。现在把这三个数值矩阵和 \(\mathbf{V}_0=\mathbf{I}\) 代回更新公式:

\[ \begin{aligned} \mathbf{V}_1 &=\mathbf{A}_0\mathbf{V}_0\mathbf{B}_0+\mathbf{C}_0\\ &=\frac{1}{4004001} \begin{bmatrix}4042001&190\\190&200201\end{bmatrix}\\ \mathbf{A}_0\mathbf{V}_0\mathbf{B}_0 &\approx \begin{bmatrix}0.999500&0.099950\\0.004998&0.000500\end{bmatrix} \begin{bmatrix}1&0\\0&1\end{bmatrix}\\[-2pt] &\hspace{2em}\times \begin{bmatrix}0.999500&0.004998\\0.099950&0.000500\end{bmatrix}\\ \mathbf{V}_1 &\approx\mathbf{A}_0\mathbf{V}_0\mathbf{B}_0 {}+\begin{bmatrix}0.000500&-0.004998\\-0.004998&0.049975\end{bmatrix}\\ &\approx \begin{bmatrix}1.009491&0.000047\\0.000047&0.050000\end{bmatrix}。 \end{aligned} \]

第二次搜索怎样到达最低点 #

矩阵右下角的元素已经接近真实的逆曲率 \(1/20=0.05\)。继续使用“逆海森矩阵近似乘以负梯度”计算第二个搜索方向:

\[ \begin{aligned} \mathbf{p}_1 &=-\mathbf{V}_1\mathbf{g}_1\\ &=-\begin{bmatrix} 4042001/4004001&190/4004001\\ 190/4004001&200201/4004001 \end{bmatrix}\\[-2pt] &\hspace{2em}\times \begin{bmatrix}-15200/2001\\-1520/2001\end{bmatrix}\\ &=\begin{bmatrix}30704000/4004001\\153520/4004001\end{bmatrix}\\ &\approx\begin{bmatrix}7.668330\\0.038342\end{bmatrix}。 \end{aligned} \]

接下来沿 \(\mathbf{p}_1\) 做第二次精确线搜索。对于海森矩阵为常数的二次型,沿搜索直线的导数为:

\[ \phi_1'(a) =\mathbf{g}_1^\mathsf{T}\mathbf{p}_1 +a\mathbf{p}_1^\mathsf{T}\mathbf{H}\mathbf{p}_1。 \]

令 \(\phi_1'(a_1)=0\),即可得到第二次线搜索的步长:

\[ \begin{aligned} N_1 &=\mathbf{g}_1^\mathsf{T}\mathbf{p}_1\\ &= \begin{bmatrix}-15200/2001&-1520/2001\end{bmatrix} \begin{bmatrix}30704000/4004001\\153520/4004001\end{bmatrix}\\ &=-\frac{233350400}{4004001}\\ &\approx-58.279306,\\[6pt] D_1 &=\mathbf{p}_1^\mathsf{T}\mathbf{H}\mathbf{p}_1\\ &= \begin{bmatrix}30704000/4004001&153520/4004001\end{bmatrix} \begin{bmatrix}1&0\\0&20\end{bmatrix}\\[-2pt] &\hspace{2em}\times \begin{bmatrix}30704000/4004001\\153520/4004001\end{bmatrix}\\ &=\frac{471367808000}{8012006001}\\ &\approx58.832683,\\[6pt] a_1 &=-\frac{N_1}{D_1}\\ &=\frac{2001}{2020}\\ &\approx0.990594。 \end{aligned} \]

其中,\(N_1\) 和 \(D_1\) 分别表示步长公式的分子内积与分母二次型。先分别计算它们,可以避免把两组矩阵乘积挤进同一个嵌套分式。

把 \(a_1\) 代回参数更新公式:

\[ \begin{aligned} \mathbf{w}_2 &=\mathbf{w}_1+a_1\mathbf{p}_1\\ &=\begin{bmatrix}-15200/2001\\-76/2001\end{bmatrix} +\frac{2001}{2020} \begin{bmatrix}30704000/4004001\\153520/4004001\end{bmatrix}\\ &=\begin{bmatrix}-15200/2001\\-76/2001\end{bmatrix} +\begin{bmatrix}15200/2001\\76/2001\end{bmatrix}\\ &=\begin{bmatrix}0\\0\end{bmatrix}。 \end{aligned} \]

这个二维结论可以推广到哪里?

因此,在保留精确分数并采用精确线搜索时,BFGS 在第二步恰好到达原点;如果使用前文经过四舍五入的小数计算,则只会得到原点附近的数值。在满足适当条件并采用精确线搜索时,全量 BFGS 最多可以用 \(d\) 步重建一个 \(d\) 维严格凸二次型所需的曲率信息;非线性、数值误差和非精确线搜索都会改变这个结论[1]。

2.6 L-BFGS:保存有限历史,而不是完整矩阵 #

L-BFGS 是 Limited-memory BFGS 的缩写,其中字母 L 表示 Limited-memory(有限内存)。它不是另一组研究者姓名的首字母,也不表示 linear(线性)或 low-rank(低秩)。这个名称直接说明了它与完整 BFGS 的主要区别:算法限制需要保存的历史信息,从而减少内存占用。

BFGS 在第 \(k\) 次迭代中,需要用逆海森矩阵近似 \(\mathbf{V}_k\) 乘以当前梯度 \(\mathbf{g}_k\),得到搜索方向:

\[ \mathbf{p}_k=-\mathbf{V}_k\mathbf{g}_k。 \]

如果模型有 \(d\) 个待优化参数,\(\mathbf{V}_k\) 就是一个包含 \(d^2\) 个元素的 \(d\times d\) 矩阵。完整 BFGS 显式保存并更新这张矩阵,因此仅曲率状态就需要 \(O(d^2)\) 的空间。L-BFGS 的关键想法是:计算 \(\mathbf{V}_k\mathbf{g}_k\) 并不一定要先把 \(\mathbf{V}_k\) 完整地构造出来。算法只保留最近 \(m\) 组参数位移和梯度变化:

\[ \begin{aligned} \mathbf{s}_i&=\mathbf{w}_{i+1}-\mathbf{w}_i,\\ \mathbf{y}_i&=\mathbf{g}_{i+1}-\mathbf{g}_i,\\ \rho_i&=\frac{1}{\mathbf{y}_i^\mathsf{T}\mathbf{s}_i}。 \end{aligned} \]
符号含义维度
\(\mathbf{V}_k\)第 \(k\) 步对逆海森矩阵的近似\(d\times d\) 矩阵
\(\mathbf{p}_k\)第 \(k\) 步的搜索方向\(d\) 维向量
\(\mathbf{s}_i\)第 \(i\) 步到第 \(i+1\) 步的参数位移\(d\) 维向量
\(\mathbf{y}_i\)同一段迭代中的梯度变化\(d\) 维向量
\(\rho_i\)对位移和梯度变化内积取倒数得到的缩放系数标量
\(m\)保留的最近历史更新对数通常远小于 \(d\)
\(m_k=\min(k,m)\)第 \(k\) 次迭代时实际可用的历史对数;算法最多保留 \(m\) 对,但前 \(m\) 次迭代还没有积累满从 \(0\) 到 \(m\) 的整数

双循环递归(two-loop recursion)指的是:在一次 L-BFGS 更新内部,算法对保存的历史向量执行两次方向相反的遍历。这里的“两次循环”不是额外执行两轮模型训练,而是用两个短循环计算完整 BFGS 矩阵原本要完成的矩阵—向量乘法。第 \(k\) 次迭代只能使用已经产生的 \(m_k\) 组历史,因此循环边界必须随实际历史数量变化。

第一个循环从最新的历史记录向最早的记录倒序遍历。它从当前梯度开始,逐步提取各组历史变化对应的系数:

\[ \begin{aligned} \mathbf{q}&\leftarrow\mathbf{g}_k,\\ \alpha_i&=\rho_i\mathbf{s}_i^\mathsf{T}\mathbf{q},\\ \mathbf{q}&\leftarrow\mathbf{q}-\alpha_i\mathbf{y}_i, \qquad i=k-1,\ldots,k-m_k。 \end{aligned} \]

接着,算法用一个容易存储的初始近似 \(\mathbf{V}_k^{(0)}\) 对 \(\mathbf{q}\) 缩放。如果至少已有一组历史,常见做法是根据最近一组 \(\mathbf{s}_{k-1}\) 和 \(\mathbf{y}_{k-1}\) 计算标量 \(\gamma_k\),再用 \(\gamma_k\mathbf{I}\) 作为初始近似:

\[ \begin{aligned} \mathbf{r}&\leftarrow\mathbf{V}_k^{(0)}\mathbf{q} =\gamma_k\mathbf{q},\\ \gamma_k&=\frac{\mathbf{s}_{k-1}^\mathsf{T}\mathbf{y}_{k-1}} {\mathbf{y}_{k-1}^\mathsf{T}\mathbf{y}_{k-1}}。 \end{aligned} \]

第一次迭代时,\(k=0\)、\(m_0=0\),此时还没有 \(\mathbf{s}_{-1}\) 或 \(\mathbf{y}_{-1}\),所以不能使用上面的 \(\gamma_k\) 公式。一个常见初始化是直接取:

\[ \mathbf{V}_0^{(0)}=\mathbf{I}。 \]

由于没有历史对,第一次和第二次循环都不执行。于是中间向量和第一个搜索方向依次为:

\[ \begin{aligned} \mathbf{q}&=\mathbf{g}_0,\\ \mathbf{r}&=\mathbf{I}\mathbf{q}=\mathbf{g}_0,\\ \mathbf{p}_0&=-\mathbf{r}=-\mathbf{g}_0。 \end{aligned} \]

因此,L-BFGS 的第一步通常从负梯度方向出发;完成第一次参数更新并得到第一组 \((\mathbf{s}_0,\mathbf{y}_0)\) 后,后续迭代才可以利用历史信息计算 \(\gamma_k\) 和曲率修正。

第二个循环再从最早的记录向最新的记录正序遍历,把参数位移所携带的曲率修正依次加回去:

\[ \begin{aligned} \beta_i&=\rho_i\mathbf{y}_i^\mathsf{T}\mathbf{r},\\ \mathbf{r}&\leftarrow\mathbf{r} {}+\mathbf{s}_i\left(\alpha_i-\beta_i\right), \qquad i=k-m_k,\ldots,k-1,\\ \mathbf{p}_k&=-\mathbf{r}。 \end{aligned} \]
符号含义需要保存的数量
\(\mathbf{q},\mathbf{r}\)两次循环使用的临时工作向量各一个 \(d\) 维向量
\(\alpha_i\)第一轮计算、第二轮继续使用的递归系数每组可用历史一个标量,共 \(m_k\) 个
\(\rho_i\)每组历史的内积缩放系数当前共 \(m_k\) 个,最多 \(m\) 个
\(\beta_i\)第二轮当前这组历史的递归系数一个可复用的临时标量
\(\mathbf{V}_k^{(0)}\)双循环开始时采用的简单逆海森矩阵近似无历史时可取 \(\mathbf I\);有历史后通常用 \(\gamma_k\mathbf{I}\) 表示
\(\gamma_k\)根据最近一组历史计算的初始缩放系数有至少一组历史时定义的标量

经过这两次遍历,\(\mathbf{r}\) 得到的正是 L-BFGS 对 \(\mathbf{V}_k\mathbf{g}_k\) 的隐式计算结果。第 \(k\) 次迭代实际保存 \(m_k\) 个 \(\mathbf{s}_i\)、\(m_k\) 个 \(\mathbf{y}_i\)、少量长度为 \(d\) 的工作向量,以及 \(O(m_k)\) 个标量。历史填满以后,最大空间计数可以写成 \(O(2md+2d+2m)\),在 \(m\ll d\) 时通常简写为 \(O(md)\)。完整 BFGS 则必须保存 \(d^2\) 个矩阵元素,所以参数维度很大时,两者的内存需求会迅速拉开。

所谓“有限内存”,限制的是保存的更新对数量,而不是把参数维度 \(d\) 变小,也不是把完整 BFGS 矩阵截断后继续保存。BFGS 和 L-BFGS 采用相同的割线更新思想,但保存的状态和计算搜索方向的方式不同,因此不能把同一条数值轨迹同时视为两种算法的结果。

本章小结:

  • 梯度下降只使用当前梯度;当所有方向共用一个学习率时,稳定性上限由曲率最大的方向决定,因此条件数较大时容易振荡并缓慢收敛。
  • 牛顿法用真实曲率重新缩放梯度;BFGS 根据参数与梯度变化逐步近似曲率,两者都用更多计算或状态换取更合适的搜索方向。
  • L-BFGS 不保存完整的 \(d\times d\) 矩阵,而是用有限历史隐式计算搜索方向,把曲率状态的空间复杂度从 \(O(d^2)\) 降到 \(O(md)\)。

这些算法差异又留下了一个工程问题:当二维参数扩展到成千上万维,并与完整训练数据一起存入内存时,算法状态究竟占多少空间?下一章把讨论从单次更新的数学规则扩展到完整训练任务的内存规模。

3. 从算法状态到训练规模:内存与高维计算 #

第二章中的 \(d\) 只表示参数维度,还没有把样本矩阵、预测值、残差和临时工作区纳入同一套计算。实际训练的内存同时受到样本数 \(n\)、参数维度 \(d\)、数值精度和优化器状态影响。本章先建立一套可复核的内存估算口径,再讨论小样本、高维数据可以利用哪些结构来避免大型显式矩阵。

3.1 从数组大小到训练峰值:内存怎样估算? #

只写“梯度下降需要 \(O(d)\) 空间,BFGS 需要 \(O(d^2)\) 空间”,还不足以估算一个训练任务会占用多少内存。实际训练既要保存数据,也要保存参数、梯度、搜索方向和优化器状态。本节先用一个具体的线性回归问题定义 \(n\) 和 \(d\),再用同一套计算口径比较梯度下降、牛顿法、BFGS 和 L-BFGS。最后分别固定 \(d\) 与 \(n\),观察样本数和参数维度怎样影响内存。

一个具体的回归例子:\(n\) 和 \(d\) 分别是什么? #

假设我们收集了 10,000 套住宅的成交记录,希望根据每套住宅的 20 个特征预测成交价格。这些特征可以包括面积、卧室数、房龄、区位指标和交通距离。将数据写成矩阵形式:

\[ \begin{aligned} X&= \begin{bmatrix} \mathbf{x}_1^\mathsf{T}\\ \mathbf{x}_2^\mathsf{T}\\ \vdots\\ \mathbf{x}_n^\mathsf{T} \end{bmatrix} \in\mathbb{R}^{n\times d},\\ \mathbf{y}&\in\mathbb{R}^{n}。 \end{aligned} \]

矩阵的一行 \(\mathbf{x}_i^\mathsf{T}\) 表示一套住宅,一列表示一个输入特征。因此,本例的样本数为 \(n=10{,}000\),特征数为 \(d=20\),设计矩阵 \(X\) 的形状为 \(10{,}000\times20\)。目标向量 \(\mathbf{y}\) 保存 10,000 个成交价格。在线性回归中,模型为:

\[ \hat{\mathbf{y}}=X\mathbf{w}, \qquad \mathbf{w}\in\mathbb{R}^{d}。 \]

本节采用不含截距的单输出线性回归,所以 \(d=20\) 既是 \(X\) 的列数,也是需要优化的参数数量。这个等式并不适用于所有模型。例如,神经网络的输入特征数通常不等于可训练参数数;此时应另外用参数数量计算梯度和优化器状态。

符号在回归问题中的含义形状
\(X\)设计矩阵,汇总全部输入样本\(n\times d\)
\(\mathbf{x}_i\)第 \(i\) 条样本的全部特征\(d\) 维向量
\(\mathbf{y}\)全部样本的真实连续目标值\(n\) 维向量
\(\mathbf{w}\)线性回归需要学习的系数\(d\) 维向量
\(\hat{\mathbf{y}}\)模型对全部样本给出的预测值\(n\) 维向量
\(n\)样本数量,即住宅数量和 \(X\) 的行数本例为 10,000
\(d\)每套住宅的特征数量;在本例中也等于参数数量本例为 20

为了让后面的数字可以手工复核,本节还采用以下简化假设:\(X\) 和 \(\mathbf{y}\) 一次完整载入内存;\(X\) 是已经完成清洗和数值化的稠密矩阵;所有数组都使用 float32;L-BFGS 保存最近 \(m=10\) 组历史。本节不把原始字符串、类别对象、pandas 索引和列标签、缺失值掩码、稀疏矩阵索引、预处理副本或框架内存池计入核心工作集。

这些假设只用于建立统一的比较基线。词袋表示、one-hot 编码等高维稀疏特征通常适合采用稀疏存储,此时内存由非零元素和索引类型决定;小批量训练也只需把当前批次放入计算设备。两种情况都不能直接套用本节的全量稠密矩阵结果。

比较四种算法的核心工作集 #

先计算输入矩阵。若每个元素占用 \(b\) 字节,\(X\) 的底层数值缓冲区为:

\[ M_X=n\times d\times b。 \]
符号含义本例取值或单位
\(M_X\)矩阵 \(X\) 的原始数据缓冲区大小字节(byte,B)
\(n\)样本数,即矩阵的行数基准情景为 10,000
\(d\)特征数,也是本例线性模型需要优化的参数数基准情景为 20
\(b\)每个元素占用的字节数float64 为 8,float32 为 4,float16 为 2

不同 Python 工具对默认精度的处理并不完全相同。pandas 的浮点数据通常使用 float64,PyTorch 和 TensorFlow/Keras 通常默认使用 float32,而 scikit-learn 的行为取决于输入和估计器。工程中应检查实际数组的 dtype,不能只根据工具名称推断精度。具体行为可查阅 pandas 数据类型文档、scikit-learn 的 as_float_array 文档、TensorFlow/Keras 默认浮点类型文档、TensorFlow 混合精度指南和 PyTorch 默认浮点类型文档。以本例的 float32 为准,每个元素占 \(b=4\) 字节,因此:

\[ \begin{aligned} M_X &=n\times d\times b\\ &=10{,}000\times20\times4\\ &=800{,}000\ \text{B}\\ &=\frac{800{,}000}{1{,}000{,}000}\ \text{MB}\\ &=0.8\ \text{MB}。 \end{aligned} \]

这个结果只包含 \(X\)。为了比较训练算法,假设程序在同一时刻还保存目标向量 \(\mathbf{y}\)、参数 \(\mathbf{w}\)、梯度 \(\mathbf{g}\)、搜索方向 \(\mathbf{p}\)、预测向量 \(\hat{\mathbf{y}}\) 和残差向量 \(\mathbf{e}\)。这里用 \(\mathbf{e}\) 表示残差,避免与 L-BFGS 双循环中的工作向量 \(\mathbf{r}\) 混淆。这七项组成四种算法共有的核心工作集:

\[ \begin{aligned} M_{\text{common}} &=M_X+M_y+M_w+M_g+M_p+M_{\hat{y}}+M_e\\ &=b\left(nd+n+d+d+d+n+n\right)\\ &=b\left(nd+3n+3d\right)。 \end{aligned} \]

共同工作集之外,不同算法还要保存不同的优化状态。这里讨论的是显式保存稠密海森矩阵的牛顿法:梯度下降不保存曲率矩阵;牛顿法保存海森矩阵;BFGS 保存逆海森矩阵近似;L-BFGS 保存历史向量和双循环缓存。假设这些对象同时存在并使用相同精度,可得:

\[ \begin{aligned} M_{\text{GD, core}} &=b\left(nd+3n+3d\right),\\ M_{\text{Newton, core}} &=b\left(nd+3n+3d+d^2\right),\\ M_{\text{BFGS, core}} &=b\left(nd+3n+3d+d^2\right),\\ M_{\text{L-BFGS, core}} &=b\left(nd+3n+5d+2md+2m+2\right)。 \end{aligned} \]
公式部分对应的内存内容受 \(n\) 影响受 \(d\) 影响
\(nd\)特征矩阵 \(X\)✓✓
\(3n\)目标值、预测值和残差✓—
\(3d\)参数、梯度和搜索方向—✓,线性增长
\(d^2\)牛顿法的海森矩阵或 BFGS 的逆海森矩阵近似—✓,平方增长
\(2md\)L-BFGS 的 \(m\) 组历史向量对—✓;固定 \(m\) 时线性增长
\(2d+2m+2\)L-BFGS 的工作向量和递归标量—主要随 \(d\) 线性增长

现在把 \(n=10{,}000\)、\(d=20\)、\(m=10\) 和 \(b=4\) 代入。这个基准例子用于核对每一项怎样进入总量:

内存内容元素数量内存梯度下降牛顿法BFGSL-BFGS
特征矩阵 \(X\)\(nd=200{,}000\)0.800 MB✓✓✓✓
目标向量 \(\mathbf{y}\)\(n=10{,}000\)0.040 MB✓✓✓✓
预测向量 \(\hat{\mathbf{y}}\)\(n=10{,}000\)0.040 MB✓✓✓✓
残差向量 \(\mathbf{e}\)\(n=10{,}000\)0.040 MB✓✓✓✓
参数、梯度和搜索方向\(3d=60\)240 B✓✓✓✓
海森矩阵\(d^2=400\)1.6 KB—✓——
逆海森矩阵近似\(d^2=400\)1.6 KB——✓—
历史向量对\(2md=400\)1.6 KB———✓
双循环工作向量\(2d=40\)160 B———✓
双循环递归标量\(2m+2=22\)88 B———✓
估算总量——0.920240 MB0.921840 MB0.921840 MB0.922088 MB

下表统一使用十进制单位:\(1\ \text{KB}=1{,}000\ \text{B}\)、\(1\ \text{MB}=1{,}000{,}000\ \text{B}\)、\(1\ \text{GB}=10^9\ \text{B}\)、\(1\ \text{TB}=10^{12}\ \text{B}\)。在这个低维基准中,四种算法相差不到 2 KB,因为数据和长度为 \(n\) 的向量已经占据主要部分。要看清 \(d^2\) 与 \(2md\) 的差别,必须分别控制 \(n\) 和 \(d\)。

固定 \(d=20\):增加样本数 \(n\) #

把共同工作集改写为 \(M_{\text{common}}=b[n(d+3)+3d]\) 后,可以看到:固定 \(d\) 时,增加样本只会扩大 \(X\)、目标值、预测值和残差。若样本数从 \(n\) 增加到 \(cn\),四种算法都会增加同样的核心内存:

\[ \Delta M_n=b(c-1)n(d+3)。 \]

下面固定 \(d=20\)、\(m=10\) 和 float32,只把样本数从 1,000 增加到 100,000:

样本数 \(n\)\(X\) 本身梯度下降牛顿法BFGSL-BFGS
1,00080 KB92.240 KB93.840 KB93.840 KB94.088 KB
10,0000.800 MB0.920240 MB0.921840 MB0.921840 MB0.922088 MB
100,0008.000 MB9.200240 MB9.201840 MB9.201840 MB9.202088 MB

样本数扩大时,四种方法的数据部分以相同速度增长。牛顿法和 BFGS 的 \(d^2\) 矩阵始终只有 1.6 KB,L-BFGS 的额外历史与递归状态也保持在 1.848 KB,因此四种总量越来越接近。这个实验说明:固定低维参数数量以后,增加 \(n\) 主要扩大所有算法共同承担的数据和预测缓存,而不会放大 BFGS 与 L-BFGS 的结构差异。

固定 \(n=10{,}000\):增加参数维度 \(d\) #

固定 \(n\) 时,\(X\) 和普通工作向量随 \(d\) 线性增长。牛顿法和 BFGS 的 \(d^2\) 项按平方增长,而固定 \(m\) 的 L-BFGS 状态仍然按线性规模增长。下面固定 \(n=10{,}000\)、\(m=10\) 和 float32:

参数数量 \(d\)\(X\) 本身梯度下降牛顿法BFGSL-BFGS
200.800 MB0.920240 MB0.921840 MB0.921840 MB0.922088 MB
10,000400 MB400.240 MB800.240 MB800.240 MB401.120 MB
100,0004 GB4.001 GB44.001 GB44.001 GB4.010 GB
1,000,00040 GB40.012 GB4.040 TB4.040 TB40.100 GB

以 \(n=10{,}000\)、\(d=100{,}000\) 为例,梯度下降的核心工作集约为 4.001 GB。牛顿法和 BFGS 还要加入 \(d^2b=40\) GB 的稠密矩阵,因此总量约为 44.001 GB;L-BFGS 的历史向量、工作向量和递归标量合计约为 8.800 MB,因此总量约为 4.010 GB。到了 \(d=1{,}000{,}000\),牛顿法和 BFGS 的矩阵单独占用 4 TB,而 L-BFGS 的额外状态仍约为 88 MB。

结论:公式估算数量级,运行时监控确认峰值 #

这两组控制变量实验说明,\(n\) 和 \(d\) 通过不同机制影响内存。增加 \(n\) 会扩大所有方法共同使用的 \(X\)、目标值、预测值和残差;增加 \(d\) 不仅扩大 \(X\) 和普通工作向量,还会让牛顿法和 BFGS 的稠密矩阵按 \(d^2\) 增长。L-BFGS 用固定数量的历史向量代替完整矩阵,所以它的额外状态在固定 \(m\) 时按 \(md\) 增长。不过,L-BFGS 只减少优化器状态,并不会消除 \(X\) 本身的 \(nd\) 成本。

下表的“训练状态”不包括 \(X\)、\(\mathbf{y}\)、预测值和残差,只比较与参数更新直接相关的向量或矩阵:

方法训练状态状态空间复杂度本节首先观察到的限制
梯度下降参数、梯度和搜索方向,不保存曲率矩阵\(O(d)\)对尺度和条件数敏感
稠密牛顿法海森矩阵\(O(d^2)\)构造、保存和分解海森矩阵的成本较高
BFGS逆海森矩阵近似\(O(d^2)\)高维问题的矩阵内存迅速增长
L-BFGS最近 \(m\) 组历史及双循环缓存\(O(md)\)内存较低,但仍需适合光滑目标和线搜索的条件

上述数字仍然只是可以由形状推导的核心工作集,不是 pandas、scikit-learn、TensorFlow 或 PyTorch 的实测峰值。完整进程还可能同时保留数据副本、类型转换结果、数值库工作区和框架内存池。工程上真正关心的是任意时刻仍然存活的对象总量的最大值:

\[ \begin{aligned} M_{\text{peak}} =\max_t\Bigl\{&M_{\text{core}}(t)+M_{\text{workspace}}(t)\\ &{}+M_{\text{copy}}(t)+M_{\text{framework}}(t) \Bigr\}。 \end{aligned} \]

其中,\(t\) 表示执行时刻。把各内存项写成 \(t\) 的函数,是为了强调其存活量会随执行过程变化;\(M_{\text{workspace}}\) 是矩阵乘法、矩阵分解和线搜索使用的临时空间;\(M_{\text{copy}}\) 是数据转换或设备传输产生的副本;\(M_{\text{framework}}\) 包括索引、对象元数据和内存池等框架开销。这些对象不一定同时存在,所以不能把程序创建过的全部对象无条件相加。更可靠的工程方法是先用本节公式估算数量级,再通过进程或设备内存监控确认实际峰值。

3.2 小样本、高维数据:怎样避免直接计算大型矩阵? #

上一节分别增加了样本数 \(n\) 和参数维度 \(d\)。其中一种特别棘手的情形是样本很少、特征很多:

\[ n\ll d。 \]

例如,研究人员可能只有 1,000 个实验样本,却为每个样本记录了 100,000 个基因、波长通道或图像特征。在线性模型中,这意味着 \(X\in\mathbb{R}^{n\times d}\),而参数向量 \(\mathbf{w}\in\mathbb{R}^d\)。困难不只是 \(d\times d\) 矩阵占用大量内存。因为 \(X\) 的秩最多为 \(\min(n,d)=n\),当 \(n

符号含义
\(n\ll d\)样本数远小于特征数或线性模型的参数数
\(\operatorname{rank}(X)\)矩阵 \(X\) 中线性独立方向的数量,简称矩阵的秩
\(\min(n,d)\)\(n\) 和 \(d\) 中较小的一个,也是 \(X\) 的秩所能达到的上限

下面这些方法利用的结构并不相同,组合使用也不一定带来额外收益。选择之前,可以先判断数据是否具备相应的稀疏性、低秩性或样本—参数规模关系。

方法核心原理主要假设或适用条件
稀疏矩阵存储只保存非零值及其位置,不为大量零值分配完整空间\(X\) 中确实有大量零值,而且节省的数值空间足以抵消行列索引开销
稀疏参数与特征筛选用 Lasso、Elastic Net 或筛选规则让大量参数变为零,减少有效特征数只有少量特征真正有用,或者可以接受稀疏近似
低秩逼近用少数主要方向近似 \(X\) 或曲率矩阵数据的大部分有效变化集中在少数方向,舍弃其余方向不会丢失关键预测信息
PCA 或截断 SVD先把 \(d\) 个相关特征压缩为 \(r\ll d\) 个方向,再训练模型高方差方向保留了足够的预测信息;无监督降维并不保证保留与目标最相关的方向
对偶形式当 \(n\ll d\) 时,把主要计算从 \(d\times d\) 参数空间转换到 \(n\times n\) 样本空间模型和正则项允许这种代数变换,例如 Ridge 回归
矩阵—向量乘积只计算 \(\mathbf{H}\mathbf{v}\),不显式构造或保存完整海森矩阵 \(\mathbf{H}\)优化器或自动微分系统能够直接提供海森矩阵—向量积
迭代线性求解器用共轭梯度或 LSQR 逐步逼近线性方程的解,避免直接求逆和完整矩阵分解可以接受近似解;收敛速度仍取决于条件数和预条件方法
L-BFGS保存最近 \(m\) 组参数和梯度变化,用双循环递归计算搜索方向目标函数较光滑,有限历史能够提供有用的曲率近似
分块或流式计算分批计算 \(X\mathbf{w}\) 和 \(X^\mathsf{T}\mathbf{e}\),避免一次把所有数据与中间结果放入设备内存运算可以按批次累积,并且数据读取成本可以接受

利用稀疏性质 #

如果 \(X\) 的绝大多数元素为零,稠密存储仍然需要保存 \(nd\) 个数值。稀疏格式只保存 \(\operatorname{nnz}(X)\) 个非零值以及相应索引,因此其主要存储量更接近:

\[ O\!\left(\operatorname{nnz}(X)\right) \quad\text{而不是}\quad O(nd)。 \]
符号含义
\(\operatorname{nnz}(X)\)矩阵 \(X\) 中非零元素的数量,名称来自 number of nonzeros
\(O(\operatorname{nnz}(X))\)内存主要随非零元素数量增长;实际格式还要保存行或列索引

这种技巧适合词袋、one-hot 编码和部分推荐系统数据,但“矩阵稀疏”不等于“最优参数稀疏”。前者描述 \(X\) 中有很多零值,后者描述 \(\mathbf{w}\) 中只有少数非零系数;Lasso 主要利用和鼓励的是后者。

利用低秩结构 #

如果高维特征之间存在强相关性,数据可能主要集中在少数方向上。截断奇异值分解(truncated SVD)可以将 \(X\) 近似写成:

\[ X\approx U_r\Sigma_rV_r^\mathsf{T}, \qquad r\ll\min(n,d)。 \]
符号含义维度
\(r\)保留的主要方向数量,也是低秩近似的秩标量,远小于 \(n\) 和 \(d\)
\(U_r\)样本在 \(r\) 个主要方向上的表示\(n\times r\)
\(\Sigma_r\)保留下来的 \(r\) 个奇异值组成的对角矩阵\(r\times r\)
\(V_r\)原始特征到主要方向的映射\(d\times r\)

后续计算可以围绕 \(r\) 个方向进行,而不必始终处理全部 \(d\) 个特征。不过,低秩逼近是一种有损近似:方差较小的方向仍可能包含重要的预测信号,所以 \(r\) 不能只根据内存大小决定,还需要通过验证数据检查预测损失。

把计算转换到样本空间 #

某些带正则化的线性模型既可以在参数空间中求解,也可以利用矩阵恒等式转换到样本空间。当 \(n\ll d\) 时,这种转换可以把主要线性系统从 \(d\times d\) 缩小为 \(n\times n\)。这并不意味着样本空间形式永远更快:实际成本还取决于矩阵是否稀疏、矩阵乘法的实现和求解精度。第四章会先定义最小二乘目标,第五章再以 Ridge 为例,从目标函数逐步推导参数空间和样本空间的两种形式。

避免显式构造矩阵 #

公式中的 \(\mathbf H^{-1}\mathbf g\) 容易让人误以为程序必须先计算逆矩阵。实际实现通常不显式构造 \(\mathbf H^{-1}\),而是直接求解线性方程组:

\[ \mathbf H\mathbf p=-\mathbf g。 \]

这里,\(\mathbf p\) 是需要求出的搜索方向。对于适合直接分解的矩阵,可以使用 Cholesky、QR 或其他矩阵分解;对于更大的系统,可以使用共轭梯度等迭代方法。直接解方程通常比“先求逆、再相乘”更稳定,也避免保存一个不必要的逆矩阵,但仍可能需要保存或访问 \(\mathbf H\)。如果连 \(\mathbf H\) 本身都过大,就需要进一步利用矩阵—向量乘积。

有些优化器只需要海森矩阵作用在一个向量上的结果,而不需要海森矩阵本身:

\[ \mathbf{z}=\mathbf{H}\mathbf{v}。 \]
符号含义
\(\mathbf{H}\)目标函数的海森矩阵;算法不一定显式保存它
\(\mathbf{v}\)迭代求解器给出的试探方向
\(\mathbf{z}\)海森矩阵—向量乘积的结果

自动微分可以直接计算这种海森矩阵—向量积(Hessian–vector product, HVP),截断牛顿法和共轭梯度法等方法再利用这些乘积逐步求方向。这样可以避开 \(O(d^2)\) 的显式矩阵存储,但不会让计算自动变得容易:如果条件数很大,迭代求解器仍可能需要很多步;实际实现也可能需要预条件器来改善收敛。

这些技巧解决的问题并不相同。稀疏存储利用“零值很多”,低秩逼近利用“有效方向很少”,对偶形式利用“样本数远小于参数数”,矩阵—向量乘积和 L-BFGS 则改变曲率信息的计算与保存方式。选择方法时,可以先确认数据具备哪一种结构,再判断相应方法是否合适。

3.3 从全批量梯度到小批量训练:样本规模怎样改变更新方式? #

第 3.2 节主要讨论 \(d\) 很大时,怎样避免保存大型参数空间矩阵。另一类常见问题是样本数 \(n\) 很大:即使每条样本只有少量特征,完整数据矩阵 \(X\) 也可能无法一次装入内存或显存。此时,优化算法不仅要决定“沿哪个方向更新”,还要决定“每次用哪些数据、以什么结构估计这个方向”。

全批量梯度为什么需要扫描所有样本? #

以平均经验损失为例,完整训练集上的梯度为:

\[ \nabla\mathcal L(\mathbf w) =\frac{1}{n} \sum_{i=1}^{n} \nabla_{\mathbf w}\ell_i(\mathbf w)。 \]
新变量或记号含义
\(\ell_i(\mathbf w)\)参数为 \(\mathbf w\) 时,第 \(i\) 条样本产生的损失
\(\nabla_{\mathbf w}\ell_i(\mathbf w)\)第 \(i\) 条样本对参数梯度的贡献
\(\nabla\mathcal L(\mathbf w)\)对全部 \(n\) 条样本取平均后得到的全批量梯度

全批量梯度下降(batch gradient descent) 每次更新都使用这 \(n\) 条样本:

\[ \mathbf w_{k+1} =\mathbf w_k-\eta\nabla\mathcal L(\mathbf w_k)。 \]

因为每次都使用相同的完整训练集,全批量梯度在参数固定时是确定的;代价是每更新一次参数,就要扫描全部数据。数据可以分块读取并累积精确梯度,因此“全批量梯度”不一定要求 \(X\) 同时驻留在设备内存中,但一次参数更新仍要处理完整训练集。

小批量怎样估计全批量梯度? #

小批量梯度下降(mini-batch gradient descent) 在第 \(k\) 步只使用一组样本 \(B_k\) 构造梯度估计。在均匀随机抽样并采用适当归一化时,该估计通常是全批量梯度的无偏估计;使用分层、过采样或其他自定义采样方案时,则需要另外检查抽样权重。令批量大小为 \(b_k=|B_k|\),则:

\[ \begin{aligned} \mathbf g_k &=\frac{1}{b_k} \sum_{i\in B_k} \nabla_{\mathbf w}\ell_i(\mathbf w_k),\\ \mathbf w_{k+1} &=\mathbf w_k-\eta\mathbf g_k。 \end{aligned} \]
新变量或记号含义
\(B_k\)第 \(k\) 次更新使用的样本索引集合
\(b_k=\lvert B_k\rvert\)当前批次包含的样本数;竖线表示集合大小
\(\mathbf g_k\)当前小批量给出的梯度估计
训练轮次(epoch)训练过程累计处理约一遍完整训练集;一个训练轮次通常包含多次参数更新

三种常见叫法的区别在于每次更新使用多少样本:

方法每次更新使用的数据主要特点
全批量梯度下降全部 \(n\) 条样本梯度确定,但每次更新都要扫描完整训练集
随机梯度下降(SGD)严格定义下为 1 条样本更新频繁、单步成本低,但梯度噪声较大
小批量梯度下降\(1在内存、矩阵计算效率和梯度稳定性之间折中

工程语境中的“SGD”有时也泛指使用随机小批量的梯度方法,并不一定表示每次只使用一条样本。阅读论文或软件文档时,应继续确认其 batch_size 和梯度归一化方式。

随机打乱什么时候会破坏训练假设? #

小批量训练并不等于把所有数据行无条件随机打乱。判断一个任务能否这样抽样,需要先区分三件事:训练、验证和测试集怎样划分;单个训练样本怎样构造;训练集中的完整样本以什么顺序送入模型。第一项决定评估是否泄漏未来信息,第二项决定样本是否保留模型需要的上下文,第三项才是通常由 shuffle 或采样器控制的读取顺序。

以零售需求预测为例,假设模型使用过去 28 天预测未来 7 天。一个训练样本应当是保持内部时间顺序的完整窗口:

\[ \underbrace{(y_{t-27},\ldots,y_t)}_{\text{过去 28 天}} \longrightarrow \underbrace{(y_{t+1},\ldots,y_{t+7})}_{\text{未来 7 天}}。 \]

训练、验证和测试窗口必须按照预测时点向前切分,不能让未来窗口进入训练集,再用更早的数据评估。Scikit-learn 的 TimeSeriesSplit 正是为了避免这种“用未来训练、用过去评估”的时间泄漏。完成时间切分以后,某些无状态模型可以在训练区间内把完整窗口随机排列成小批量;TensorFlow 的时间序列教程也采用“先构造连续窗口,再批量读取窗口”的方式。这里可以打乱的是完整窗口的读取顺序,而不是窗口内部的日期、输入与标签的对应关系。

如果模型需要在相邻批次之间连续传递隐藏状态,批次顺序和序列边界还必须与状态管理方式一致。即使模型无状态,构造滞后量、滚动统计量或目标编码时也只能使用预测时点之前可获得的信息;随机拆分高度重叠的窗口,还可能让训练集和验证集共享几乎相同的历史片段,使评估结果过于乐观。

限制也不只出现在时间序列中。以正类比例只有 \(0.1\%\) 的欺诈检测为例,随机抽取 64 条样本时,许多批次可能完全没有正类,因此该批次的损失与梯度中没有来自正类样本的直接贡献,模型也难以从这些批次学习欺诈样本的特征。分层采样、类别加权或专门的批次采样器可以缓解这个问题,但过度采样又会改变训练批次中的类别分布;验证和概率校准仍应反映真实业务分布。相比之下,普通图片分类通常把一张图片及其标签视为一个完整样本,在固定数据划分以后随机排列训练样本通常不会破坏样本内部结构。PyTorch 的 DataLoader 教程展示的就是这种独立样本场景。

任务或数据结构训练样本能否通常随机排列批次构造必须保留什么
独立图片分类通常可以先固定训练、验证和测试划分;每张图片及其标签保持完整
稀有事件分类可以,但需要控制批次构成正负样本覆盖、损失权重,以及验证集中的真实发生率
零售需求预测不能随机拆分时间轴;完整窗口能否排列取决于模型状态窗口内部顺序、预测时点、滞后特征和时间验证边界
序列分类或跨批次传递状态的 RNN取决于状态是否跨批次延续序列内部顺序、序列边界和隐藏状态连续性
排序或成组损失不能把相关样本任意拆散同一查询、用户、会话或比较组中的样本关系

因此,小批量梯度能否合理估计全批量梯度,不只取决于 \(b_k\) 的大小,还取决于抽样方案是否保留损失函数依赖的时间、分组和类别结构,以及是否采用了必要的抽样权重。小批量训练是一种计算策略,不会自动决定正确的数据划分和样本定义。

一个内存例子:800 MB 怎样缩小为 81.92 KB? #

继续使用本章的住宅回归场景,但把样本数扩大到 \(n=10{,}000{,}000\),保持 \(d=20\) 和 float32。完整特征矩阵的数值缓冲区需要:

\[ \begin{aligned} M_X &=n\times d\times b\\ &=10{,}000{,}000\times20\times4\\ &=800{,}000{,}000\ \text{B}\\ &=800\ \text{MB}。 \end{aligned} \]

如果每次只把 \(b_k=1{,}024\) 条样本送入计算设备,那么当前批次的特征缓冲区为:

\[ \begin{aligned} M_{X,B_k} &=b_k\times d\times b\\ &=1{,}024\times20\times4\\ &=81{,}920\ \text{B}\\ &=81.92\ \text{KB}。 \end{aligned} \]
新变量或记号含义本例取值
\(M_{X,B_k}\)当前小批量特征矩阵的数值缓冲区81.92 KB
\(b_k\)当前批量的样本数1,024
\(d\)每条样本的特征数20
\(b\)每个 float32 数值占用的字节数4 B

这并不表示整个训练进程只需要 81.92 KB。程序还要保存标签、参数、梯度、优化器状态、数据读取缓存和框架工作区。这个计算只说明:当前批次的特征数据由全批量稠密矩阵的 \(O(nd)\) 缩小为 \(O(b_kd)\)。完整数据仍然要保存在主机内存、磁盘或分布式存储中,并在训练期间被持续读取。

批量越小越好吗? #

批量也不是越小越好。较小的批量减少单步内存,却会增加梯度方差和更新次数;较大的批量通常更容易发挥矩阵运算和 GPU 并行效率,却需要更多设备内存。改变批量大小以后,学习率、训练轮数和停止条件也可能需要重新验证。第 7.3 节会回到神经网络,继续讨论小批量抽样怎样影响梯度噪声、设备利用率和训练曲线。

本章小结:

  • 样本数 \(n\) 主要扩大数据、预测与残差缓存;参数维度 \(d\) 还会让稠密海森矩阵或 BFGS 状态按 \(d^2\) 增长。
  • 稀疏、低秩、样本空间转换和矩阵—向量乘积利用的是不同结构,选择方法时需要先确认数据与目标是否具备相应条件。
  • 小批量把当前批次的数据内存从 \(O(nd)\) 降到 \(O(b_kd)\),但批次构造仍需保留损失函数依赖的时间、分组和类别结构,完整训练也仍需承担参数、梯度、优化器状态、数据读取和框架工作区的成本。

第二章解释了优化算法怎样寻找最低点,第三章说明了训练规模怎样改变计算与内存需求。接下来还需要回答一个更基础的问题:机器学习模型究竟把什么定义为“最低点”?第四章从普通最小二乘回归开始,把预测误差写成明确的目标函数;第五章再加入 Ridge、Lasso 和 Elastic Net,说明正则化怎样限制可接受的解。

4. 最小二乘法:优化怎样变成模型训练? #

普通最小二乘回归(OLS)主要用于预测连续数值(如房价、销量、温度或交付时间)。它假设预测值可以表示为输入特征的线性组合,是理解损失函数、闭式解、条件数和正则化的基础模型。OLS 不是分类任务的标准选择:虽然它可以在数值上拟合 0/1 标签,但预测值不受 \([0,1]\) 范围约束,也不能自然表达类别概率;分类任务通常使用逻辑回归等模型。

线性回归假设:

\[ \hat{y}_i=\mathbf{x}_i^\mathsf{T}\boldsymbol{\beta}。 \]

普通最小二乘法选择 \(\boldsymbol{\beta}\),使残差平方和最小:

\[ \min_{\boldsymbol{\beta}} \mathcal{J}(\boldsymbol{\beta}) =\frac{1}{2n}\lVert\mathbf{y}-X\boldsymbol{\beta}\rVert_2^2。 \]
变量含义维度
\(n\)训练样本数量标量
\(p\)输入特征数量;不直接出现在公式中,但决定矩阵维度标量
\(X\)设计矩阵,每行是一条样本,每列是一个特征\(n\times p\)
\(\mathbf{x}_i\)第 \(i\) 条样本的特征向量\(p\) 维向量
\(\boldsymbol{\beta}\)线性模型需要学习的系数\(p\) 维向量
\(\mathbf{y}\)全部真实目标值组成的向量\(n\) 维向量
\(\hat{y}_i\)模型对第 \(i\) 条样本的预测值标量
\(\mathbf{y}-X\boldsymbol{\beta}\)所有样本的残差向量\(n\) 维向量
\(\lVert\cdot\rVert_2^2\)各分量平方后求和;平方范数中不保留外层平方根标量
\(1/(2n)\)对样本取平均,并用 \(1/2\) 抵消求导产生的系数 \(2\)标量

平方损失可以避免正负误差相互抵消,而且会对较大的误差施加更强的惩罚。由此得到的目标函数光滑且凸。如果进一步假设误差相互独立,并且服从同方差的高斯分布,那么最小化平方损失也等价于最大化数据似然[2]。

为了简化公式,本章假设特征和目标已经中心化,因此省略截距。实际建模如果显式加入截距,多数实现不会对截距项施加正则化;后面的 Ridge、Lasso 和 Elastic Net 公式也沿用这一约定。

目标函数的梯度为:

\[ \nabla\mathcal{J}(\boldsymbol{\beta}) =\frac{1}{n}X^\mathsf{T}(X\boldsymbol{\beta}-\mathbf{y})。 \]

令梯度等于零。当 \(X^\mathsf{T}X\) 可逆时,可以得到:

\[ \hat{\boldsymbol{\beta}} =(X^\mathsf{T}X)^{-1}X^\mathsf{T}\mathbf{y}。 \]

这个公式适合解释数学结构,但实际计算通常不会显式求逆。QR 分解和奇异值分解(SVD)往往更加稳定;当样本或参数很多时,也可以采用迭代方法。因此,最小二乘规定的是“优化什么”,而不是“只能怎样求解”[3]。

最小二乘目标的海森矩阵为 \(X^\mathsf{T}X/n\)。如果不同特征的尺度相差很大,或者特征之间高度相关,这个矩阵的条件数就可能很大。此时,目标函数会形成第二章所示的狭长谷底:优化算法更难收敛,回归系数也更容易受到数据扰动的影响。

最小二乘法已经明确了模型怎样把残差转换成优化目标,但它没有限制系数可以取多大,也没有解决高相关特征导致的解不稳定问题。第五章在同一个线性模型上加入正则项,观察目标函数、闭式解和系数性质会怎样改变。

5. Ridge、Lasso 与 Elastic Net:正则化改变了什么? #

Ridge、Lasso 和 Elastic Net 都是带正则化的线性回归模型,主要用于连续数值预测。它们保留了线性模型易于解释、训练成本低的特点,同时通过限制回归系数来降低估计方差,并在适当的正则化强度下减少模型追随训练噪声的程度。Ridge 通常保留大多数特征,并能在特征高度相关时提高回归系数估计的稳定性;Lasso 能够将部分系数精确收缩到零,常用于稀疏建模和变量筛选;Elastic Net 则在稀疏性和相关特征的稳定性之间提供折衷。

正则化会直接改变训练目标,而不是在模型训练结束后进行修补。

5.1 Ridge:用 L2 惩罚收缩系数 #

Ridge 怎样改变目标函数? #

\[ \min_{\boldsymbol{\beta}} \frac{1}{2n}\lVert\mathbf{y}-X\boldsymbol{\beta}\rVert_2^2 +\lambda\lVert\boldsymbol{\beta}\rVert_2^2。 \]
新变量或记号含义
\(\lambda\ge0\)正则化强度;越大越重视限制系数,而不是只追求训练误差
\(\lVert\boldsymbol{\beta}\rVert_2^2=\sum_{j=1}^{p}\beta_j^2\)所有系数平方之和
\(j\)本章表示特征或回归系数的索引

这里采用本文统一的归一化约定:数据损失除以 \(2n\),L2 惩罚写作 \(\lambda\lVert\boldsymbol{\beta}\rVert_2^2\),因此求导后出现 \(2\lambda\boldsymbol{\beta}\),闭式解中出现 \(2n\lambda\mathbf{I}_p\)。其他教材或软件可能把 \(1/2\) 放入正则项、对损失求和而不取平均,或使用不同参数名。因此,本文的 \(\lambda\) 不一定与 API 中的 alpha 或 lambda 数值相同;比较 Ridge、Lasso 或 Elastic Net 的配置前,应先核对目标函数定义。

从梯度得到参数空间解 #

要把第三章提到的“参数空间”和“样本空间”联系起来,先对 Ridge 目标求梯度。数据损失的梯度与第四章相同,L2 惩罚的梯度为 \(2\lambda\boldsymbol{\beta}\),所以:

\[ \nabla\mathcal{J}(\boldsymbol{\beta}) =\frac{1}{n}X^\mathsf{T} \left(X\boldsymbol{\beta}-\mathbf{y}\right) +2\lambda\boldsymbol{\beta}。 \]

令梯度等于零,并保留每一步代数变换:

\[ \begin{aligned} \frac{1}{n}X^\mathsf{T} \left(X\boldsymbol{\beta}-\mathbf{y}\right) +2\lambda\boldsymbol{\beta} &=\mathbf{0},\\ X^\mathsf{T}X\boldsymbol{\beta} -X^\mathsf{T}\mathbf{y} +2n\lambda\boldsymbol{\beta} &=\mathbf{0},\\ \left(X^\mathsf{T}X+2n\lambda\mathbf{I}_p\right) \boldsymbol{\beta} &=X^\mathsf{T}\mathbf{y}。 \end{aligned} \]

当 \(\lambda>0\) 时,加入的正对角项使这个矩阵可逆,由此得到参数空间中的解:

\[ \hat{\boldsymbol{\beta}}_{\text{Ridge}} =\left(X^\mathsf{T}X+2n\lambda\mathbf{I}_p\right)^{-1} X^\mathsf{T}\mathbf{y}。 \]

样本空间形式为什么适合 \(n\ll p\)? #

如果特征数 \(p\) 远大于样本数 \(n\),直接求解 \(p\times p\) 系统可能代价很高。利用恒等式:

\[ \left(X^\mathsf{T}X+c\mathbf{I}_p\right)^{-1}X^\mathsf{T} =X^\mathsf{T}\left(XX^\mathsf{T}+c\mathbf{I}_n\right)^{-1}, \]

这个恒等式可以直接核对:\((X^\mathsf{T}X+c\mathbf{I}_p)X^\mathsf{T}=X^\mathsf{T}(XX^\mathsf{T}+c\mathbf{I}_n)\)。当 \(c>0\) 时,两侧括号内的矩阵均可逆;分别在适当一侧乘以逆矩阵,就得到上式。

再代入 \(c=2n\lambda\),可以得到样本空间中的等价形式:

\[ \hat{\boldsymbol{\beta}}_{\text{Ridge}} =X^\mathsf{T} \left(XX^\mathsf{T}+2n\lambda\mathbf{I}_n\right)^{-1} \mathbf{y}。 \]
新变量或记号含义维度
\(\mathbf{I}_p\)参数空间中的单位矩阵\(p\times p\)
\(\mathbf{I}_n\)样本空间中的单位矩阵\(n\times n\)
\(c\)矩阵恒等式中的正标量;本例代入 \(2n\lambda\)标量
\(X^\mathsf{T}X\)参数空间中的特征内积矩阵\(p\times p\)
\(XX^\mathsf{T}\)样本空间中的样本内积矩阵\(n\times n\)
\(\hat{\boldsymbol{\beta}}_{\text{Ridge}}\)Ridge 目标函数的最优系数估计\(p\) 维向量

当 \(n\ll p\) 时,样本空间形式把主要线性系统从 \(p\times p\) 缩小为 \(n\times n\)。实际实现仍会根据稀疏性、数值稳定性和底层线性代数库选择求解路径,而不会机械地显式计算公式中的逆矩阵。

L2 惩罚会压缩较大的系数,但通常不会将系数精确收缩到零。从矩阵角度看,它相当于在海森矩阵的对角线上增加正值,这通常可以减小条件数,缓解矩阵的病态性,并让高度相关的特征获得更稳定的权重。这种收缩会引入一些偏差,但可能换来更低的方差和更稳定的预测。

5.2 Lasso:L1 的尖角为什么产生稀疏解? #

\[ \min_{\boldsymbol{\beta}} \frac{1}{2n}\lVert\mathbf{y}-X\boldsymbol{\beta}\rVert_2^2 +\lambda\lVert\boldsymbol{\beta}\rVert_1。 \]
新变量或记号含义
\(\lVert\boldsymbol{\beta}\rVert_1=\sum_{j=1}^{p}\lvert\beta_j\rvert\)所有系数绝对值之和
\(\lvert\beta_j\rvert\)第 \(j\) 个系数的绝对值;在 \(\beta_j=0\) 处不可导

为了理解稀疏解的几何来源,我们可以将上述惩罚形式转换为与某个 \(\lambda\) 对应的约束形式:在 \(\lVert\boldsymbol{\beta}\rVert_1\le c\) 的区域内最小化数据损失,其中 \(c\ge0\) 是 L1 范数的上限。在适当的凸优化条件下,惩罚形式中的 \(\lambda\) 与约束形式中的 \(c\) 可以产生相同的最优解集合;两者控制正则化的方式不同,其数值没有可以直接套用的一一对应关系。

L1 约束区域在坐标轴上有尖角,损失函数的椭圆等高线更容易在这些尖角处与约束边界接触。当接触点落在坐标轴上时,就意味着某些系数精确等于零。然而,\(|\beta_j|\) 在零点不可导,因此不能直接套用针对光滑目标的普通牛顿法。常见的求解方法包括坐标下降、次梯度法和近端梯度法。近端更新使用的软阈值函数(soft-thresholding)为:

\[ \operatorname{soft}(z,\gamma) =\operatorname{sign}(z)\max(|z|-\gamma,0)。 \]
新变量或记号含义
\(z\)完成一次普通梯度步骤后、尚未执行 L1 收缩的临时值
\(\gamma\ge0\)当前近端步骤的收缩阈值,通常由步长和 L1 强度共同决定
\(\operatorname{sign}(z)\)返回 \(z\) 的正负号
\(\operatorname{soft}(z,\gamma)\)软阈值函数的输出;绝对值不超过阈值时为零

当 \(|z|\le\gamma\) 时,软阈值函数直接返回零。Lasso 的稀疏性来自 L1 惩罚的目标结构;在近端梯度法中,这种结构具体表现为软阈值操作把绝对值较小的临时系数直接映射为零。

5.3 Elastic Net:在稀疏性和稳定性之间折中 #

\[ \begin{aligned} \min_{\boldsymbol{\beta}}\quad &\frac{1}{2n}\lVert\mathbf{y}-X\boldsymbol{\beta}\rVert_2^2\\ &{}+\lambda\rho\lVert\boldsymbol{\beta}\rVert_1\\ &{}+\lambda\frac{1-\rho}{2} \lVert\boldsymbol{\beta}\rVert_2^2。 \end{aligned} \]
新变量或记号含义常见异名
\(\rho\in[0,1]\)L1 在混合惩罚中的比例l1_ratio、\(\alpha\)
\(1-\rho\)L2 在混合惩罚中的比例不适用
\(\lambda\)L1 与 L2 组合后的整体强度Scikit-learn API 中常叫 alpha

\(\lambda\) 控制整体正则化强度,而 \(\rho\) 决定 L1 和 L2 各自所占的比例。当 \(\rho=1\) 时,Elastic Net 退化为 Lasso;当 \(\rho=0\) 时,目标函数只保留 L2 惩罚。如果数据中有多组高度相关的特征,Lasso 可能只保留其中一个,且选择结果可能随样本扰动而变化。Elastic Net 中的 L2 部分倾向于让相关特征共同保留,而 L1 部分则继续提供稀疏性。值得注意的是,即使 Lasso 将某些系数收缩到零,被保留的变量也并不自动具有因果意义;变量选择还会受到特征尺度、相关性和样本扰动的影响。

下表中的“稀疏系数”表示模型是否会把部分回归系数精确压到零;“常见求解方式”列举典型路线,不表示每个软件库只能使用这一种算法:

模型正则项稀疏系数常见求解方式
OLS无否QR、SVD、迭代法
RidgeL2通常否线性代数、迭代法
LassoL1是坐标下降、近端方法
Elastic NetL1 + L2是坐标下降

6. XGBoost 与 LightGBM:怎样在函数空间中逐轮加树? #

XGBoost 和 LightGBM 都属于梯度提升决策树模型。它们能处理回归(如价格、需求预测)、二分类、多分类和排序任务(如客户流失判断、风险等级识别、搜索结果排序)。它们常用于表格数据任务,因为决策树能够表示非线性关系和特征交互,也不要求输入特征与目标之间呈线性关系。具体支持哪些目标函数和数据类型,仍取决于软件版本与配置。

6.1 共同基础:加法树模型怎样逐轮修正预测? #

XGBoost 和 LightGBM 虽然在分裂搜索、树的生长方式和工程实现上不同,但都采用同一种基本数学结构:模型不是一棵独立的树,而是多棵回归树组成的加法模型。设初始模型为 \(F_0\),第 \(t\) 轮加入的新树为 \(f_t\),学习率为 \(\eta\),则完整模型可以写成:

\[ \begin{aligned} F_t(\mathbf{x}) &=F_{t-1}(\mathbf{x})+\eta f_t(\mathbf{x})\\ &=F_0(\mathbf{x}) {}+\eta\sum_{s=1}^{t}f_s(\mathbf{x}),\\ \hat{y}_i^{(t)} &=F_t(\mathbf{x}_i)。 \end{aligned} \]

这里,\(F_t\) 表示加入前 \(t\) 棵树后的完整预测函数,而 \(f_t\) 只表示第 \(t\) 轮新增的一棵树。对于一棵有 \(T_t\) 个叶节点的回归树,可以进一步写成:

\[ f_t(\mathbf{x})=w_{t,q_t(\mathbf{x})}, \qquad q_t:\mathbb{R}^{d}\rightarrow\{1,2,\ldots,T_t\}。 \]

函数 \(q_t\) 根据树中的分裂规则,把输入 \(\mathbf{x}\) 分配到某个叶节点;\(w_{t,j}\) 是第 \(t\) 棵树第 \(j\) 个叶节点保存的预测值。因此,训练一棵新树既要决定树的结构 \(q_t\),也要决定每个叶节点的权重。XGBoost 和 LightGBM 的主要差别,不在这个加法模型本身,而在于怎样高效寻找分裂、组织树结构并实现计算。

变量或记号含义
\(F_0(\mathbf{x})\)尚未加入任何树时的初始预测函数,例如回归任务中的一个常数基线
\(F_t(\mathbf{x})\)加入前 \(t\) 棵树后得到的完整模型
\(s\)加法模型求和中的树编号,从 \(1\) 到 \(t\)
\(f_s(\mathbf{x})\)第 \(s\) 棵回归树对输入 \(\mathbf{x}\) 给出的修正值
\(\eta\)学习率或收缩系数,控制每棵新树加入总体模型时的贡献大小
\(q_t(\mathbf{x})\)第 \(t\) 棵树把输入 \(\mathbf{x}\) 映射到叶节点编号的函数
\(T_t\)第 \(t\) 棵树的叶节点总数
\(w_{t,j}\)第 \(t\) 棵树第 \(j\) 个叶节点的预测权重
\(\hat{y}_i^{(t)}\)第 \(t\) 轮结束后,完整模型对第 \(i\) 条样本的累计预测

第 \(t\) 轮训练不会重新同时拟合前面所有树,而是在固定 \(F_{t-1}\) 的条件下,选择一棵新树 \(f_t\)。这一轮的优化问题可以概括为:

\[ \begin{aligned} \underset{f_t\in\mathcal{F}}{\operatorname{minimize}} \quad \mathcal{J}^{(t)} ={}&\sum_{i=1}^{n} \ell\!\left( y_i, F_{t-1}(\mathbf{x}_i)+\eta f_t(\mathbf{x}_i) \right)\\ &{}+\Omega(f_t)。 \end{aligned} \]
新变量或记号含义
\(\mathcal{F}\)当前算法允许选择的回归树集合
\(\mathcal{J}^{(t)}\)第 \(t\) 轮选择新树时需要最小化的目标函数
\(\ell(y_i,\hat y_i)\)第 \(i\) 条样本的预测损失
\(F_{t-1}(\mathbf{x}_i)\)前 \(t-1\) 棵树对样本 \(i\) 的累计预测;本轮训练时视为已知量
\(\eta f_t(\mathbf{x}_i)\)第 \(t\) 棵树经过学习率缩放后提供的预测修正
\(\Omega(f_t)\)对新树复杂度的惩罚,例如限制叶节点数量和叶节点权重

这条公式解释了“逐轮加树”的含义:每一轮都寻找一棵能降低当前损失、同时不过度增加模型复杂度的新树。只观察第 \(i\) 条样本时,预测更新式就是:

\[ \hat{y}_i^{(t)} =\hat{y}_i^{(t-1)}+\eta f_t(\mathbf{x}_i)。 \]
变量含义
\(t\)Boosting 轮次,不表示日历时间
\(\mathbf{x}_i\)第 \(i\) 条样本的输入特征向量
\(\hat{y}_i^{(t-1)}\)加入第 \(t\) 棵树之前的累计预测
\(f_t(\mathbf{x}_i)\)第 \(t\) 棵树对样本 \(i\) 给出的修正值
\(\hat{y}_i^{(t)}\)加入本轮新树后的累计预测

下一节按照 XGBoost 的常见推导,先令 \(\eta=1\) 求出本轮未缩放的新树,再在更新累计预测时应用学习率。训练过程要选择的不只是固定树中的连续参数,还包括分裂特征、分裂阈值和整棵树的结构。因此,不能把 Boosting 简单理解为“对决策树做梯度下降”。

以带 \(1/2\) 系数的平方损失为例:

\[ \ell_i=\frac{1}{2}(y_i-\hat{y}_i)^2, \]

其负梯度为:

\[ -\frac{\partial\ell_i}{\partial\hat{y}_i} =y_i-\hat{y}_i。 \]
变量或记号含义
\(\ell_i\)第 \(i\) 条样本的损失
\(y_i\)第 \(i\) 条样本的真实标签
\(\hat{y}_i\)当前模型对第 \(i\) 条样本的预测
\(\partial\ell_i/\partial\hat{y}_i\)损失对当前预测的一阶偏导
\(y_i-\hat{y}_i\)本节所定义平方损失下的残差,也等于负梯度

对于平方损失,新树拟合的就是残差;从函数空间的角度看,这相当于沿着最能降低当前损失的方向修正模型。换成其他可微损失以后,新树拟合的则是相应的伪残差。

6.2 XGBoost:用二阶近似评价新树 #

XGBoost 在当前预测附近进行二阶泰勒(Taylor)展开[4][5]:

\[ \mathcal{J}^{(t)} \approx\sum_{i=1}^{n} \left[g_i f_t(\mathbf{x}_i)+\frac{1}{2}h_i f_t^2(\mathbf{x}_i)\right] {}+\Omega(f_t), \]
新变量或记号含义
\(\mathcal{J}^{(t)}\)第 \(t\) 轮加入新树时需要近似最小化的目标
\(g_i\)损失对样本 \(i\) 当前预测的一阶导数
\(h_i\)损失对样本 \(i\) 当前预测的二阶导数
\(\Omega(f_t)\)对第 \(t\) 棵树的叶节点数量、叶节点权重等复杂度施加的惩罚
\(\approx\)当前预测附近的二阶泰勒近似,不是恒等式

其中,\(g_i\) 和 \(h_i\) 分别表示损失函数对当前预测的一阶和二阶导数。对叶节点 \(j\),记 \(G_j=\sum_{i\in I_j}g_i\)、\(H_j=\sum_{i\in I_j}h_i\)。在常见的 L2 叶节点权重正则化下:

\[ w_j^*=-\frac{G_j}{H_j+\lambda}。 \]
新变量或记号含义
\(j\)本节表示叶节点索引,不再表示线性模型的特征索引
\(I_j\)落入叶节点 \(j\) 的训练样本集合
\(G_j=\sum_{i\in I_j}g_i\)叶节点 \(j\) 内的一阶导数之和
\(H_j=\sum_{i\in I_j}h_i\)叶节点 \(j\) 内的二阶导数之和
\(w_j^*\)固定树结构下,叶节点 \(j\) 的最优输出权重
\(\lambda\)叶节点权重的 L2 正则化强度,与前文含义一致

算法可以根据分裂前后 \(G\)、\(H\) 的变化计算候选分裂的增益。由此可见,一阶和二阶导数不仅决定固定树结构下的叶节点权重,也直接参与候选分裂和树结构的搜索。

实现更新(截至 2026 年 8 月):上面的推导采用标量叶节点来说明 XGBoost 的基本机制。XGBoost v3.4.1 为 hist 树方法提供了功能完整的向量叶模型。设置 multi_strategy="multi_output_tree" 后,多分类或多输出任务可以让多个输出共享同一棵树的分裂结构,并在每个叶节点保存一个预测向量。默认的 one_output_per_tree 仍然为每个输出分别建立标量叶树,因此向量叶是另一种可选策略,并非全面替代原有实现。它更适合不同输出能够共享相似分裂条件的任务;如果各输出需要不同的分裂结构,分别建树仍可能更灵活。

6.3 LightGBM:目标相近,搜索方式不同 #

LightGBM 同样以梯度提升树为基础,也会使用损失函数对当前预测的一阶和二阶导数。它与其他实现的主要差别在于训练工程和树的生长策略[6][7]:

  • 算法先把连续特征离散到有限的直方图区间,因此搜索分裂点的工作量更多取决于 bin 的数量;
  • LightGBM 默认逐叶生长(leaf-wise,也称 best-first),每次选择预计能让损失下降最多的叶节点继续分裂;
  • 在叶节点总数相同的情况下,逐叶生长往往能更快降低训练损失,但在小数据集上也更容易过拟合,因此需要用 num_leaves、max_depth、min_data_in_leaf 等参数约束模型复杂度;
  • GOSS 和 EFB 是进一步的加速策略,但是否启用以及具体行为取决于配置和版本。

因此,不能简单地把 LightGBM 称为“比 XGBoost 更先进的优化器”。两者采用相同的梯度提升框架,但在树的生长方式、分裂搜索、数据表示和工程实现上有所不同。最终效果取决于具体数据、目标函数、特征、超参数和计算环境。

7. 神经网络:损失、反向传播与优化器如何配合? #

神经网络不是一个单一模型,而是一类由多层计算单元和可学习参数构成的模型族。它们可以完成分类、回归、序列预测、表示学习和内容生成等任务。对于本文讨论的基于梯度的训练方法,不同网络大体遵循同一条主线:计算预测值与损失,通过反向传播计算梯度,最后由优化器更新参数。

7.1 常见神经网络分别解决什么问题? #

这一节不是神经网络架构的完整发展史,而是为后面的优化讨论建立必要背景:网络结构决定预测函数怎样组织参数,损失函数量化预测误差,再通过求导和反向传播得到参数梯度。下面只保留几类常见结构及其最典型的训练目标。

前馈全连接网络是最简单的神经网络类型,足以说明其基本机制。信息单向从输入层流经一个或多个隐藏层,最终到达输出层;同一层的神经元通常与前一层的所有输出全连接。它可以用于表格数据分类和回归,也常作为其他复杂网络中的输出头。其局限在于没有引入针对图像空间结构或序列顺序的归纳偏置。

卷积神经网络(Convolutional Neural Network, CNN)通过局部连接和共享卷积核提取二维图像中的局部模式,经典应用包括手写字符与文档图像识别[8]。这里引用的论文用于说明 CNN 的经典视觉识别背景,并不单独覆盖后来扩展出的所有卷积应用。

循环神经网络(Recurrent Neural Network, RNN)通过把前一步的隐藏状态传递给下一步来表示序列依赖,因此长期以来被用于序列数据建模。长短期记忆网络(Long Short-Term Memory, LSTM)通过在循环结构中引入门控机制,缓解了普通 RNN 难以学习长期依赖的问题。它曾广泛用于时间序列、语音和自然语言序列建模,目前在部分序列任务中仍然实用[9]。

自编码器(Autoencoder)由编码器和解码器组成。编码器将输入压缩为潜在表示,解码器则尝试重建原始输入。模型通常通过最小化重建误差学习表示,可用于降维、去噪、异常检测和预训练;但较低的重建误差并不自动保证潜在表示具有业务上需要的语义[10]。

Transformer 利用注意力机制建立序列中不同位置之间的关系,不再像 RNN 那样沿序列逐步传递隐藏状态,从而使得同一层中的不同位置在训练时更容易并行计算。原始论文主要验证了机器翻译和英语成分句法分析;后来的大语言模型进一步展示了这种架构在给定上下文窗口内建模长文本依赖的实际能力[11]。

GPT 是采用仅解码器(decoder-only)Transformer 架构的自回归语言模型族。训练时,模型根据前序词元(token)预测下一个词元;推理时,则反复执行此过程生成文本。GPT-3 展示了大规模自回归语言模型通过文本提示完成零样本、单样本和少样本任务的能力[12]。大语言模型(Large Language Model, LLM)则是更宽泛的类别:GPT 属于 LLM,但并非所有 LLM 都采用完全相同的网络结构、训练数据或训练目标。

网络类型主要结构特点常见任务典型训练目标
前馈全连接网络信息逐层向前传递,层与层之间通常全连接表格分类、回归、其他网络的输出头交叉熵、均方误差
CNN局部连接、共享卷积核图像与文档识别交叉熵等分类损失
RNN / LSTM隐藏状态沿序列传递,LSTM 使用门控记忆时间序列、语音、序列分类与预测序列交叉熵、回归损失
自编码器编码器压缩表示,解码器重建输入降维、去噪、异常检测、表示学习重建损失及其他约束
Transformer用注意力连接不同位置机器翻译、文本与其他序列任务取决于任务和训练方式
GPT 类语言模型仅解码器 Transformer,自回归生成文本生成、问答、摘要、代码等下一个 token 的交叉熵

无论采用何种结构,神经网络都可以统一表示为 \(\hat{\mathbf{y}}=f_\theta(\mathbf{x})\)。分类任务通常使用交叉熵等损失函数,回归任务可能使用均方误差,自编码器常使用重建损失,自回归语言模型则计算下一个 token 的预测损失。完整的训练目标还可以包含权重衰减等正则项。

不同资料对 loss、cost 和 objective 的用法并不完全一致。本文不依赖这三个英文单词划分概念,而是用 \(\ell_i\) 表示单个样本的损失,用 \(\mathcal{L}\) 表示数据损失的汇总,用 \(\mathcal{J}\) 表示包含正则项在内的完整优化目标。阅读其他资料时,仍要先确认作者采用的定义。

7.2 反向传播不是梯度下降 #

前向传播负责计算预测值和损失,反向传播则利用链式法则计算计算图中损失项对参数的梯度;如果正则项显式写入该计算图,它的梯度也会一并计算。反向传播回答的是“梯度是多少”,并不决定“参数下一步更新到哪里”。以随机梯度下降(SGD)为例:

\[ \theta_{t+1}=\theta_t-\eta\widehat{\nabla\mathcal{J}}_t。 \]
变量或记号含义
\(t\)本章表示神经网络的参数更新步数
\(\theta_t\)第 \(t\) 步时网络全部可训练参数的集合
\(\widehat{\nabla\mathcal{J}}_t\)当前样本或小批量对完整目标梯度的估计;帽子表示估计量
\(\eta\)优化器学习率,与前文保持一致

在典型的 PyTorch 训练循环中,loss.backward() 负责计算并累积梯度,optimizer.step() 负责更新参数,optimizer.zero_grad() 负责清除或重置梯度。三个操作各有自己的职责[13]。

7.3 为什么通常使用小批量训练? #

第 3.3 节已经说明,批次构造会受到时间顺序、类别比例和样本依赖关系的限制。本节假设每个训练样本已经按任务要求正确构造,只讨论神经网络训练中的梯度估计与计算效率。

\[ \begin{aligned} \widehat{\nabla\mathcal{J}}_t ={}&\frac{1}{|B_t|} \sum_{i\in B_t}\nabla_\theta\ell_i(\theta_t)\\ &{}+\lambda\nabla_\theta\Omega(\theta_t)。 \end{aligned} \]
新变量或记号含义
\(B_t\)第 \(t\) 步抽取的小批量样本集合
\(\lvert B_t\rvert\)当前小批量包含的样本数;竖线表示集合大小,不是绝对值
\(\ell_i(\theta_t)\)当前参数下第 \(i\) 条样本的损失
\(\nabla_\theta\ell_i\)单个样本损失对全部参数的梯度
\(\lambda\nabla_\theta\Omega(\theta_t)\)可微正则项对完整目标梯度的贡献;没有显式正则项时省略

全批量梯度使用全部训练数据,在参数和数据固定时具有确定性,但每次更新的计算成本较高;单样本梯度虽然更新频繁,但噪声也很大。小批量训练则在内存占用、计算吞吐量和梯度噪声之间折衷。上式描述了将可微正则项直接写入目标函数的情况;若无显式正则项,公式仅保留前面的批量平均梯度。批量大小还会影响硬件利用率、归一化统计和泛化表现,不能简单理解为“批量越大,梯度就越准确,模型也一定越好”。

7.4 动量法怎样利用历史梯度? #

动量法会累积过去的梯度方向:

\[ \mathbf{u}_t=\mu\mathbf{u}_{t-1}+\mathbf{g}_t,\qquad \theta_{t+1}=\theta_t-\eta\mathbf{u}_t。 \]
新变量或记号含义
\(\mathbf{g}_t\)第 \(t\) 步计算出的梯度;本文沿用第二章的梯度记号
\(\mathbf{u}_t\)累积历史方向后的动量状态;这里改用 \(\mathbf{u}\),避免与 Adam 的二阶矩记号冲突
\(\mu\in[0,1)\)动量衰减系数,决定保留多少历史方向

如果连续多步的梯度方向大致一致,历史方向会相互叠加,使参数沿该方向移动得更快。反过来,当梯度在高曲率方向上反复改变符号时,历史信息会抵消部分摆动,从而减弱振荡。

7.5 Adam 怎样调整每个参数的更新尺度? #

Adam 在动量思想的基础上,进一步估计每个参数方向上的梯度尺度。为简化记号,将第 \(t\) 步的小批量梯度写成:

\[ \mathbf{g}_t=\widehat{\nabla\mathcal{J}}_t。 \]

Adam 首先计算梯度一阶矩和未中心化二阶矩的指数移动平均[14]:

\[ \mathbf{m}_t =\beta_1\mathbf{m}_{t-1}+(1-\beta_1)\mathbf{g}_t, \]\[ \mathbf{v}_t =\beta_2\mathbf{v}_{t-1} +(1-\beta_2)(\mathbf{g}_t\odot\mathbf{g}_t)。 \]

\(\mathbf{m}_t\) 是近期梯度的平滑平均,保留了梯度的方向和带符号大小,其作用类似于动量。\(\mathbf{v}_t\) 记录近期梯度平方的平均水平,用来衡量每个参数方向上的梯度尺度。算法通常将 \(\mathbf{m}_0\) 和 \(\mathbf{v}_0\) 初始化为零向量,因此训练初期的两个移动平均都会偏向零,需要进行偏差修正:

\[ \begin{aligned} \widehat{\mathbf{m}}_t &=\frac{\mathbf{m}_t}{1-\beta_1^t},\\ \widehat{\mathbf{v}}_t &=\frac{\mathbf{v}_t}{1-\beta_2^t}。 \end{aligned} \]

最后,Adam 用修正后的一阶矩决定更新方向,并用修正后二阶矩的平方根分别调整各参数的更新幅度:

\[ \theta_{t+1} =\theta_t -\eta\frac{\widehat{\mathbf{m}}_t} {\sqrt{\widehat{\mathbf{v}}_t}+\epsilon}。 \]

上式中的平方、平方根和除法都按向量分量逐一计算。如果某个参数近期的梯度平方经常较大,其分母就会增大,实际更新幅度通常也会相应减小;梯度尺度较小的参数则可能获得相对更大的更新。Adam 根据历史梯度为每个参数调整尺度,但它并不会像牛顿法那样计算或使用海森矩阵的逆,因此不能将两者等同起来。

新变量或记号含义
\(\mathbf{m}_t\)第 \(t\) 步梯度的一阶矩指数移动平均,可理解为近期梯度带符号大小的平滑估计
\(\mathbf{v}_t\)第 \(t\) 步梯度的未中心化二阶矩指数移动平均,可理解为近期梯度平方尺度的平滑估计
\(\beta_1\in[0,1)\)一阶矩衰减系数;越接近 1,保留的一阶矩历史越长
\(\beta_2\in[0,1)\)二阶矩衰减系数;越接近 1,保留的梯度平方历史越长
\(\mathbf{g}_t\odot\mathbf{g}_t\)梯度向量与自身逐元素相乘,即每个分量分别平方
\(\widehat{\mathbf{m}}_t\)经过初始零值偏差修正的一阶矩估计;帽子表示修正后的估计量
\(\widehat{\mathbf{v}}_t\)经过初始零值偏差修正的二阶矩估计
\(\epsilon>0\)加在分母中的很小常数,用于避免除以零并改善数值稳定性

Adam 原论文建议采用 \(\beta_1=0.9\)、\(\beta_2=0.999\) 和 \(\epsilon=10^{-8}\) 作为默认值,但具体软件库或训练配置可能使用不同设置[14]。Adam 经常能让训练损失在早期下降得更快,但这并不保证模型在测试集上表现更好,也不保证算法能在非凸目标上找到全局最优解。

7.6 如何理解神经网络的非凸优化地形? #

先回忆凸目标函数的一个重要性质:连接参数空间中任意两个点,目标函数在两点之间的取值不会高于连接两个函数值的直线。用公式表示为:

\[ \begin{aligned} &\mathcal{J}\bigl( \rho\theta^{(a)}+(1-\rho)\theta^{(b)} \bigr)\\ &\quad\leq \rho\mathcal{J}\bigl(\theta^{(a)}\bigr) {}+(1-\rho)\mathcal{J}\bigl(\theta^{(b)}\bigr),\\ &0\leq\rho\leq1。 \end{aligned} \]
新变量或记号含义
\(\theta^{(a)},\theta^{(b)}\)参数空间中的任意两个参数点
\(\rho\)两个参数点之间的插值比例,取值范围为 \([0,1]\)
\(\rho\theta^{(a)}+(1-\rho)\theta^{(b)}\)两个参数点之间的一个中间位置
\(\mathcal{J}(\theta)\)神经网络训练时需要最小化的完整目标函数

凸目标的任何局部最低点同时也是全局最低点。前文讨论的普通最小二乘在设计矩阵固定时就是凸优化问题。算法可能因为条件数较大而收敛缓慢,但不会停在一个只对附近参数最优、放到整个参数空间却明显较差的严格局部最低点。

神经网络通常不具备这种性质。甚至不需要引入 ReLU、Sigmoid 或注意力机制,只要把两个可训练层连接起来,层与层之间的参数乘法就可能产生非凸目标。考虑一个只有一个输入和一个输出的两层线性网络:

\[ \hat y=w_2(w_1x)=w_1w_2x。 \]

取一个训练样本 \(x=1\)、\(y=1\),并使用平方误差,则完整目标为:

\[ \mathcal{J}(w_1,w_2) =(\hat y-y)^2 =(w_1w_2-1)^2。 \]
新变量或记号含义本例取值
\(x\)网络输入\(1\)
\(y\)真实目标值\(1\)
\(w_1\)第一层的标量权重待学习参数
\(w_2\)第二层的标量权重待学习参数
\(\hat y\)网络预测值\(w_1w_2\)
\(\mathcal{J}(w_1,w_2)\)当前两个权重对应的平方误差\((w_1w_2-1)^2\)

选择两个参数点 \(\theta^{(a)}=(1,1)\) 和 \(\theta^{(b)}=(-1,-1)\)。两个点都能给出正确预测:

\[ \begin{aligned} \mathcal{J}(1,1) &=(1\times1-1)^2=0,\\ \mathcal{J}(-1,-1) &=\bigl((-1)\times(-1)-1\bigr)^2=0。 \end{aligned} \]

再取两点的中点,即令 \(\rho=1/2\):

\[ \begin{aligned} \frac{1}{2}\theta^{(a)}+\frac{1}{2}\theta^{(b)} &=\frac{1}{2}(1,1)+\frac{1}{2}(-1,-1)\\ &=(0,0),\\ \mathcal{J}(0,0) &=(0\times0-1)^2=1。 \end{aligned} \]

如果 \(\mathcal{J}\) 是凸函数,中点的目标值应满足:

\[ \begin{aligned} \mathcal{J}(0,0) &\leq \frac{1}{2}\mathcal{J}(1,1) +\frac{1}{2}\mathcal{J}(-1,-1)\\ &=\frac{1}{2}\times0+\frac{1}{2}\times0=0。 \end{aligned} \]

实际结果却要求 \(1\leq0\),所以凸性条件不成立。这个例子说明:即使网络没有非线性激活函数,多层权重的组合也足以使参数优化问题变成非凸问题。加入非线性激活函数以后,目标函数还会出现更多具有不同梯度和曲率的区域。需要注意,ReLU 对它的输入是分段线性的,并不意味着训练目标对所有网络参数是凸的。

深度网络的优化地形还受到参数对称性的影响。例如,交换同一隐藏层中两个神经元的位置,并同步交换下一层对应的连接,网络输出不会改变。在某些网络中,一层权重乘以非零常数,下一层权重再按相反比例缩放,也可能保持相同的预测函数。因此,参数空间中往往存在许多功能等价的解,而不是唯一的最低点。

常见的地形特征可以这样理解:

地形特征数学或直观含义训练中的可能表现
局部最低点附近没有更低的位置,但远处可能存在更低的目标值优化器停止明显改进,但训练损失仍可能偏高
鞍点某些方向向上弯曲,另一些方向向下弯曲梯度可能接近零,但当前位置并不是最低点
平坦区域参数移动一段距离,目标值仍然变化很小梯度较小,训练进展缓慢
陡峭区域某些方向上的目标值和梯度变化很快学习率过大时容易振荡或数值溢出
狭长谷地不同方向的曲率相差很大与第二章的椭圆形等高线类似,单一学习率难以兼顾所有方向

不能把所有训练困难都简单归因于“陷入局部最低点”。鞍点、梯度消失或爆炸、不同参数方向的尺度差异,以及小批量梯度的随机波动,都可能让目标函数下降缓慢或不稳定。实际训练通常也不追求证明优化器找到了唯一的全局最低点,而是寻找训练损失较低、验证表现稳定,并且满足计算与部署要求的参数。

训练曲线告诉我们什么? #

工程实践中,最直接的诊断工具通常不是把高维目标函数画出来,而是同时记录每个 epoch 的训练集与验证集指标。训练损失(training loss)来自参与参数更新的数据;验证损失(validation loss)在不用于更新参数的独立数据上计算,用来观察模型能否把学到的规律推广到未见样本。

对于分类任务,还可以同时观察训练准确率和验证准确率。不过,优化器通常直接最小化交叉熵等可微损失,而不是准确率。准确率只统计预测类别是否正确,是一个离散指标:模型可能提高了正确类别的预测概率,使交叉熵下降,但只要预测类别没有改变,准确率就可能暂时保持不变。因此,诊断优化过程时通常先观察损失;判断预测效果时,还需要结合准确率以及更符合任务目标的评价指标。

曲线现象可能含义下一步检查
训练损失与验证损失都下降,训练和验证准确率都上升当前优化设置能够学习,并且验证表现仍在改善继续训练,同时观察验证曲线何时趋于稳定
训练损失持续下降,验证损失先下降后上升;训练准确率继续上升,验证准确率停滞或下降模型开始过拟合训练数据考虑早停、权重衰减、Dropout、数据增强或减小模型容量
训练和验证损失都长期维持较高水平,准确率也没有明显提高学习率、模型容量、输入特征、标签质量或实现可能存在问题先确认模型能否在一个很小的数据子集上过拟合,再逐项检查数据和训练配置
损失剧烈振荡、突然增大或变成 NaN学习率过大、梯度爆炸或低精度数值溢出降低学习率,检查输入尺度、梯度范数和损失实现,必要时使用梯度裁剪
损失下降但准确率几乎不变预测概率正在变化,但尚未跨过类别判定边界;也可能存在类别不平衡检查概率、混淆矩阵和更适合任务的指标,不要只根据准确率判断训练失败

训练曲线只能显示现象,不能单独证明原因。例如,训练与验证曲线之间出现差距通常提示过拟合,但数据分布变化、验证集过小或数据泄漏也可能使曲线产生误导。比较实验时,可以保持数据切分、随机种子、评价口径和训练预算一致,并根据预先选定的验证指标保存检查点;模型确定后,再使用未参与选择的测试集进行最终评价,而不是默认最后一个 epoch 的参数最好。

非凸目标下常用哪些工程方法? #

训练问题方法核心作用与边界
初始激活值或梯度逐层放大、缩小Xavier 或 He 初始化根据网络宽度和激活函数设置初始权重尺度,为优化提供可训练的起点;不能把非凸目标变成凸目标
深层网络中的信号和梯度难以传播归一化方法、残差连接改善数值尺度或提供更直接的传播路径;具体效果仍取决于网络结构和任务
训练初期不稳定,后期难以细化学习率预热与衰减训练初期逐步增大学习率,后期减小步长;改变搜索路径,但不改变模型定义
梯度突然变得很大梯度裁剪限制梯度范数或分量,降低单次异常更新的破坏;应同时监控裁剪是否过于频繁
训练集表现继续改善,验证集开始变差权重衰减、Dropout、数据增强、早停控制过拟合并改善泛化;这些方法并不保证训练损失下降得更快
不同运行结果差异明显多个随机种子与重复实验衡量结果对初始化、批次顺序和随机算子的敏感程度;不应只报告最好的一次运行

这些方法分别作用于初始化、信号传播、更新尺度和泛化控制,不能全部归入“换一个更好的优化器”。诊断时可以按顺序提问:训练损失能否下降?验证损失是否同步改善?任务指标是否达到要求?不同随机种子的结果是否稳定?这个顺序有助于区分优化失败、过拟合和评价指标不匹配。

本章小结:

  • 反向传播负责计算梯度,SGD、动量法和 Adam 才负责利用梯度更新参数;二者承担的任务不能互换。
  • 小批量抽样、动量以及按参数自适应缩放更新幅度,都会改变优化器的搜索路径,却不能保证非凸目标的全局最优解或更好的测试表现。
  • 训练曲线用于判断优化是否推进,验证曲线和任务指标用于判断泛化与实际效果;将优化失败、过拟合和指标不匹配分别诊断,通常更容易找到有效的调整方向。

神经网络的训练目标通常是非凸的,因此训练不再是求解一个具有唯一最优答案的简单凸问题;优化器往往需要在大量功能相近或等价的低损失参数中找到一个可用解。初始化、批量抽样、优化器和学习率调度共同影响搜索路径;正则化与验证方法则帮助我们从许多低损失解中选择泛化更稳定的模型。下一章将换一种概率语言理解这种对解的偏好:在 MAP 中,参数先验会以负对数项进入优化目标,从而明确表达模型更偏好哪些参数。

8. MAP:用概率语言重新理解正则化 #

最大后验估计(maximum a posteriori estimation, MAP)并非一种独立的预测模型,而是一种参数估计方法。线性回归、Prophet 以及其他概率模型,都可以在给定似然函数和先验分布后,通过 MAP 选取使后验密度最大的参数点。它将数据与参数的相容程度和先验对参数的约束整合到同一个优化目标中。

根据贝叶斯公式(Bayes’ theorem):

\[ p(\theta\mid y)\propto p(y\mid\theta)p(\theta)。 \]
变量或记号含义
\(p(\theta\mid y)\)观察到数据 \(y\) 以后,参数 \(\theta\) 的后验密度
\(p(y\mid\theta)\)给定参数以后观察到数据的似然
\(p(\theta)\)观察数据以前对参数的先验密度
\(\propto\)两边只相差一个与 \(\theta\) 无关的归一化常数

MAP 的数学表达式为:

\[ \hat{\theta}_{\mathrm{MAP}} =\arg\min_\theta\left[-\log p(y\mid\theta)-\log p(\theta)\right]。 \]
新变量或记号含义
\(\hat{\theta}_{\mathrm{MAP}}\)使后验密度最大的参数点估计
\(\arg\min_\theta\)返回令后面表达式最小的参数,而不是返回最小函数值
\(-\log p(y\mid\theta)\)负对数似然,对应数据拟合项
\(-\log p(\theta)\)负对数先验,对应正则化项

第一项衡量在给定参数时观测数据的相对可能性,第二项衡量该参数与先验分布的相容程度。当先验超参数固定,并忽略与待估参数无关的常数后,MAP 的负对数目标在数学结构上等同于“数据损失加正则项”。

8.1 一个数值例子:先验怎样把估计值拉向零? #

假设一家零售企业想估计某项新促销活动平均每天能为一家门店增加多少销量。用 \(\theta\) 表示相对于日常基线的平均增量,单位为“件/天”。团队先在一家门店试行两天,观察到每天的销量增量分别为:

\[ y_1=4\text{ 件},\qquad y_2=6\text{ 件}。 \]

这个例子中的数据、方差和先验都是为了说明计算过程而人工设定的,不代表真实零售业务的经验值。问题是:只有两天试验数据时,应该怎样估计平均销量增量 \(\theta\)?

先不加入任何先验,只让观测数据回答这个问题。假设给定 \(\theta\) 以后,两天的观测条件独立,并且都以 \(\theta\) 为均值,随机波动服从方差为 \(\sigma^2=1\) 的正态分布:

\[ y_i\mid\theta\sim\mathcal N(\theta,\sigma^2), \qquad \sigma^2=1。 \]
新变量或记号含义本例取值
\(y_1,y_2\)试行第一天和第二天相对于日常基线的销量增量\(4,6\) 件
\(\theta\)需要估计的平均每日销量增量待估参数,单位为件/天
\(\sigma^2\)给定平均增量以后,单日随机波动的方差\(1\) 件\(^2\)
\(y_i\mid\theta\)给定平均增量 \(\theta\) 后,第 \(i\) 天观测值的条件分布\(\mathcal N(\theta,1)\)

在正态误差假设下,最大化似然等价于最小化平方误差。忽略与 \(\theta\) 无关的常数,只使用两天数据得到的负对数似然为:

\[ \begin{aligned} \mathcal L_{\mathrm{data}}(\theta) &=\frac{(y_1-\theta)^2+(y_2-\theta)^2}{2\sigma^2}\\ &=\frac{(4-\theta)^2+(6-\theta)^2}{2\times1}\\ &=\frac{1}{2}(4-\theta)^2+\frac{1}{2}(6-\theta)^2。 \end{aligned} \]

对 \(\theta\) 求导并令导数等于零:

\[ \begin{aligned} \frac{d\mathcal L_{\mathrm{data}}}{d\theta} &=(\theta-4)+(\theta-6)\\ &=2\theta-10,\\ 2\theta-10&=0,\\ \hat\theta_{\mathrm{MLE}} &=\frac{10}{2}=5\text{ 件/天}。 \end{aligned} \]

在上述正态误差假设下,如果不加入先验,最大似然估计就是样本均值,即平均每天增加 \(5\) 件。不过,两天样本非常少,样本均值很容易受到偶然波动影响。现在假设企业在试验开始前作出以下判断:相似促销有时增加销量,有时也可能没有效果或产生轻微负面影响,因此不能预先认定促销一定会增销;而且在缺少新证据时,企业认为平均每日增量大多应当接近零。

要把这段业务判断写成正态先验,需要分别确定先验均值和先验尺度。本例把先验均值设为 \(0\),表示试验前以“没有平均增量”作为中心,而不是提前假定促销一定有效。再把先验标准差设为 \(s=1\) 件/天。对于正态分布,大约 68% 的概率质量位于均值上下一个标准差之内,因此这个设定表示:在观察两天试验数据以前,企业把平均增量落在 \(-1\) 到 \(+1\) 件/天之间视为较常见的情况。

公式使用的是方差,而方差等于标准差的平方,所以:

\[ \begin{aligned} s&=1\text{ 件/天},\\ s^2&=(1\text{ 件/天})^2=1\text{ 件}^2/\text{天}^2,\\ \theta&\sim\mathcal N(0,s^2)=\mathcal N(0,1)。 \end{aligned} \]
新变量或记号含义本例取值
\(\mathcal L_{\mathrm{data}}(\theta)\)只由两天试验数据产生的负对数似然两个平方误差项之和
\(\hat\theta_{\mathrm{MLE}}\)不使用先验时,使观测数据最可能出现的参数估计\(5\) 件/天
\(s\)参数 \(\theta\) 的先验标准差,单位与 \(\theta\) 相同\(1\) 件/天(教学设定)
\(s^2\)参数 \(\theta\) 的先验方差;它是标准差的平方\(1\) 件\(^2\)/天\(^2\)
\(\mathcal N(0,1)\)均值为零、方差为 \(1\) 的正态先验约 68% 的先验概率质量位于 \([-1,1]\) 件/天内,但不强制 \(\theta=0\)

这里的 \(s=1\) 不是由前面的两天数据计算出来的,也不是零售行业的通用经验值,而是作者为了展示 MAP 计算而人为设定的先验尺度。相对于 \(4\) 件和 \(6\) 件的观测值,它代表一个较强、较谨慎的先验,故意让历史判断与新数据之间形成明显张力。若改用更大的 \(s^2\),先验分布会更宽,对大增量的排斥会减弱,MAP 结果也会更接近只由数据得到的 MLE \(5\);若使用更小的 \(s^2\),收缩则会更强。

正态先验的负对数会产生一个关于 \(\theta\) 的二次惩罚。MAP 将前面的数据项和这个先验项相加,需要最小化:

\[ \begin{aligned} \mathcal J(\theta) &= \underbrace{ \frac{(y_1-\theta)^2+(y_2-\theta)^2}{2\sigma^2} }_{\text{负对数似然}} + \underbrace{ \frac{\theta^2}{2s^2} }_{\text{负对数先验}}\\ &= \frac{(4-\theta)^2+(6-\theta)^2}{2\times1} +\frac{\theta^2}{2\times1}\\ &= \frac{1}{2}(4-\theta)^2 +\frac{1}{2}(6-\theta)^2 +\frac{1}{2}\theta^2。 \end{aligned} \]

对 \(\theta\) 求导,再令导数等于零:

\[ \begin{aligned} \frac{d\mathcal J}{d\theta} &=(\theta-4)+(\theta-6)+\theta\\ &=3\theta-10,\\ 3\theta-10&=0,\\ 3\theta&=10,\\ \hat\theta_{\mathrm{MAP}} &=\frac{10}{3}\approx3.33。 \end{aligned} \]

还可以从“精度加权平均”的角度理解 \(s^2=1\) 怎样影响结果。正态分布的精度定义为方差的倒数。两条独立观测提供的数据总精度为 \(n/\sigma^2\),先验提供的精度为 \(1/s^2\)。在本例的正态似然与正态先验下,MAP 估计也可以写成:

\[ \begin{aligned} \hat\theta_{\mathrm{MAP}} &= \frac{ \left(n/\sigma^2\right)\bar y +\left(1/s^2\right)\mu_0 }{ n/\sigma^2+1/s^2 }\\ &= \frac{ \left(2/1\right)\times5 +\left(1/1\right)\times0 }{ 2/1+1/1 }\\ &=\frac{10}{3}\\ &\approx3.33。 \end{aligned} \]
新变量或记号含义本例取值
\(n\)独立观测的数量\(2\)
\(\bar y\)两天观测值的样本平均数\((4+6)/2=5\) 件/天
\(\mu_0\)先验分布的均值\(0\) 件/天
\(n/\sigma^2\)两条观测合计提供的数据精度\(2/1=2\)
\(1/s^2\)先验精度,即先验方差的倒数\(1/1=1\)

因此,本例相当于按照 \(2:1\) 的精度权重,在数据均值 \(5\) 和先验均值 \(0\) 之间取平均。这里把 \(s^2\) 设为 \(1\),会使先验获得权重 \(1\)。如果把 \(s^2\) 增大到 \(4\),先验精度就会降为 \(1/4\),此时:

\[ \hat\theta_{\mathrm{MAP}} =\frac{2\times5+(1/4)\times0}{2+1/4} =\frac{10}{2.25} \approx4.44。 \]

结果从 \(3.33\) 上升到 \(4.44\),明显向数据均值 \(5\) 靠近。这说明 \(s^2\) 并非无关紧要的常数:它直接控制先验在 MAP 结果中拥有多大权重。

只看两天试验数据时,MLE 给出的平均销量增量为 \(5\) 件/天;加入历史先验后,MAP 将估计收缩为约 \(3.33\) 件/天。把 MLE 和 MAP 两个候选值分别代回完整目标,可以更直接地看到这种权衡。对于 \(\theta=5\):

\[ \begin{aligned} \mathcal J(5) &=\frac{1}{2}(4-5)^2 +\frac{1}{2}(6-5)^2 +\frac{1}{2}(5)^2\\ &=0.5+0.5+12.5\\ &=13.5。 \end{aligned} \]

对于 \(\theta=10/3\):

\[ \begin{aligned} \mathcal J\left(\frac{10}{3}\right) &=\frac{1}{2}\left(4-\frac{10}{3}\right)^2 +\frac{1}{2}\left(6-\frac{10}{3}\right)^2 +\frac{1}{2}\left(\frac{10}{3}\right)^2\\ &=\frac{2}{9}+\frac{32}{9}+\frac{50}{9}\\ &=\frac{84}{9}\\ &\approx9.33。 \end{aligned} \]

因此,\(\theta=5\) 虽然单独看两天试验数据的误差更小,但它受到的先验惩罚更大;\(\theta=10/3\) 的数据拟合略差,却使完整的负对数后验从 \(13.5\) 降到约 \(9.33\)。MAP 因而选择约 \(3.33\) 件/天。这个结果不是在“证明”促销的真实效果一定等于 \(3.33\),而是说明:在本例给定的似然、先验及其超参数下,\(3.33\) 是使后验密度最大的参数点。

8.2 不同先验怎样对应不同正则项? #

具体来说,如果误差服从高斯分布,负对数似然便与残差平方和成正比,从而得到最小二乘目标。若系数的先验分布为 \(\beta_j\sim\mathcal{N}(0,s^2)\),其负对数先验中会出现 \(\beta_j^2/(2s^2)\),这对应于 L2 正则化(Ridge 回归)。如果系数改为服从拉普拉斯(Laplace)分布:

\[ p(\beta_j\mid b)=\frac{1}{2b}\exp\left(-\frac{|\beta_j|}{b}\right), \]
新变量或记号含义
\(\beta_j\)第 \(j\) 个回归系数
\(b>0\)拉普拉斯分布的尺度;越小表示先验越集中在零附近
\(\exp(\cdot)\)自然指数函数
\(p(\beta_j\mid b)\)给定尺度 \(b\) 时,\(\beta_j\) 在某个位置的概率密度,不是该点的概率

其负对数先验就会包含 \(|\beta_j|/b\),这与 L1 正则化(Lasso 回归)的形式一致。这里的“对应”是指目标函数中惩罚项的形状相同;具体的正则化系数还会受到似然方差、先验尺度和损失归一化方式的影响。MAP 只保留后验密度最大的参数点;完整贝叶斯推断则研究整个后验分布,因此还能表达参数不确定性。两者回答的问题并不完全相同。

9. Prophet:MAP 怎样约束趋势和季节性? #

Prophet 是一种可加时间序列预测模型,常用于具有长期趋势、季节性和节假日效应的业务序列,例如业务量、访问量和需求量。它解决的是随时间变化的数值预测问题,而非分类任务。Prophet 将趋势、周期和事件效应表示为相对清晰的可加组成项,因而便于分别检查这些时间结构。如果数据缺少此类结构,或者预测主要依赖复杂的特征交互,其他模型可能更合适。

项目状态(截至 2026 年 8 月):Prophet 从 v1.4.0 起进入维护模式。项目计划继续接受错误修复、依赖更新,以及使 R 版本与 Python 版本保持一致的修改,但不再规划新功能。这不影响本节讨论的模型与 MAP 原理;如果准备在新项目中采用 Prophet,还应把项目的后续维护策略纳入选型考虑。

如果希望把本章的模型与先验解释落到 Prophet 1.4 代码上,可以继续阅读《用 Prophet 做零售需求预测:从模型原理到工程实践》。这篇实践文章从零售需求场景出发,演示数据准备、模型配置、训练、验证与结果解释。

在默认的加法模式下,Prophet 将观测到的时间序列分解为以下几部分[15]:

\[ y(t)=g(t)+s(t)+h(t)+\varepsilon_t。 \]
变量含义
\(t\)本章表示时间点,不再表示 Boosting 轮次或优化步数
\(y(t)\)时间 \(t\) 的观测值
\(g(t)\)趋势项,描述非周期性的长期变化
\(s(t)\)季节性项,描述周期性变化
\(h(t)\)节假日和事件效应
\(\varepsilon_t\)模型未解释的随机误差

如果季节性波动的幅度会随趋势水平增大,Prophet 也支持乘法模式。此时,季节性和节假日效应按趋势的相对比例变化,不再只是固定幅度的加法项[16]。

当 mcmc_samples=0 时,Prophet 的 Python API 使用 MAP 点估计。只有将 MCMC 样本数设为大于零的值,程序才会对后验分布进行采样[15]。

9.1 趋势变点:拉普拉斯先验怎样产生稀疏调整? #

Prophet 在候选变点上引入趋势变化量:

\[ \delta_j\sim\operatorname{Laplace}(0,\tau)。 \]
新变量或记号含义
\(j\)本节表示候选趋势变点的索引
\(\delta_j\)第 \(j\) 个候选变点处的趋势斜率变化量
\(\sim\)“服从某个概率分布”,不是近似等于
\(\operatorname{Laplace}(0,\tau)\)位置为 \(0\)、尺度为 \(\tau\) 的拉普拉斯分布
\(\tau>0\)变点调整先验的尺度;越小,向零收缩越强

相应的 MAP 目标包含一个与 \(|\delta_j|/\tau\) 成正比的惩罚项。Prophet 可以预先设置较多候选变点;只有当某个候选变点带来的拟合改善足以抵消先验惩罚时,对应的趋势变化量才会在 MAP 解中保留较大的非零值。

为了单独观察这个权衡过程,考虑一个局部教学例子。假设只看某一个候选变点,并且在不加先验时,数据拟合项希望趋势变化量取 \(3\)。用一个简单的二次函数表示该参数附近的数据损失:

为了让数据拟合项与先验惩罚能够直接比较,本例把 \(\delta\) 视为模型内部尺度上的无量纲参数,并把局部负对数似然归一化为曲率为 \(1\) 的二次函数。下面的数值 \(3\) 和 \(\tau\) 只用于展示收缩机制,不表示每天增减多少件。

\[ \mathcal L(\delta)=\frac{1}{2}(\delta-3)^2。 \]

加入尺度为 \(\tau\) 的拉普拉斯先验以后,简化的 MAP 目标变为:

\[ \mathcal J(\delta) =\frac{1}{2}(\delta-3)^2 +\frac{|\delta|}{\tau}。 \]
新变量或记号含义本例设定
\(\delta\)当前候选变点处的趋势变化量;为简化记号,本例省略下标 \(j\)内部尺度上的无量纲待估参数
\(3\)只考虑数据拟合时最理想的趋势变化量作者设定的教学数值
\(\mathcal L(\delta)\)当前变化量对应的局部数据损失近似\(\frac{1}{2}(\delta-3)^2\)
\(\lvert\delta\rvert/\tau\)拉普拉斯先验产生的 L1 型惩罚\(\tau\) 越小,惩罚越强
\(\mathcal J(\delta)\)数据损失与先验惩罚之和简化的局部 MAP 目标

先令 \(\tau=1\)。由于没有先验时的理想值为正数,先检查 \(\delta\geq0\) 的区域;此时 \(|\delta|=\delta\):

\[ \begin{aligned} \mathcal J(\delta) &=\frac{1}{2}(\delta-3)^2+\delta,\\ \frac{d\mathcal J}{d\delta} &=(\delta-3)+1\\ &=\delta-2。 \end{aligned} \]

令导数等于零:

\[ \delta-2=0 \quad\Longrightarrow\quad \hat\delta_{\mathrm{MAP}}=2。 \]

还需要检查 \(\delta=0\) 这个绝对值函数的折点以及负数区域。三个代表性位置的完整目标值为:

\[ \begin{aligned} \mathcal J(0) &=\frac{1}{2}(0-3)^2+|0|=4.5,\\ \mathcal J(2) &=\frac{1}{2}(2-3)^2+|2|=0.5+2=2.5,\\ \mathcal J(3) &=\frac{1}{2}(3-3)^2+|3|=3。 \end{aligned} \]

在负数区域,导数为 \((\delta-3)-1=\delta-4\),始终小于零,因此目标值会随着 \(\delta\) 向零移动而下降,不会在负数区域产生更小的解。由此可见,加入拉普拉斯先验后,最优变化量从 \(3\) 收缩到 \(2\)。

如果把先验尺度减小到 \(\tau=0.25\),惩罚项会变为:

\[ \frac{|\delta|}{0.25}=4|\delta|。 \]

在 \(\delta>0\) 的区域:

\[ \frac{d\mathcal J}{d\delta} =(\delta-3)+4 =\delta+1>0。 \]

目标函数从 \(\delta=0\) 开始便随 \(\delta\) 增大而上升;在负数区域,目标函数则朝 \(0\) 方向下降。因此,最低点落在绝对值函数的折点:

\[ \hat\delta_{\mathrm{MAP}}=0。 \]

这个例子说明,较大的 \(\tau\) 允许数据保留较明显的趋势变化,较小的 \(\tau\) 则可能把证据不足的变化量压到零。这正是 changepoint_prior_scale 增大时趋势通常更加灵活、减小时趋势通常更加平滑的数学方向。

上述计算只是为了隔离“数据拟合与拉普拉斯先验怎样共同决定一个变点变化量”而构造的局部教学例子,并不是 Prophet 完整目标函数的逐项复现。实际模型会同时估计趋势、多个变点、季节性、节假日效应以及噪声尺度,这些量也会共同影响最终结果。

changepoint_prior_scale 控制趋势变化的灵活程度。较大的先验尺度意味着约束更宽松,模型可以拟合更明显的趋势变化;较小的值会加强收缩,使趋势更加平滑。由于它表示先验尺度,其作用方向与传统正则化系数 \(\lambda\) 相反:prior scale 越大,等效约束通常越弱[17]。

9.2 季节性与回归系数:正态先验怎样平滑收缩系数? #

Prophet 可以将季节性、节假日和额外回归变量组织到设计矩阵 \(X\) 中,并用 \(\boldsymbol{\beta}\) 表示相应的系数:

\[ \beta_j\sim\mathcal{N}(0,s_j^2)。 \]
新变量或记号含义
\(j\)本节表示季节性、节假日或额外回归特征的系数索引
\(\beta_j\)设计矩阵第 \(j\) 列对应的回归系数
\(\mathcal{N}(0,s_j^2)\)均值为 \(0\)、方差为 \(s_j^2\) 的正态(Normal)分布
\(s_j>0\)第 \(j\) 个系数的先验标准差;越小,收缩越强

这里保留 \(\sigma\) 表示观测噪声的标准差,因此改用 \(s_j\) 表示第 \(j\) 个系数的先验标准差。在 MAP 目标中,这个正态先验对应 L2 型惩罚,其收缩逻辑与 8.1 节的一维正态先验例子相同。seasonality_prior_scale 和 holidays_prior_scale 控制相应先验的尺度:值越大,模型越能拟合幅度较大的季节性或节假日效应;值越小,相关系数越接近零。通过 add_regressor 添加的额外回归变量可以分别设置 prior_scale,不一定共用季节性或节假日的先验尺度[18]。

历史拟合曲线可以帮助发现明显异常,但不足以单独确定这些参数。更稳妥的选择方式是:在对数尺度上设置一组候选值,采用相同的历史窗口、预测步长和截断点(cutoff)进行滚动时间序列交叉验证,比较口径一致的业务指标,同时检查趋势与季节性分解,并确认训练过程没有使用未来信息[19]。

本章小结:

  • Prophet 的 MAP 估计把数据的负对数似然与参数先验放入同一个目标,在拟合历史数据与限制模型复杂度之间取舍。
  • 趋势变点的拉普拉斯先验产生 L1 型收缩,季节性、节假日和回归系数的正态先验产生 L2 型收缩。
  • prior_scale 表示先验尺度:数值越大,约束通常越弱;最终取值仍应通过无未来信息泄漏的滚动时间序列交叉验证来选择。

10. 一张统一地图:模型究竟在优化什么? #

前面的章节从一个二维二次型出发,逐步讨论了线性模型、提升树、神经网络和 Prophet。虽然这些模型的结构与用途不同,但理解训练过程时,可以始终追问四件事:模型怎样产生预测?数据损失怎样评价预测?正则化或先验偏好什么样的解?求解方法怎样寻找这个解?下表把这四个层次放在同一张地图中。表中只列出代表性形式和常见求解方式,并不穷举所有软件实现与配置。

模型或方法预测结构与待学习对象数据损失约束或先验求解方式与对应章节
OLS\(X\boldsymbol{\beta}\);学习线性系数 \(\boldsymbol{\beta}\)平方误差无显式正则项正规方程说明解析关系;工程上常用 QR、SVD 或迭代线性求解器(第 4 章)
Ridge\(X\boldsymbol{\beta}\);学习线性系数 \(\boldsymbol{\beta}\)平方误差L2 惩罚;可解释为高斯先验求解带 L2 项的线性系统;\(n\ll p\) 时可转到样本空间(第 5.1 节)
Lasso\(X\boldsymbol{\beta}\);学习线性系数 \(\boldsymbol{\beta}\)平方误差L1 惩罚;可解释为拉普拉斯先验坐标下降、次梯度法或近端梯度法;近端更新表现为软阈值(第 5.2 节)
Elastic Net\(X\boldsymbol{\beta}\);学习线性系数 \(\boldsymbol{\beta}\)平方误差L1 与 L2 组合常用坐标下降,同时处理 L1 与 L2 惩罚(第 5.3 节)
XGBoost\(F_t=F_0+\eta\sum_s f_s\);学习树结构与叶节点权重任务相关损失树复杂度与叶节点权重惩罚对当前目标作二阶近似,逐轮添加树并搜索分裂(第 6.1—6.2 节)
LightGBM加法树模型;学习树结构与叶节点权重任务相关损失树复杂度等约束梯度提升、直方图分裂搜索与逐叶生长(第 6.1、6.3 节)
神经网络\(f_\theta(\mathbf{x})\);学习网络权重与偏置 \(\theta\)交叉熵、均方误差或其他任务损失权重衰减及其他正则化反向传播计算梯度;SGD、动量法或 Adam 更新参数(第 7 章)
自回归 LLM\(p_\theta(x_r\mid x_{\lt r})\);学习网络参数 \(\theta\)下一 token 交叉熵权重衰减;后训练阶段还可能引入偏好约束反向传播和 AdamW,并结合混合精度与分布式训练(第 7 章、第 10.2 节)
Prophet MAP\(g(t)+s(t)+h(t)\);学习趋势与各组成项参数负对数似然趋势、季节性和回归系数的先验将负对数似然与负对数先验组成目标,再进行数值优化(第 8—9 章)

10.1 怎样用这张地图分析一个新模型? #

这四个层次彼此关联,却不能互相替代:

  1. 模型结构决定预测怎样产生,以及哪些量可以从数据中学习。 线性模型组合特征系数,提升树累加多棵回归树,神经网络复合多层变换,Prophet 则把时间序列拆成趋势、季节性和事件效应。
  2. 数据损失决定怎样衡量预测与观测之间的不一致。 平方误差、交叉熵和负对数似然对应不同任务与概率假设。改变损失函数,通常也会改变梯度以及算法重点修正的样本。
  3. 正则化或先验决定在多个可行解之间偏好哪一种。 L1 倾向于产生稀疏系数,L2 倾向于平滑收缩,树复杂度惩罚限制结构增长;在 MAP 中,参数先验以负对数项进入完整目标。
  4. 求解方法决定怎样寻找参数,但不重新定义模型和目标。 反向传播负责计算神经网络的梯度,SGD 或 Adam 才负责更新参数;最小二乘定义平方误差目标,基于 QR、SVD 或迭代算法的方法只是不同的求解路径。

这四层也可以作为排查问题的起点。训练损失长期不下降时,可以先检查梯度、学习率、数值精度、条件数和具体实现;训练损失继续下降而验证误差上升时,问题可能更多地位于数据划分、模型容量、正则化或先验;离线指标良好却无法满足实际需求时,则值得重新检查训练目标、评价指标和数据分布是否准确表达了业务问题。不同现象往往来自不同层次,单独更换优化器通常无法覆盖所有情况。

因此,面对论文、软件库或 model.fit(X, y) 这样的高层封装时,可以暂时放下模型名称,先把训练过程拆回这四层。这样一来,学习率、正则化强度、树深度和先验尺度就不再是彼此孤立的“调参旋钮”,而能对应到各自影响的机制。

10.2 把同一套问题延伸到大语言模型 #

第 7 章介绍了 Transformer 和 GPT,但没有展开大语言模型(Large Language Model,LLM)的大规模训练。大多数数据科学家和工程师没有机会从头预训练基础模型,也未必能直接接触相应的训练基础设施。不过,LLM 并没有脱离本文建立的优化框架。以自回归语言模型为例,一个代表性的预训练数据损失为:

\[ \mathcal L_{\mathrm{LM}}(\theta) =-\frac{1}{T} \sum_{r=1}^{T} \log p_\theta(x_r\mid x_{\lt r})。 \]
新变量或记号含义
\(\theta\)语言模型的全部可训练参数
\(r\)当前 token 在训练序列或小批量中的位置索引
\(T\)当前统计范围内包含的 token 数量
\(x_r\)第 \(r\) 个真实 token
\(x_{\lt r}\)第 \(r\) 个 token 之前的上下文
\(p_\theta(x_r\mid x_{\lt r})\)模型根据前文为真实下一个 token 分配的条件概率
\(-\log p_\theta(x_r\mid x_{\lt r})\)第 \(r\) 个 token 对交叉熵损失的贡献
\(\mathcal L_{\mathrm{LM}}(\theta)\)当前序列或小批量中所有 token 的平均自回归数据损失

Transformer 架构定义模型如何根据上下文计算下一个 token 的概率分布;交叉熵衡量该分布与真实 token 之间的差异;权重衰减等方法约束参数;反向传播计算梯度;AdamW 等优化器更新参数。四层框架仍然适用,但规模显著增加了工程难度:当参数量、训练 token 数量、设备数量和训练时间同时增长时,一个简洁的数学目标会变成优化、数值计算和分布式系统共同参与的问题。

第一,参数和优化器状态可能无法放入单张 GPU。 训练不仅要保存模型参数,还要保存梯度、Adam 类优化器的一阶矩和二阶矩,以及某些混合精度配置中的高精度参数副本。ZeRO 的不同阶段会在设备之间切分优化器状态、梯度和参数,减少数据并行训练中的内存冗余[20]。这正是第 3 章内存估算在大模型规模下的延伸:决定能否训练的往往不只是参数文件有多大,而是整个训练工作集的峰值内存。

第二,一次参数更新需要许多设备共同完成。 大规模训练可能组合数据并行、张量并行和流水线并行,分别拆分训练样本、层内张量计算或网络层。设备还需要交换梯度和中间结果,因此通信带宽、负载均衡以及通信能否与计算重叠,都会影响实际吞吐量。Megatron-LM 展示了将 Transformer 层内计算拆分到多个 GPU 的张量模型并行方法[21]。

第三,低精度计算节省资源,也缩小了数值安全范围。 FP16、BF16 或更低精度可以减少部分内存和计算成本,但不同格式的动态范围与有效精度不同,梯度可能发生上溢、下溢或舍入误差。经典混合精度训练使用高精度参数副本和 loss scaling 等方法缓解这些问题[22]。因此,第 7 章提到的 NaN、梯度范数和数值稳定性,在大模型训练中不是边缘问题。

第四,训练周期很长,小的不稳定也可能造成昂贵损失。 学习率预热与衰减、梯度裁剪、稳定的归一化结构、训练曲线监控和可恢复检查点都会影响一次训练能否持续进行。OLMo 的技术报告记录了学习率预热、线性衰减、梯度裁剪和混合精度等具体设置,说明公开的大模型训练同样需要这些基础措施[23]。

第五,预训练损失与最终使用目标并不完全相同。 更低的下一 token 交叉熵说明模型更善于预测训练分布中的文本,却不会自动保证答案可靠、有帮助或符合具体业务要求。监督微调、偏好优化和其他后训练阶段会引入新的数据、目标函数、约束和评价方式。每进入一个新阶段,都需要重新问:模型在预测什么?优化器真正最小化什么?离线指标与真实使用目标之间还有多大距离?

从 Gemini、ChatGPT 和 Claude 的公开资料看这些挑战 #

Gemini、ChatGPT 和 Claude 经常被当作三个“大模型名称”并列讨论,但它们并不处于完全相同的命名层次。Gemini 和 Claude 分别指向 Google 与 Anthropic 的模型族及相关产品;ChatGPT 则是 OpenAI 面向用户的产品,底层可以使用不同的 GPT 系列模型。下面不是比较三者的能力高低,而是借助各家公司公开的技术资料,观察前面的优化问题怎样出现在真实的大模型研发中。

资料时间说明:以下版本信息核对至 2026 年 10 月 8 日。 Google DeepMind 的官方模型页面当时已经列出 Gemini 4 Argon 和 Gemini 3.8 Flash,Gemini 3.7 因而不再是页面中最新的 Gemini 条目[24];OpenAI 的官方研究页面列出 GPT-6.1 Sol[25];Anthropic 的官方发布页面列出 Claude 5.5 系列[26]。这些产品名称和版本还会继续变化。

下表仍然选用 Gemini 1.5、GPT-4 和 Constitutional AI 作为案例,不是因为它们代表 2026 年 10 月的最新能力,而是因为相应公开报告对本文关心的长上下文、可预测缩放和偏好目标给出了较具体的技术说明。较新的产品页面并未公开完整的训练配方,因此不能仅凭版本号推断其优化方法。

公开案例公开资料中体现的技术挑战与本文概念的关系
Gemini 1.5Google 报告了跨文本、音频和视频的百万 token 级上下文能力,并采用稀疏混合专家结构[27]从工程角度推断,长上下文、多模态输入和稀疏专家结构会把序列长度、数据表示、内存与分布式执行带入同一个资源约束问题
GPT-4 与 ChatGPTOpenAI 指出,GPT-4 级别的训练无法承受大量针对最终模型的反复调参,因此需要让基础设施和优化过程在不同规模上具有可预测性,并根据小规模训练推测大型训练的损失与部分能力[28]对应学习率和训练稳定性,也说明为什么小规模实验、缩放规律和训练监控必须在昂贵的正式训练之前建立证据
Claude 与 Constitutional AIAnthropic 公开的 Constitutional AI 先让模型根据一组原则批评和修改回答,再通过 AI 生成的偏好训练奖励模型并进行强化学习;Anthropic 也说明 Claude 使用了由这些研究发展而来的原则[29][30]对应“目标函数究竟奖励什么”:把抽象的有帮助、无害等要求转化为数据、偏好信号和优化目标,本身就是模型训练的一部分

这三个案例分别落在统一地图的不同层次:Gemini 1.5 的公开报告涉及模型结构与资源约束,GPT-4 的报告强调昂贵训练中的可预测缩放,Constitutional AI 则说明行为原则怎样转化为偏好数据和训练目标。它们共同表明,大模型优化并不只是“更快地计算梯度”,还包括目标设计、数值稳定性、内存管理和分布式执行。

公开资料也有明确边界。上述报告没有完整披露当前商业模型的数据配比、全部损失项、优化器状态和训练基础设施,因此不能用这些案例复原 Gemini、GPT 或 Claude 当前版本的完整训练配方。读者研究具体版本时,仍需重新核对对应的技术报告和系统卡。尽管如此,第 2 章的曲率与学习率、第 3 章的训练工作集,以及第 7 章的梯度、低精度和训练曲线仍然适用。规模改变了实现难度和故障代价,却没有改变这些基本问题。

10.3 AI 工具怎样与基本原理配合? #

AI 工具可以生成代码、解释公式、建议超参数,也可以帮助定位训练异常。这些能力降低了使用模型的门槛,却不能替工程师回答几个根本问题:数据是否代表真实任务?目标函数是否表达了真正需要的结果?验证过程是否发生信息泄漏?一次指标改善究竟来自模型能力,还是来自数据变化、评价口径或随机波动?

工程师不必手工实现本文讨论的每一种优化器,也不需要背下所有推导。不过,掌握一些基本原理,会让工程师更容易判断工具给出的答案是否适合当前任务。例如,可以从区分模型、损失函数和优化器开始,再逐步读懂训练与验证曲线、估算主要内存开销,并把公式中的变量对应到代码、数据和业务含义。

工具能够承担越来越多的计算和实现工作,而问题定义、假设取舍与证据判断仍需要使用者参与。工程师不必与工具比较记忆量或计算速度;一种更可靠的配合方式,是让 AI 帮助展开计算、生成候选实现和检查遗漏,再由工程师依据数据、基本原理和可复核的验证结果作出判断。

下一次看到 model.fit(X, y),可以沿着四个问题继续展开:模型怎样产生预测?程序实际最小化什么目标?目标中包含哪些约束或先验?求解器怎样寻找参数?沿着这四个问题展开,model.fit(X, y) 就不再只是一个调用入口,而会成为理解模型为什么得到当前结果的起点。

参考资料 #

以下资料按照正文首次引用的顺序排列。论文和著作提供算法推导与研究背景;软件文档用于说明具体实现与接口行为。软件文档可能随版本更新,复现实验时还应同时核对所用版本的文档。

[1] Jorge Nocedal, Stephen J. Wright. Numerical Optimization. Springer, 2006.

[2] Trevor Hastie, Robert Tibshirani, Jerome Friedman. The Elements of Statistical Learning. Springer, 2009.

[3] scikit-learn. Linear Models User Guide. scikit-learn Documentation.

[4] Tianqi Chen, Carlos Guestrin. XGBoost: A Scalable Tree Boosting System. KDD, 2016.

[5] XGBoost. Tree Methods. XGBoost Documentation.

[6] Guolin Ke et al. LightGBM: A Highly Efficient Gradient Boosting Decision Tree. NeurIPS, 2017.

[7] LightGBM. Features. LightGBM Documentation.

[8] Yann LeCun, Léon Bottou, Yoshua Bengio, Patrick Haffner. Gradient-Based Learning Applied to Document Recognition. Proceedings of the IEEE, 1998.

[9] Sepp Hochreiter, Jürgen Schmidhuber. Long Short-Term Memory. Neural Computation, 1997.

[10] Geoffrey E. Hinton, Ruslan R. Salakhutdinov. Reducing the Dimensionality of Data with Neural Networks. Science, 2006.

[11] Ashish Vaswani et al. Attention Is All You Need. NeurIPS, 2017.

[12] Tom B. Brown et al. Language Models are Few-Shot Learners. NeurIPS, 2020.

[13] PyTorch. Autograd mechanics. PyTorch Documentation.

[14] Diederik P. Kingma, Jimmy Ba. Adam: A Method for Stochastic Optimization. ICLR, 2015.

[15] Sean J. Taylor, Benjamin Letham. Forecasting at Scale. The American Statistician, 2018.

[16] Prophet. Multiplicative Seasonality. Prophet Documentation.

[17] Prophet. Trend Changepoints. Prophet Documentation.

[18] Prophet. Seasonality, Holiday Effects, and Regressors. Prophet Documentation.

[19] Prophet. Diagnostics. Prophet Documentation.

[20] Samyam Rajbhandari, Jeff Rasley, Olatunji Ruwase, Yuxiong He. ZeRO: Memory Optimizations Toward Training Trillion Parameter Models. SC, 2020.

[21] Mohammad Shoeybi et al. Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism. 2019.

[22] Paulius Micikevicius et al. Mixed Precision Training. ICLR, 2018.

[23] Dirk Groeneveld et al. OLMo: Accelerating the Science of Language Models. ACL, 2024.

[24] Google DeepMind. Models. 访问日期:2026 年 10 月 8 日。

[25] OpenAI. Research Newsroom. 访问日期:2026 年 10 月 8 日。

[26] Anthropic. Newsroom. 访问日期:2026 年 10 月 8 日。

[27] Gemini Team et al. Gemini 1.5: Unlocking Multimodal Understanding Across Millions of Tokens of Context. 2024.

[28] OpenAI. GPT-4 Technical Report. 2023.

[29] Yuntao Bai et al. Constitutional AI: Harmlessness from AI Feedback. Anthropic, 2022.

[30] Anthropic. Claude’s Constitution. 2023.