第11讲 梯度下降到底在做什么?

很多人第一次学到“梯度下降”时,都会有一种很强的不安。

名字听起来很数学,公式看起来也很复杂:

  • 梯度
  • 求导
  • 学习率
  • 参数更新

这些词单独看都不陌生,但连在一起时,初学者最容易陷入一种状态:

公式会抄,过程会背,但并不知道它到底在做什么。

更具体一点,很多困惑都集中在下面几个问题上:

  • 梯度到底是对谁求的?
  • 为什么要对它求导?
  • 输入 (x) 也在公式里,为什么不去改输入?
  • 模型训练时,到底什么在变,什么不变?

如果这些问题没有想清楚,那后面即使继续学反向传播、神经网络训练,也很容易一直停留在“会写不会懂”的层面。

所以这一讲,我们不急着上来就堆公式,而是先把最核心的一件事讲清楚:

梯度下降,本质上是在根据损失函数的变化趋势,去调整模型参数,让模型犯的错越来越小。

而训练之所以要这样做,是因为机器一开始并不会分类,它是通过大量样本不断调整内部参数,慢慢把判断规则学出来的 。


一、梯度下降到底在解决什么问题?

前面我们已经知道,机器学习不是一个抽象的“让机器变聪明”的过程,而是在学习一种从输入到输出的映射关系。

对于分类模型来说,过程通常是这样的:

  1. 输入数据进入模型
  2. 模型给出预测结果
  3. 预测结果和真实答案之间会有差距
  4. 我们需要根据这个差距去调整模型参数

其中,模型一开始并不会分类,它只是带着一组初始参数去做计算;之所以后来能识别数字,是因为它在大量样本中不断试错、不断修正,最后学会了一套更好的分类规则 。

于是问题就来了:

既然已经知道模型当前错了多少,那参数到底该怎么改?

这正是梯度下降要解决的问题。

换句话说,梯度下降真正关心的不是“模型会不会分类”,而是:

怎样调整参数,才能让损失函数变小?


二、先把最关键的一点讲清楚:我们到底在对谁求导?

这是初学者最容易卡住的地方。

假设我们现在有一个训练样本:

  • 输入:(x)
  • 标签:(y)

模型根据当前参数做出预测:

[
\hat{y} = f(x; w, b)
]

然后我们用损失函数来衡量预测和真实答案之间的差距:

[
L = L(y, \hat{y}) = L(y, f(x; w,b))
]

看到这里,很多人会疑惑:

损失函数里面明明有 (x)、(y)、(w)、(b),那我们到底在对谁求导?

答案一定要非常明确:

我们是在对参数求导。

也就是:

[
\frac{\partial L}{\partial w}, \quad \frac{\partial L}{\partial b}
]

而不是去求:

  • 输入怎么变
  • 标签怎么变

因为训练模型时,当前这一步里:

  • 输入 (x) 是给定的数据,视为常量
  • 标签 (y) 是标准答案,视为常量
  • 真正需要学习、需要调整的是参数 (w,b)

所以从训练的角度看,当前真正的未知数不是输入,而是参数。

这一点必须想清楚,因为后面所有“求梯度”“更新参数”的操作,都是建立在这个前提上的:

我们关心的是:参数稍微变一点,损失会怎么变。


三、为什么输入看成常量,参数看成变量?

因为训练的目标不是改数据,而是改模型。

机器学习的基本框架里,数据提供输入,标签提供标准答案,任务定义了我们到底要学什么。
这些东西一旦确定,在当前训练步骤里就已经是已知的了。

比如一张手写数字图片,它的像素值就是当前输入;
它对应的标签“这是数字 3”,也是已知答案。

训练时我们不会做的事情是:

  • 把这张图片偷偷改一改
  • 把标签临时换一个
  • 让数据去适应模型

我们真正做的是反过来:

让模型的参数去适应数据。

而前面也已经讲过,分类模型的判断能力,本质上就是由参数塑造出来的;学习这件事,说到底就是在调参数 。

