机器学习怎么把误差压小 —— 从「参数动一点,损失往哪边变」到梯度下降与反向传播

机器学习把误差压小的办法只有一条:先算出「参数动一点,损失会往哪边变、变多少」,再沿着让损失变小的方向反复调参数。这句话里的两件事就是本篇要讲清楚的全部内容:前半句是偏导与梯度怎么定义、怎么算;后半句是梯度下降怎么沿负梯度走,以及反向传播怎么用链式法则把 $\partial L / \partial w$ 一层层乘回来。

机器学习在找什么:模型就是一张从 X 映射到 Y 的表

机器学习本质上是在学一个映射函数 $Y = f(X)$。$X$ 是你喂给机器的特征,$f$ 是模型,$Y$ 是模型给出的预测。模型不是什么黑箱魔法,它就是一堆可以调的数(参数)拼成的函数;训练要做的事只有一件:反复调这些数,让预测值和真实值之间的差距越来越小。Goodfellow 等人的《Deep Learning》在给模型下定义时也只说它是一个函数,整本书的重点全在「这个函数怎么学出来」。DeepLearning

讲义把这件事拆成三部分:输入 X、模型 f、输出 Y。模型里的参数,就是神经元之间每一条连接上的权重。

图注:讲义给全篇立的中心公式。Y 用浅绿色底块标出,代表输出;f 用浅黄色底块标出,代表映射关系本身;括号里的 X 用浅蓝色底块标出,代表输入。三块底色把「输入经过一个函数得到输出」直接画了出来。

这个函数要画成什么样?把样本简化到二维,目标就是在平面里找到一条直线把两类分开,这条线叫决策边界。

图注:讲义自带的决策边界图。五个蓝色圆点落在直线一侧,五个红色叉号落在另一侧,直线上方标注着 f(X)。

如果数据不是线性可分的,就得用更复杂的函数(曲线或曲面),参数数量会大幅增加。这就带出两个问题:参数量到底意味着什么,以及我们怎么学到这些参数。第一个问题,Stanford 的 CS231n 课程笔记给了官方对照图:

图注:CS231n 官方对照图,三个子图分别是 3 个、6 个、20 个隐藏神经元。隐藏神经元越多,训练出来的决策区域可以切得越碎,20 个神经元那张已经把红绿两色的区域切成互不相连的小块。CS231n

这里要小心一个常见误解:网络容量大不等于更好。CS231n 的结论是,不该因为怕过拟合而用更小的网络,而应该在算力预算内用尽可能大的网络,用别的正则化手段控制过拟合。CS231n

第二个问题是训练。讲义给出的训练闭环只有两条路:向前算预测,向后调参数。

图注:讲义的训练闭环图。上方橙色箭头标着 Feed-forward,从左往右,输出层的 y 是预测值;下方橙色箭头标着 Back-propagation,从右往左。预测 y 与真值 y' 之间那道蓝色双向箭头,就是「差距」所在。

常见的做法是随便试几个方向,哪个损失小往哪走。这个做法偶尔能猜对,但既说不清为什么,也算不出该走多远。接下来几章要把这个猜测升级成一条能算、能复述的规则。

偏导与梯度:参数动一点,损失往哪边变、变多少

偏导数就是固定其他变量之后,损失对单个参数的变化率;梯度是所有偏导组成的一个方向,它指向上坡,取负号才是下坡;链式法则说外层变化率乘内层变化率,这就是后面「梯度一层层往回乘」的全部依据。

先说导数。一元函数里,导数就是曲线在某一点的切线斜率。3Blue1Brown 的官方课程说得很准:真正的导数不是两点之间的「升高除以水平距离」,而是「在某一点处与图像相切的那条线的斜率」。3Blue1Brown

然后是偏导。参数不止一个,损失 $L$ 既依赖 $w$ 也依赖别的量。于是固定其余变量,只让 $w$ 动一点点,问两个问题:损失往哪边变?变多少?「变多少」就是偏导数 $\partial L / \partial w$。几何上的说法是:损失是一个曲面,固定其他维度相当于用一张平面把它切一刀,切口是一条曲线,这条曲线在 $w$ 方向的斜率就是偏导数。这个「切面」的说法出自 3Blue1Brown 官方页面直接链接的 Khan Academy 多元微积分文章,不是 Essence of Calculus 系列本身。

