梯度下降

有了尺子,我们知道模型哪里不好。现在让计算机自动找到最好的参数

知识课 · 约 30 分钟 · 更新于 2026-06-05

梯度下降:自动寻找最低点

到这里,训练神经网络的拼图我们已经凑齐了三块: 用 线性模型 把输入映射到输出(模型结构), 手头有一批 数据 , 还有 损失函数 这把尺子来衡量预测离真实值有多远。 上一课的损失曲面也已经把答案画了出来:碗底对应的 就是最优参数。 还差最关键的一步——让计算机 自动 走到那个谷底,把最优参数找出来。

本节课要讲的 梯度下降 (Gradient Descent)就是完成这一步的算法, 它的核心思路是:每一步都朝 脚下最陡的下坡方向 迈出一小步,重复多次就能到达谷底。

这里有一个重要的观念转变:在梯度下降中, 「自变量」不再是数据 ,而是模型的参数 和 。 回忆一下:参数(parameter)是模型中需要通过训练来确定的值。 前面的课程里 和 都靠我们手动设定——也就是 人工调参 。 线性模型只有这 2 个参数,还能勉强应付;但真实神经网络的参数量动辄成千上万乃至上亿,人工调参根本不现实。 梯度下降要解决的,正是让计算机自动帮我们找到最优的 和 。

一维梯度下降

先考虑最简单的情况:只有一个参数 (theta), 损失函数为 ——即损失只取决于这一个参数的值。

导数 (derivative)告诉我们函数在某一点的变化率: 导数为正表示函数正在增大(往右走会上升),导数为负表示函数正在减小(往右走会下降)。 导数的绝对值越大说明坡度越陡。

算法步骤:

  1. 选择一个起点 (随机初始化)
  2. 设定一个正数 (eta)作为更新步长(含义见下文)
  3. 反复更新参数:

为什么是 减号 ?导数为正→函数在增大→要往负方向走; 导数为负→函数在减小→要往正方向走。减号正好实现了「总是往下坡方向走」。

上式中的 称为 学习率 (learning rate): 导数确定了下坡方向以及该方向上的陡峭程度, 则决定每一步沿这个方向走多远。 取得太小,每步只挪一点点,要迭代很久才能走到谷底; 取得太大,一脚跨过谷底反而到了对面坡上,可能反复震荡甚至越走越远。 因此 是需要人为选定的 超参数 ,下方就用一个交互实验来对比这几种情形。

交互动画展示一维梯度下降的完整更新过程:曲线为损失函数 ,红点是当前 所在的位置,淡色虚线记录历次迭代的轨迹。 先用滑块选择一个 ,再点击「下一步」执行一次参数更新——每点一次, 就按公式 移动一步。请分别尝试极小、合适、过大三档学习率,对照观察梯度下降是稳步收敛、缓慢爬行,还是来回震荡甚至发散; 点「重置」可回到起点重新开始。

多维梯度下降

回到线性回归 ,要优化的参数有 和 两个:

是 偏导数 (partial derivative),表示「只看 方向上损失变化有多快」。 把所有偏导数打包在一起,就得到了 梯度 (gradient):

梯度是一个向量,指向函数 增长最快 的方向。 梯度下降就是 沿梯度的反方向 走——往减小最快的方向走。

下面这个 3D 曲面展示了一个同时包含 鞍点 、 局部极小值 和 全局最小值 的函数。 鞍点是一个特殊位置——它在某个方向是谷底,但在另一个方向是山顶; 局部极小值在邻近区域是最低点,但并不是整个曲面的最低点; 只有全局最小值才是真正的「最低谷」。 调节学习率并点击「下一步」,观察梯度下降如何绕过鞍点,最终落到某个谷底。