所以在求导时:

  • (x, y) 看成常量
  • (w, b) 看成变量

这是训练过程最自然、也是最核心的视角。


四、为什么我们优化的是损失函数?

这也是很容易被忽略的一点。

很多人会说:
“训练模型不就是为了提高准确率吗?为什么不直接优化准确率?”

因为训练时,我们需要一个可以计算、可以比较、可以优化的目标,而损失函数正是为此存在的 。

损失函数的作用,不是简单判断“对”还是“错”,而是把预测结果和真实答案之间的差距,变成一个可以优化的数值 。

这意味着什么?

意味着:

  • 预测错了,损失通常会比较大
  • 预测对了,也不代表损失一定很小
  • 同样都是预测对,0.51 和 0.99 的把握程度不一样,损失也可能不一样

所以训练不是只关心“最后类别对没对”,而是关心:

当前预测离真实答案到底还有多远。

这就是为什么梯度下降优化的对象不是“准确率”本身,而是损失函数 。


五、梯度到底是什么?

把前面的铺垫都放好以后,现在就可以谈“梯度”了。

如果先只考虑一个参数 (w),那么梯度你可以先理解成:

损失函数对参数 (w) 的导数。

写成公式就是:

[
\frac{dL}{dw}
]

它表示的是:

如果参数 (w) 变动一点点,损失 (L) 会怎样变化。

注意这里的主语一定是“损失函数”。

也就是说,梯度不是一个脱离上下文的抽象概念,
它在训练里说的其实是:

损失函数关于参数的变化趋势。

比如:

  • 梯度是正的,说明参数往增大的方向走时,损失倾向于变大
  • 梯度是负的,说明参数往增大的方向走时,损失倾向于变小
  • 梯度接近 0,说明当前位置可能已经比较平缓了

所以梯度并不是“模型理解了答案”,
它只是告诉我们:

在当前位置,参数往哪边改,更可能让损失下降。


六、为什么叫“梯度下降”?

这个名字其实非常形象。

你可以把损失函数想象成一片地形:

  • 地势高的地方,表示损失大,说明模型错得多
  • 地势低的地方,表示损失小,说明模型错得少

而模型当前的参数位置,就相当于你站在这片地形中的某个点。

现在我们的目标很简单:

从高处往低处走。

那该怎么走?

最自然的办法是:

  1. 先看当前位置朝哪个方向上升最快
  2. 然后不要顺着这个方向走
  3. 而是朝着相反方向走一步

这就是“梯度下降”的含义:

  • 梯度:告诉你上升最快的方向
  • 下降:我们偏偏朝相反方向走,让损失变小

所以它本质上并不神秘,
只是一个非常朴素的优化思路:

根据当前位置的局部变化趋势,沿着让损失减小的方向去更新参数。


七、梯度下降的更新公式到底在说什么?

最经典的参数更新公式是:

[
w \leftarrow w - \eta \frac{\partial L}{\partial w}
]

如果模型里还有偏置 (b),那它也会更新:

[
b \leftarrow b - \eta \frac{\partial L}{\partial b}
]

这个公式第一次看很吓人,但拆开以后其实只有三层意思。

1)(\frac{\partial L}{\partial w}) 是什么?

它表示的是:

损失函数对参数 (w) 的导数。

也就是:
如果 (w) 发生一点变化,损失会怎样变化。

这一项一定不能含糊。
因为训练时我们不是在对模型随便求导,而是在对损失函数关于参数求导。

2)(\eta) 是什么?

(\eta) 是学习率。
它决定每次更新时,参数走多大一步。

你可以把它理解成:

  • 方向由梯度决定
  • 步子大小由学习率决定

3)为什么前面是减号?

因为梯度指向的是“损失上升更快”的方向。
但训练目标是让损失下降,所以我们要朝相反方向走。

因此,更新公式里的核心逻辑就是:

参数的新值 = 参数的旧值 - 学习率 × 损失对参数的梯度