规范符号出自《Mathematics for Machine Learning》:偏导数写作差商的极限,梯度则是「把每个变量逐个变化一次、其余保持不变,把得到的这些偏导收集起来」:

$$\frac{\partial f}{\partial x_1} = \lim_{h \to 0} \frac{f(x_1 + h, x_2, \dots, x_n) - f(x)}{h}, \qquad \nabla f = \left[\frac{\partial f}{\partial x_1}, \dots, \frac{\partial f}{\partial x_n}\right]$$

MML

梯度是一个方向,不是要你去试方向。

图注:3Blue1Brown 官方配图。绿色箭头标着 ∇C(x,y),图上写明它是「方向最陡上升」;红色箭头指向相反方向,也就是负梯度。官方图注一句话点破:梯度给出上坡方向,所以梯度的相反数给出下坡方向。3Blue1Brown

这一步把「随便试方向」换掉了:函数自己就指出了最快上坡的方向,取负就是最快下坡。梯度向量的长度还有第二层含义,它告诉你这坡有多陡。

接下来是链式法则,也就是剥洋葱。

图注:3Blue1Brown 官方的一元链式法则图。公式 d/dx g(h(x)) = (d/dh) g(h(x)) · (d/dx) h(x),四组花括号分别标出 Inner、Outer、d(Outer)、d(Inner),正好对应右边那两个相乘项。3Blue1Brown

所谓复合函数,就是外层套内层:$y = f(u)$,$u = g(w)$。要问 $\partial y / \partial w$,就拆成两个问题:$u$ 动一点、$y$ 变多少($\partial y / \partial u$),$w$ 动一点、$u$ 变多少($\partial u / \partial w$),两个乘起来就是答案:$\partial y / \partial w = (\partial y / \partial u) \cdot (\partial u / \partial w)$。官方课程把它比作剥洋葱:每一层都得单独处理,一次处理一层。3Blue1Brown

多元版本同理,只是中间层换成向量,$\partial L / \partial w = (\partial L / \partial a) \cdot (\partial a / \partial w)$,中间那个量像矩阵乘法里被约掉一样。到这里,最后一章要手算的 $\partial L / \partial w = 2(a - y) \cdot x$ 所需的零件全部齐了:一个变化率(偏导)、一个方向(梯度)、一条把局部变化率串成整体变化率的规则(链式法则)。

模型在什么数据上学、又在什么数据上被评价

学习类型由数据有没有标签决定;训练集、验证集、测试集各管一段,所以「训练损失在降」并不等于「模型真的变好」。

讲义按「有没有标签」把机器学习分成四类。监督学习的数据全部带标签(手机人脸解锁的初始设置);无监督学习完全没有标签(手机相册里的「人物」聚类);半监督学习只有一部分带标签(「抬手唤醒」用少量人工「本人」标注加上海量无标签的传感器记录);强化学习没有预设标签,智能体通过与环境交互、拿奖励或惩罚来学习(送货机器人撞到障碍物扣分、到达充电站加分)。Goodfellow 等人提醒过一句:监督学习与无监督学习这两个术语「并非严格定义的术语」。DeepLearning

模型类别是另一套划分,不能和上面这套混:分类模型输出离散标签,回归模型输出连续值,聚类模型在无标签数据里自行分组。输出长什么样决定模型类别,数据带不带标签决定学习类型。

讲义第 11 页已经给了三份数据的职责:训练集用来训练模型,模型反复学习模式并更新内部参数;验证集指导调参,不直接更新模型参数;测试集只在最终评估阶段使用,训练或调参期间绝不使用。

官方文档把这件事说得更硬。scikit-learn 官方用户指南直接写明:「Test data should never be used to make choices about the model.」同一份文档把过拟合的起点也定在这里:在同一份数据上训练又测试是一种方法学错误,因为一个只会把刚看过的标签背下来的模型可以得到满分,却对未见数据毫无用处。sklearn