你也可以点击「选择起点」然后在曲面上点击一个位置来设定新的起点—— 这对应着神经网络训练中的 参数初始化 。 实际训练中,不同的随机初始化可能让模型收敛到 不同的 谷底, 有时是全局最小值,有时只是局部极小值, 甚至卡在鞍点附近很久。试试不同的起点,感受初始化的影响!

学习率的选择

学习率 是梯度下降中最重要的 超参数 (hyperparameter,需要人为设定的参数):

  • 太小 :收敛极慢
  • 太大 :来回震荡,可能永远到不了最低点
  • 合适 :稳步收敛

实践:手动实现梯度下降

在学自动工具之前,先自己动手写一遍梯度下降的参数更新,感受核心逻辑。

实践:PyTorch 自动微分

上面的手动梯度下降中, loss.backward() 一行就自动算出了所有参数的梯度—— 这就是 PyTorch 的 自动微分 (Autograd)。 你只需写前向计算,PyTorch 自动帮你算反向梯度。

深度学习的通用训练范式

手动梯度下降已经把训练用到的零件——数据、模型、损失、参数更新——都串过一遍。 把这些零件整理成一个固定流程,就是 深度学习的通用训练范式 。 无论解决的是回归、分类还是更复杂的任务,只要用梯度下降训练神经网络, 整体流程都会落到下面这 「五步法」 上——它是与具体框架、具体模型无关的 通用骨架 。

  1. 准备数据 :把 输入与标签组织成张量,明确好形状(shape)。
  2. 定义模型 :写出从输入到输出的网络结构(线性层、卷积层、注意力层……), 并声明模型里需要被学习的参数。
  3. 选定损失函数与优化器 :损失函数衡量预测与真实值的差距(如均方误差、交叉熵); 优化器决定参数怎么按梯度更新(如 SGD、Adam)。
  4. 训练循环:前向 → 算损失 → 清旧梯度 → 反向求梯度 → 更新参数 。 这五个动作顺序固定、缺一不可——任何一步漏掉或顺序错了,训练都会出问题。把整个循环重复多轮,直到损失趋于稳定。
  5. 查看结果 :在测试 / 验证数据上评估模型,做推理、可视化或保存权重。

这五步是后面 所有 训练相关内容的基础。后续课程里出现的分类、CNN、Transformer 等更复杂的模型,骨架不会再变,变的只是第 2、3 步里换上更深的网络层与更合适的损失。 请把它在心里反复演练几遍,理解每一步的职责。

实践:PyTorch 中的五步法实现

理解了通用流程,再来看具体框架的落地。PyTorch 把上面五步里常用的零件做成了开箱即用的标准组件: nn.Linear 、 nn.Conv2d 等模块对应「定义模型」; nn.MSELoss 、 nn.CrossEntropyLoss 对应「损失函数」; optim.SGD 、 optim.Adam 对应「优化器」; 再配合自动微分自动算梯度,原本几十行的训练代码可以缩成十几行。

下面这段代码是用 PyTorch 训练线性回归模型的最简范本,请对照五步法逐条阅读, 看看每一步在 PyTorch 里具体落在哪几行:

后续课程将 不再重复讲整体流程 ,而是聚焦于「第 2、3、4 步里能怎么换得更好」—— 比如换更强的模型、换更合适的损失、给训练循环里加更巧妙的技巧(学习率调度、正则化、混合精度等)。

Playground:线性回归训练

把所有知识串在一起——自由调节学习率、噪声大小, 体验线性回归从随机参数到收敛拟合的完整过程。

附录:PyTorch 自动微分完整语法参考

PyTorch 自动微分(Autograd)的工作思路很简单:你写前向计算时它在背后悄悄记下每一步运算, 调用 .backward() 就沿着记录反向用链式法则把每个参数的梯度算出来——这正是 loss.backward() 一行能算出全部梯度的原因。 Autograd 内部如何组织这些运算记录,涉及 计算图 (Computational Graph), 后续会有一节课详细讲解,本附录先聚焦日常使用中常见的语法与注意点。