八、先用一个最简单的损失函数,理解“对损失求导”到底是什么意思

一上来就讲神经网络,很容易把问题搞复杂。
所以我们先看一个最简单的例子:

[
L(w) = w^2
]

这里故意把它写成 (L(w)),就是为了强调:

现在我们正在优化的,就是一个损失函数。

问题很直接:

怎样调整参数 (w),让损失 (L(w)) 变小?

第一步:先对损失函数求导

[
\frac{dL}{dw} = 2w
]

这个导数告诉我们:

  • 当 (w > 0) 时,梯度是正的
  • 当 (w < 0) 时,梯度是负的
  • 当 (w = 0) 时,梯度是 0

第二步:按梯度下降公式更新

假设学习率 (\eta = 0.2),那么更新公式就是:

[
w \leftarrow w - 0.2 \cdot 2w
]

如果一开始:

[
w = 4
]

那么:

  • 当前损失是 (L(4)=16)
  • 当前梯度是 (\frac{dL}{dw}=8)

更新后:

[
w \leftarrow 4 - 0.2 \times 8 = 2.4
]

再来一步:

  • 当前损失变成 (L(2.4)=5.76)
  • 当前梯度变成 (4.8)

于是继续更新:

[
w \leftarrow 2.4 - 0.2 \times 4.8 = 1.44
]

你会发现,(w) 在逐渐接近 0,损失也在不断下降。

这个例子虽然简单,但它已经完整说明了梯度下降的本质:

先对损失函数关于参数求导,再根据这个导数去调整参数。


九、把“输入是常量,参数是变量”放进模型里看一遍

上面的例子太简单了,没有输入数据。
现在我们看一个更接近机器学习训练的形式。

假设模型非常简单:

[
\hat{y} = wx + b
]

然后定义损失函数:

[
L = (y - \hat{y})^2 = (y - (wx+b))^2
]

注意这个式子里一共有四类量:

  • (x):输入
  • (y):真实标签
  • (w):权重
  • (b):偏置

在当前这一步训练时:

  • (x) 是给定样本,视为常量
  • (y) 是标准答案,视为常量
  • (w,b) 是模型参数,视为变量

所以我们真正关心的是:

[
\frac{\partial L}{\partial w}, \quad \frac{\partial L}{\partial b}
]

而不是去改 (x) 或 (y)。

这一点一旦想通,后面哪怕模型从线性模型变成神经网络,本质也没有变。
只不过函数形式更复杂了,但核心仍然是:

研究损失函数随着参数变化会怎样变化。


十、用代码看一遍,梯度下降到底做了什么

下面用一个最小可运行例子,把刚才的过程写成代码。

这里还是用最简单的损失函数:

[
L(w)=w^2
]

对应代码如下:

w = 4.0
lr = 0.2

def loss(w):
    return w ** 2

def grad(w):
    return 2 * w

for step in range(10):
    current_loss = loss(w)
    current_grad = grad(w)
    print(f"step={step}, w={w:.6f}, loss={current_loss:.6f}, grad={current_grad:.6f}")
    w = w - lr * current_grad

输出:

step=0, w=4.000000, loss=16.000000, grad=8.000000
step=1, w=2.400000, loss=5.760000, grad=4.800000
step=2, w=1.440000, loss=2.073600, grad=2.880000
step=3, w=0.864000, loss=0.746496, grad=1.728000
step=4, w=0.518400, loss=0.268739, grad=1.036800
step=5, w=0.311040, loss=0.096746, grad=0.622080
step=6, w=0.186624, loss=0.034829, grad=0.373248
step=7, w=0.111974, loss=0.012538, grad=0.223949
step=8, w=0.067185, loss=0.004514, grad=0.134369
step=9, w=0.040311, loss=0.001625, grad=0.080622
...

这段代码特别适合初学者,因为它把整个过程压缩成了三件事:

  1. 计算当前损失
  2. 计算损失函数对参数的梯度
  3. 根据梯度下降公式更新参数