图注:scikit-learn 官方的交叉验证工作流图。Dataset 先分成 Training data 与 Test data,Test data 直到最后一步 Final evaluation 才被接进来;Parameters 与 Training data 一起进 Cross-validation,产出 Best parameters,再用它重训得到 Retrained model,最后才和 Test data 一起做最终评估。sklearn

数据泄漏有两种典型形态。官方给的定义是:预测时拿不到的信息被用进了模型构建过程,结果是成绩乐观得离谱,真正上线反而变差。第一种是切分之前就做了预处理,比如用全体数据的均值做标准化。官方文档的例子里,只用训练集拟合标准化时测试集 MSE 是 62.80,对测试集也做同样变换后掉到 0.90。这两个数字来自文档里那份特定的合成数据与随机种子,不是通用规律,说明的是方向:泄漏会让成绩好得不真实。第二种是拿测试集去做特征选择或超参搜索。

过拟合与欠拟合怎么判,官方给的标准是训练分与验证分的组合:

训练分验证分结论
低低欠拟合,模型太简单
高低过拟合,模型把训练数据背下来了
高高拟合良好

还有一个容易忽略的点:验证集分数本身也会被调优掉,因为你是照着它挑参数的。要拿到一个诚实的泛化估计,还得再留一份没参与任何选择的测试数据。

差距要先变成一个能算的数:模型、学习准则、优化方法

学习准则就是损失函数,它把「差距」写成一个可以计算的数;平方损失用于回归,交叉熵用于分类,而 0-1 损失只能当评估指标,因为它在大多数点上根本求不出导数。

讲义给机器学习列了三要素。

图注:讲义的三要素结构图。顶部主框 The Three Elements of Machine Learning 向下引出 Model、Learning Criterion、Optimization Method 三个模块,底部云朵注释写着一句关键点:a model is essentially a mapping function。

模型就是第一章那个映射函数。优化方法是后面两章的梯度下降。学习准则这一项,讲义给的定义是「一条判断模型预测是否准确的规则,核心思想是让预测值与真实标签之间的差距尽可能小」,落到具体函数上就是损失函数 $L(Y_{pred}, Y_{true})$:把差距量化成一个数,损失越小模型越好。只有先定义了怎么量化差距,才谈得上把它压小。

三种常用损失各有各的位置。

0-1 损失在二分类里最直观:预测对损失为 0,预测错损失为 1。它的问题不在定义,而在不可优化。Goodfellow 等人把错误率称为「期望的 0-1 损失」,也就是把它当性能度量;在优化那一章他们明确写道,像 0-1 损失这样的函数「没有可用的导数,导数要么是零,要么处处无定义」。所以训练用交叉熵,评价才用 0-1 损失。这也正是「训练损失」和「准确率」不是一回事的根本原因:前者是优化的目标,后者是报告出来的指标。DeepLearning

平方损失 $L(y, \hat{y}) = (y - \hat{y})^2$ 主要用于回归。为什么要平方,讲义给了两条理由。一是去掉符号:平方后损失恒为非负,高估和低估都会受罚,0 表示完美预测。二是重罚大误差:手机 A 的预测误差是 100 元,$(100)^2 = 10,000$;手机 B 的误差是 200 元,$(200)^2 = 40,000$。误差只翻了一倍,损失却变成四倍,所以模型会优先削减大的预测误差。

交叉熵损失 $L(y, \hat{y}) = -\sum_i y_i \log \hat{y}_i$ 常用于分类问题。要算它,得先知道两件事。第一是独热编码:用一个只有一位是 1(hot,热点)、其余全是 0(cold,冷点)的向量表示一个类别。第二是模型输出的是一个概率分布。讲义给的例子是手机人脸识别:模型看到张三的脸后,预测是张三 0.85、李四 0.10、王五 0.05,而真实标签是张三,独热向量 [1, 0, 0]。代入进去:

$$L = -\left[1 \cdot \log(0.85) + 0 \cdot \log(0.10) + 0 \cdot \log(0.05)\right] = -[\log(0.85) + 0 + 0] = -\log(0.85)$$

