主题
第 1 章 导数与计算图:程序怎样知道往哪儿改
训练一个神经网络之前,可以先解决一个更小的问题:程序算出了一个不满意的数,输入该往哪个方向改?后端程序员习惯沿调用链查错。这里也要沿依赖关系往回走,不过传回去的是一个数:输出对某个输入的变化有多敏感。
本章只用标量,也就是单个实数。先把导数算对,再谈矩阵和 GPU,会少掉许多同时出现的概念。本章对应课程第一讲前半 notebook 的函数、差分、计算图和手工求导部分;本文重新组织推导,不是视频转录。固定版本 notebook
1.1 从一个能运行的函数开始
设输入是实数
代入
把多项式展开,分子是
python
def f(x):
return 3*x*x - 4*x + 5
x, h = 3.0, 1e-6
slope = (f(x + h) - f(x)) / h这个近似称为前向差分。它不需要知道函数内部怎样写,代价是每个待检查方向都要重新运行函数。参数上百万时,用它训练模型不合适;用来检查少数梯度却很有价值。
为什么不让
更好的对照是中心差分:
若函数足够光滑,左右展开中的偶次项相消,截断误差由前向差分的
1.2 多个输入:每次只动一个
现在把程序写成
符号 “偏” 提醒我们,其他输入暂时固定。这些偏导数按输入顺序组成向量
还可以接着计算
图里的箭头记录依赖:算出
1.3 链式法则是一条局部乘法规则
先看离终点最近的乘法
再往前一层,
最后,
| 节点 | 前向值 | 对最终输出的导数 |
|---|---|---|
| 2 | 6 | |
| -3 | -4 | |
| 10 | -2 | |
| -6 | -2 | |
| 4 | -2 | |
| -2 | 4 | |
| -8 | 1 |
最后一行的 1 来自 .grad 表示最终目标对它的导数;局部规则负责把这个数继续向前传播。
有分叉时,还要相加。例如
在 +=。
1.4 梯度描述局部方向,不保证任意步长有效
若目标是减小
由一阶近似,
课程 notebook 的早期演示有一段沿正梯度方向改数值,用来观察输出增大。那与后面减小损失时使用负号并不冲突。另一个容易漏掉的条件是,必须先执行反向计算,否则初始梯度都是零,所谓更新根本没有移动。
交互实验:梯度下降与学习率
训练实验室 · 梯度下降
方向对了,步子太大会怎样?
只训练一个参数 w,让它靠近目标 t。调节步长,再亲手更新一次,看损失是否真的下降。
L(w) = (w − t)² · g = 2(w − t) · w ← w − ηg。每一步都按公式重新计算。
01
选一种走法,比较结果
02
输入 · 步长与目标
决定沿负梯度走多远。0 表示停在原地。同侧逐步靠近 · 误差 × 0.6
训练开始前,参数所在的位置。初始损失 16 · 梯度 8
损失曲线的最低点;到达这里时梯度为零。初始误差 w₀ − t = 4
滑块与精确输入控制同一个参数
03
过程 · 沿曲线更新参数
已更新 0 / 16 次
从 w = 4 开始,损失为 16,梯度为 8。
曲线保留可读尺寸。窄屏可左右滑动,手动滚动会暂停播放;键盘聚焦曲线区域后,用左右方向键查看坐标与轨迹。
指标保留完整数字;如数字较长,可左右滑动,或聚焦数字后用方向键查看。
当前参数 w4目标 0
当前损失 L16离目标距离的平方
下次使用的梯度8g = 2(w − t)
误差倍数 1 − 2η0.6绝对值小于 1 才会缩短距离
这组参数说明什么?学习率在 0 与 0.5 之间:从同一侧逐步靠近目标。
逐步数值记录(已完成 0 次更新)
保留完整数值。窄屏可左右滑动;键盘聚焦记录区域后,用左右方向键查看。
| 步数 | 参数 w | 梯度 | 损失 |
|---|---|---|---|
| 0 | 4 | 8 | 16 |
04
解释 · 方向之外,还要看步长
为什么这个例子能判断是否收敛?
令误差 e = w − t,一次更新后 e 新 = (1 − 2η)e,损失因此乘以 (1 − 2η)²。对非零初始误差,0 < η < 1 时逐步收敛;η=1 保持距离;η>1 放大距离。起点已经等于目标时,梯度为零,任何允许的学习率都不移动。
这是一个可完整算清的标量二次函数,运行的是真实梯度下降规则。神经网络有许多参数,损失曲面也不同;这里的学习率分界不能直接套到网络训练。没有训练数据、随机小批量、动量或 Adam。JavaScript 使用有限精度浮点数,极小时可能出现舍入或下溢。
不操作也能读懂:负梯度给出局部下降方向;学习率决定走多远。把 η 改成 1.2,可以看到“方向正确但损失越走越大”。
依据:PyTorch:梯度与参数更新;收敛分界由本页的二次函数直接推导。外部文档核对于 2026-10-14。
1.5 把计算结果交给测试
在项目根目录执行:
bash
source qa/environment/env.sh
python examples/part1/scalar_engine.py这是本书真实运行的小实验,完整记录在 qa/part1/scalar.log。它核对了 1.497e-09;这比脚本设置的
练习与解答
补充题:保持
官方 micrograd 练习第一部分要求对
求解析梯度,再比较前向差分和中心差分。对本题实数定义域取
在 examples/part1/micrograd_exercises.py,会以同一个
来源与边界
正文依据第一讲两份 MIT notebook 的已读取单元编写,固定提交为 73c3fcc741f0ec104ca850b1fb0df90e7e8d4cde;后半 notebook 开头重复的导数演示合并在本章。官方练习已取得原始 notebook 并逐题核对。视频描述的章节时间戳用于范围校验,不代表取得了完整字幕。配套代码的改编来源和 MIT 授权保存在 examples/part1/NOTICE.txt。