而且你能非常清楚地看到:

我们求的是损失对参数的导数,不是别的量。


十一、放回机器学习里,梯度下降到底在更新什么?

现在把视角重新放回真正的模型训练。

训练过程通常可以理解成这样一条线:

输入数据 x
→ 模型根据当前参数做计算
→ 得到预测结果
→ 损失函数衡量预测与真实答案的差距
→ 对损失函数关于参数求导
→ 更新参数

这里面,损失函数的作用非常关键:
它把“模型到底错了多少”变成了一个可以计算、可以优化的数值 。
如果没有这一步,参数更新就没有依据,训练过程也无从谈起 。

而前面也讲过,机器并不是突然“懂了”图片,而是在大量数据中不断调整内部参数,慢慢学会了更好的分类规则 。

所以梯度下降真正更新的,就是模型内部这些参数:

  • 权重
  • 偏置

而不是输入样本本身。

从这个角度看,训练的本质其实很朴素:

模型先犯错,损失函数衡量它错了多少,再通过梯度下降把参数往更合适的方向推。


十二、为什么梯度下降不是“模型突然知道答案了”?

这是一个很常见的误解。

很多人看到“求梯度、更新参数”,容易产生一种感觉:

好像模型一算导数,就突然开窍了。

其实不是。

梯度并不代表模型“理解了问题”,
它只是提供了一个非常局部的信息:

在当前参数位置上,往哪个方向改,更可能让损失下降。

所以梯度下降本质上不是“顿悟”,而是一个反复试错和修正的过程。

这和前面讲机器为什么能识别数字时的逻辑是一致的:
机器不是天生会分类,而是在大量数据中不断调整参数,慢慢把判断规则学出来的 。


十三、学习率为什么也必须一起理解?

更新公式里除了梯度,还有一个非常重要的量:

[
\eta
]

它就是学习率。

很多初学者只盯着“梯度”,却忽略了学习率。
但实际上,梯度决定的是方向,学习率决定的是步子大小。

如果学习率太小

  • 每次改动都很保守
  • 损失虽然可能持续下降
  • 但训练速度会很慢

如果学习率太大

  • 参数一步跨太远
  • 可能直接越过较优位置
  • 甚至来回震荡,训练不稳定

所以一个完整的理解应该是:

  • 梯度告诉你该往哪边走
  • 学习率告诉你这一步走多大

十四、这一讲最容易混淆的几个点

1. 梯度是对输入求的

不是。
在这一步训练里,输入和标签都是已知量,通常看成常量;我们真正关心的是损失函数对参数的导数。

2. 损失函数只是判断对错

不完全是。
损失函数不是简单判断预测是否正确,而是在衡量预测和真实答案之间的差距到底有多大 。

3. 分类对了,损失就一定很小

不一定。
即使最后分类结果一样,不同置信程度对应的损失也可能不同 。

4. 梯度下降是在更新模型结构

不是。
梯度下降通常更新的是模型参数,而不是任务定义、输入数据或模型结构本身。

5. 梯度下降就是随便调参数

不是。
它不是盲目乱试,而是根据损失函数对参数的变化趋势,有方向地更新参数。


十五、总结

现在回到最开始的问题:

梯度下降到底在做什么?

如果把这一讲压缩成一句话,那么最核心的答案就是:

梯度下降是在对损失函数关于模型参数求导。训练时,把输入和标签看成已知常量,把参数看成待学习的变量;然后根据导数给出的变化趋势,沿着让损失减小的方向一步步更新参数。

再说得更直白一点,就是:

  • 数据先进入模型
  • 模型给出预测结果
  • 损失函数衡量预测和真实答案之间差了多少
  • 我们关心“损失对参数的导数”
  • 然后按照让损失变小的方向更新参数
  • 参数不断被修正后,模型的判断能力也就慢慢形成了

所以梯度下降并不神秘。
它做的事情其实非常朴素:

看当前哪里错了,再朝着“错得更少”的方向改一点。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