独热向量里只有一位是 1,所以整串求和只剩下一项。这就是交叉熵偏爱「正确的确信」的原因:预测分布越接近真值,$-\log$ 那一项越小;而「确信但错」的那一侧,曲线会急剧升高。

图注:Deep Learning 书里的二元香农熵曲线。两端趋近 0(分布接近确定),p = 0.5 处达到峰值(分布最均匀)。这张图画的是香农熵本身,不是交叉熵损失;「确信但错」的惩罚要到 −log p 这条曲线上才看得到(真值为 1 时 p→0 处 −log p 急剧升高)。DeepLearning

为什么 softmax 输出层要配交叉熵?官方给的理由是,softmax 用 exp 归一化,对数似然里的 log 恰好能把 exp 抵消掉;如果目标函数不这么配,在 exp 的参数很负时梯度会消失。DeepLearning CS231n 课程笔记里还有一条官方对照:L2 损失比 Softmax 难优化得多,而且对离群点脆弱。CS231n

损失公式用在哪能否当训练目标
0-1 损失预测对 0,预测错 1评估(错误率)不能,多数点上没有可用导数
平方损失$(y - \hat{y})^2$回归能,但官方指出它比 Softmax 难优化、对离群点脆弱
交叉熵$-\sum_i y_i \log \hat{y}_i$分类(配 softmax)能,官方推荐

沿最陡下坡的方向走:负梯度与学习率

梯度下降就是沿着负梯度反复走,每一步迈多远由学习率决定;每步用多少样本决定稳不稳;batch size、iteration、epoch 这三个词必须分清。

先补规范依据。《Mathematics for Machine Learning》写得很明确:梯度指向最陡上升的方向,而且与函数的等高线正交。Deep Learning 书里同一件事的措辞是「梯度直接指向上坡,负梯度直接指向下坡」。所以沿负梯度走不是经验规则,是定义。MML

图注:MML 教材的示例目标函数图。曲线上四个黑色箭头沿切线指向下坡,按官方图注这些是负梯度;最深的谷底用蓝色虚线标为全局最小。右侧还有一个较浅的谷底,说明从不同起点出发会走到不同的局部极小。MML

更新式就是讲义给的那一条:

$$\theta(t+1) = \theta(t) - \eta \nabla L(\theta(t))$$

MML 用 $\gamma$ 表示步长、用行向量记梯度,写成 $x_{i+1} = x_i - \gamma_i ((\nabla f)(x_i))^T$,那是教材记号,和讲义的 $\eta$ 是同一件事。MML

图注:讲义自己的梯度下降流程图。纵轴是总损失 L,横轴是参数 w;曲线上引出一条蓝色切线虚线,横轴上用红色括号标出位移量 −η·∂L/∂w,右下角橙色框写着 η is called "learning rate"。

一次迭代就是四步:随机初始化参数,前向算出预测与损失,反向算出梯度,沿负梯度更新参数,然后重复。

讲义接着提了两个问题。第一个是每步用多少样本。

方法每次用的数据特点
批量梯度下降 BGD整个训练集稳定、缺少随机性、内存占用低
随机梯度下降 SGD单个样本波动大、收敛不稳定、内存占用低
小批量随机梯度下降一个小批次兼顾稳定性与随机性,实践中最常用

这里有个术语陷阱要点名一次:官方文档提醒,「batch gradient descent」通常指用整个训练集,但「batch size」这个词在实践中常常指的是一个 minibatch 的大小,与讲义把 batch 当作整个训练集的用法同名异义。DeepLearning

第二个问题是步子迈多大,也就是学习率。太大会 overshoot,甚至无法收敛;太小则收敛很慢。PyTorch 官方教程把梯度回传写成了 API:.backward() 从根节点沿链式法则逐节点回传,梯度累加进参数的 .grad,而 .grad 默认是 None,第一次 backward 之后才变成张量,之后不清零就会继续累加。PyTorch

按这套官方语义写一段最小示例(a = ⟨x,w⟩、b = a − y、L = b²)本地实跑一遍就能看到:同一组梯度下,学习率 0.01 让损失从 0.01 降到 0.005184;换成 0.1,损失反而升到 0.0324。

最后把三个词钉死。batch size 是一个 mini-batch 里的样本数;iteration 是用一个小批次做一次参数更新;epoch 是把整个训练集完整过一遍。关键关系是「每轮的迭代次数 = 训练样本数 ÷ 批大小」,讲义给的例子是 10,000 ÷ 50 = 200。

梯度是一层层乘回来的:∂L/∂w = 2(a−y)·x 的四步手推

反向传播没有新魔法,它就是把链式法则沿计算图一层层乘回来,$\partial L / \partial w = 2(a - y) \cdot x$ 你能自己手算出来,而今天的框架只是把这条链自动走了一遍。

先看讲义自己的计算图。

图注:讲义的核心计算图。底层是 x 与 y;x 与 w 在下一层得到 a = ⟨x,w⟩;a 与 y 再得到 b = a − y;顶层是 L = b²。箭头自下而上,表示前向计算方向。

前向三步算完,目标就是 $\partial L / \partial w$。讲义把它拆成四步反向累加,每一步都只是一次链式法则。

第一步,声明目标:要算 $\partial L / \partial w$。

第二步,$\partial L / \partial b = 2b$。这一步用的是平方函数自己的导数,但它需要 b 的数值,而 b 是前向算出来的,所以讲义在这一行写着「读取预计算结果」。

第三步,$\partial L / \partial a = \partial L / \partial b \cdot \partial b / \partial a = \partial L / \partial b$。因为 $b = a - y$ 里 $y$ 是常数,所以 $\partial b / \partial a = 1$,这一层相当于乘了个 1。

第四步,$\partial L / \partial w = \partial L / \partial a \cdot \partial a / \partial w = (\partial L / \partial a) \cdot x$。因为 $a = \langle x, w \rangle$ 是 x 与 w 的内积,对 w 求导就是 x。

四步合起来:

$$\frac{\partial L}{\partial w} = \frac{\partial L}{\partial b} \cdot \frac{\partial b}{\partial a} \cdot \frac{\partial a}{\partial w} = 2b \cdot 1 \cdot x = 2(a - y) \cdot x$$

讲义第 57 页还给了链式法则的一般展开式:$\partial y / \partial x = (\partial y / \partial u_n) \cdot \dots \cdot (\partial u_1 / \partial x)$。所以不管网络有几层、节点有几个,规则都是同一条:梯度沿着计算图一层层往回乘。

图注:CS231n 官方课程笔记里的同一件事。绿色数字是前向算出的值(x = −2、y = 5、z = −4,中间量 q = 3,输出 f = −12),红色数字是反向回传的梯度。官方图注说得很清楚:前向从输入到输出算值,反向从末端开始递归地套用链式法则,把梯度一路送回输入端。CS231n

计算图的规范定义是:节点表示变量,边表示运算,整体是一张有向无环图;前向按顺序算值,反向逐节点把梯度传给所有输入。如果同一个节点可以从两条以上的路径到达,各条路径到达的梯度要相加。DeepLearning

CS231n 把反向流总结成三条可复用的规律,用「门」来讲:

门反向流的行为
加法门把输出上的梯度等分给所有输入,与前向数值无关
最大值门把梯度路由给前向中取值更高的那一个输入
乘法门局部梯度是「另一个输入的值」,再乘上输出端的梯度

CS231n

乘法门那条规律还带出一个反直觉的后果:如果把所有输入放大 1000 倍,权重上的梯度也会大 1000 倍,学习率必须相应调小同等倍数。这也是数据预处理为什么重要。

今天在框架里,这套东西长这样:

图注:PyTorch 官方教程里的算子级 DAG。节点画的是前向各操作对应的反向函数,蓝色叶子节点是叶子张量,箭头方向是前向传播方向(不是梯度流向)。PyTorch

autograd 的作用就是把上面那条链自动走一遍:前向时它把操作记录成一张有向无环图,反向时从输出开始沿链式法则逐节点回传,把梯度累加进参数的 .grad。你手算的 $\partial L / \partial w = 2(a - y) \cdot x$,框架算出来就是同一个数。

这套方法不是新把戏。1986 年 10 月,Rumelhart、Hinton 和 Williams 在 Nature 上发表短文,摘要第一句就是「我们描述一种新的学习过程,back-propagation」,正文把「反向传播把导数从顶层一路传回底层」写成了带编号公式的算法步骤。Rumelhart1986

图注:1986 年那篇论文画的网络结构:顶部一个 Output unit,左右各一个 hidden unit,中间一列 Input units,连线上标着权重,节点圆圈里标着偏置。图上没有反向箭头,也没有任何梯度标注。Rumelhart1986

作者自己也在同一篇论文里点了名:误差面可能存在局部极小,所以梯度下降不保证找到全局最小;方法不利用二阶信息,收敛不如用二阶导数的方法快;末页更直说「以现在的形式,这个学习过程不是大脑学习的合理模型」。这些在 1986 年就已经是公开的局限。

2026 年 10 月的一篇综述仍然把这件事当作开放的联系点在重述:它把反向传播与最优控制之间的关联称为控制理论与深度学习之间的「另一个接触点」(another point of contact),并用离散时间模型重建了 80 年代就已知的经典联系。这里说的是关联,不是等同。ControlView

时间代表材料贡献
1986-10Rumelhart, Hinton & Williams, Nature 323:533–536误差回传的公开成文表述
2016Goodfellow 等,Deep Learningsoftmax 与交叉熵、计算图与反向传播算法的规范表述
2017 起3Blue1Brown 官方可视化课程(微积分系列自 2017-04 起;梯度与梯度下降两讲属其神经网络系列,2017-10)把链式法则、梯度与梯度下降做成官方可视化
2020-04Deisenroth 等,Mathematics for Machine Learning偏导、梯度、链式法则与梯度下降的规范定义
2026-10Deep learning from a control vantage point反向传播与最优控制之间仍被重述的理论关联

从 Y = f(X) 到 $\partial L / \partial w = 2(a - y) \cdot x$,这条链的每一环现在都能自己复述:模型是一个从 X 到 Y 的映射函数,损失函数把差距写成一个数,梯度下降沿负梯度走,学习率管步子,反向传播用链式法则把梯度一层层乘回来。

参考文献

本专题引用的核心资料如下,建议深入学习时阅读原文:

  1. 本篇主体材料:Chapter 3 · Fundamentals of Machine Learning(Li Liu 课程讲义,58 页英文教学幻灯片,用户上传) — 全篇的记号(a / b / L、η、∂L/∂w)、公式与手算例子均出自此讲义
  2. Mathematics for Machine Learning(Deisenroth, Faisal, Ong;Cambridge University Press 官方免费 PDF,2020-04) — https://mml-book.github.io/book/mml-book.pdf
  3. Essence of Calculus / Neural Networks(3Blue1Brown 官方可视化微积分课程,2017 起) — https://www.3blue1brown.com/lessons/essence-of-calculus
  4. Deep Learning(Goodfellow, Bengio, Courville;MIT Press 2016 官方免费在线版) — https://www.deeplearningbook.org/
  5. CS231n 课程笔记(Stanford):Neural Networks 1/2 + Backpropagation(站点当前标注 Spring 2026) — https://cs231n.github.io/optimization-2/
  6. PyTorch 官方教程:Automatic Differentiation (autograd) — https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html
  7. scikit-learn 官方用户指南 1.9.1:Common Pitfalls / Cross-validation / SGD — https://scikit-learn.org/stable/common_pitfalls.html
  8. Learning representations by back-propagating errors(Rumelhart, Hinton, Williams;Nature 323:533–536,1986-10-09) — https://www.cs.toronto.edu/~hinton/absps/naturebp.pdf
  9. Deep learning from a control vantage point(arXiv:2610.14385,2026-10-09) — https://arxiv.org/abs/2610.14385
机器学习怎么把误差压小 —— 从「参数动一点,损失往哪边变」到梯度下降与反向传播