人工智能训练的核心秘密:梯度下降与L1/L2正则化

📅 2026/7/5 2:15:16 👁️ 阅读次数 📝 编程学习
人工智能训练的核心秘密:梯度下降与L1/L2正则化

一、机器学习在解决什么问题

假设我们要让计算机学会一个规律:输入一个数字 x,输出它的两倍,即 y = 2x

计算机不知道这个规律,它只能看到一组数据:

输入 x对应的输出 y
12

计算机现在的任务:根据这组数据,猜出背后的规律是什么

计算机决定用一个简单的公式来模拟这个规律:y_pred = w × x

这里w是一个未知数,计算机需要从数据中推算出w应该是几。如果算出来w = 2,那模型就完美复现了规律y = 2x

但计算机一开始完全不知道w该是多少,它随机猜了一个值:w = 10

问题转化为:如何利用数据,把 w 从 10 修正到 2?


二、梯度下降:如何修正一个参数

2.1 误差有多大:定义损失函数

当前模型:y_pred = w × x = 10 × 1 = 10

真实答案:y_true = 2

预测值 10 比真实值 2 大了 8,模型错了。

定义一个函数,用来量化"错得有多严重"。这个函数叫损失函数,我们用均方误差

Loss(w) = (y_pred - y_true)²

y_pred = w × x = w × 1 = w代入:

Loss(w) = (w - 2)²

w = 10时:Loss(10) = (10 - 2)² = 64

这个 64 代表当前模型的错误程度。

2.2 往哪个方向改:梯度的含义

我们想知道:如果把 w 增大一点点,损失会变大还是变小?

分别算两个临近点的损失:

w 的值损失 Loss = (w-2)²
1064
1181

从 10 增加到 11,损失从 64 增加到 81。所以w 增大,损失增大,我们应该减小 w

但这只是粗略看方向,我们需要精确知道"每改变一个单位,损失变化多少"。

这个精确的变化率就是导数(梯度)

展开损失函数:
Loss(w) = (w - 2)² = w² - 4w + 4

对 w 求导(逐项求):

  • 的导数是2w

  • -4w的导数是-4

  • +4的导数是0

所以:梯度 = d(Loss)/dw = 2w - 4

代入当前w = 10梯度 = 2×10 - 4 = 16

梯度 = 16 的意义:w 每增加 1 个单位,损失大约增加 16 个单位。

  • 正数说明增加 w 会让损失更大,所以应该减小 w

  • 数值 16 决定了每次要改多大的步幅

2.3 更新公式:迈出第一步

更新规则:w_new = w_old - 学习率 × 梯度

学习率lr = 0.1,是一个事先设定的控制步长的系数。

代入:w_new = 10 - 0.1 × 16 = 10 - 1.6 = 8.4

第一步更新结束,w 从 10 降到了 8.4。

2.4 不断迭代重复

每一步做同样的事情:

  1. 用当前 w 计算预测值

  2. 用预测值计算损失

  3. 用损失对 w 求导得到梯度

  4. 用梯度更新 w

轮次当前 w预测值 = w×1损失 = (w-2)²梯度 = 2w-4更新后 w = w - 0.1×梯度
初始101064168.4
18.48.440.9612.87.12
27.127.1226.2110.246.10
36.106.1016.788.205.28
45.285.2810.746.564.62
54.624.626.875.244.10
103.073.071.142.142.86
202.162.160.0260.322.13
302.032.030.0010.062.02
..................
收敛2.002.00002.00

2.5 为什么最终停在 2

w = 2时:

  • 预测值:2 × 1 = 2,与真实值完全一致

  • 损失:(2-2)² = 0

  • 梯度:2×2 - 4 = 0

梯度为 0,更新公式变为:w_new = 2 - 0.1×0 = 2

w 不再变化,因为损失已经降到最低,无法再降低了。

2.6 一个重要澄清:梯度下降不是"一直变小"

如果初始 w = -5:

  • 损失:(-5-2)² = 49

  • 梯度:2×(-5) - 4 = -14

梯度是负数 -14,更新:w_new = -5 - 0.1×(-14) = -5 + 1.4 = -3.6

w 变大了(从 -5 增加到 -3.6)。

所以梯度下降的方向是:如果 w 在最佳值左侧,就增大;如果在右侧,就减小。最终所有路径都汇聚到最佳值 2。


三、为什么需要正则化

3.1 测量误差导致的问题

上面假设数据完全没有误差。现实中的数据往往有测量误差。

假设真实规律仍然是y = 2x,但我们采集的数据有一个微小的误差:

输入 x真实值(无误差)采集到的值(有误差)
122.1

误差只有 0.1,很小。

如果不用正则化,模型会怎么做?

损失函数:Loss(w) = (w×1 - 2.1)² = (w - 2.1)²

这个损失在w = 2.1时等于 0,因为(2.1-2.1)² = 0

模型会学到w = 2.1,把训练数据上的损失完美降到 0。

但现在来了一个测试数据:x = 2,正确答案应该是2×2 = 4

  • w = 2.1预测:2.1×2 = 4.2,偏差 0.2

  • 如果用w = 2.0预测:2.0×2 = 4.0,偏差 0

问题:模型为了拟合训练数据里那 0.1 的测量误差,把 w 从 2 推到了 2.1,导致在新数据上表现变差。

这就是过拟合:模型记住了训练数据中的噪声,反而学坏了。

3.2 正则化的核心思想

正则化在损失函数中增加一项惩罚,防止参数变得太大。

新的损失函数 = 原来的损失 + 惩罚项

惩罚项不依赖于数据,只依赖于参数本身。参数越大,惩罚越大。

这样模型在选择参数时就要权衡:

  • 拟合数据(让原损失小)

  • 控制参数大小(让惩罚项小)


四、L2 正则化:权重衰减

4.1 L2 正则化的形式

L2 正则化在损失函数中增加λ × w²

Loss_L2(w) = (w - 2.1)² + λ × w²

这里的 λ 叫正则化系数,控制惩罚的力度。我们设λ = 0.5

Loss_L2(w) = (w - 2.1)² + 0.5 × w²

这个式子要求模型同时做两件事:

  1. (w - 2.1)²尽量小(拟合数据)

  2. 0.5 × w²尽量小(不让 w 太大)

4.2 L2 正则化的梯度

对两项分别求导:

  • (w - 2.1)²求导:2 × (w - 2.1) = 2w - 4.2

  • 0.5 × w²求导:0.5 × 2 × w = w

总梯度:梯度_L2(w) = (2w - 4.2) + w = 3w - 4.2

4.3 一个常见的错误直觉

很多人会想:"加了正则化,只是让 w 稍微小一点,最后应该还是停在 2.1 附近吧?"

我们来验证:假设 w = 2.1:

  • 误差部分梯度:2×(2.1-2.1) = 0(数据已经完美拟合,误差部分不想再改 w)

  • 惩罚部分梯度:2×0.5×2.1 = 2.1(惩罚部分依然在说:w 太大,必须减小)

总梯度 = 0 + 2.1 =2.1(正数)

因为总梯度为正,更新公式w_new = w - lr×正数会让 w减小

结论:w = 2.1 站不住脚,会被惩罚项强行拉下来。

4.4 真正的平衡点在哪里

模型最终停下来的条件是:总梯度 = 0(两股力量完全抵消)。

3w - 4.2 = 0

3w = 4.2w = 4.2/3 = 1.4

验证:当 w = 1.4 时:

  • 误差部分梯度:2×(1.4-2.1) = 2×(-0.7) = -1.4
    (负数,表示"误差想把 w 拉大",因为 1.4 比 2.1 小)

  • 惩罚部分梯度:2×0.5×1.4 = 1.4
    (正数,表示"惩罚想把 w 拉小",因为 1.4 比 0 大)

两者刚好抵消:-1.4 + 1.4 = 0。平衡。

4.5 对比有无正则化的收敛结果

方法损失函数梯度收敛点
无正则化(w-2.1)²2w-4.22.1
L2 正则化 (λ=0.5)(w-2.1)² + 0.5w²3w-4.21.4

L2 让 w 收敛到 1.4,而不是 2.1

  • 在训练数据上的损失:(1.4-2.1)² = 0.49,没有降到 0

  • 在新数据x=2上的预测:1.4×2 = 2.8,离 4 更远了(比 2.1 更差?)

等等,这里有个重要细节:如果真实规律是 y=2x,那么 L2 正则化让 w=1.4 实际上比 w=2.1 更差,因为真正的 w 是 2。

那 L2 正则化到底好在哪里?

关键在于:我们刚才的推导假设真实规律是 y=2x,但机器并不知道这一点。如果训练数据只有一组,机器无法判断到底哪个 w 是正确的。L2 正则化选择了一个更小的 w,在数据不足的情况下,小参数通常泛化能力更强。

更重要的是,当有多个参数时,L2 正则化的作用会更清晰。


五、多参数场景:现实世界的真实情况

5.1 为什么必须引入多参数

真实问题不可能只有一个输入特征。预测房价需要:面积、卧室数、房龄、地段……

模型需要多个参数:y_pred = w₁×x₁ + w₂×x₂ + w₃×x₃ + ...

每个特征有自己的权重,机器需要同时找到所有 w 的最佳值

5.2 两个参数的完整示例

真实规律:y = 2×x₁ + 3×x₂

机器看到的数据:

x₁x₂y_true
128

验证:2×1 + 3×2 = 2+6 = 8,数据符合规律。

机器使用模型:y_pred = w₁×x₁ + w₂×x₂

随机初始化:w₁ = 5w₂ = 5

损失函数
Loss(w₁, w₂) = (w₁×1 + w₂×2 - 8)² = (w₁ + 2w₂ - 8)²

对 w₁ 的梯度(偏导数)
把 w₂ 当作常数,只对 w₁ 求导。
u = w₁ + 2w₂ - 8Loss = u²
d(Loss)/dw₁ = 2×u × d(u)/dw₁
d(u)/dw₁ = 1(w₁ 的系数是 1)

所以:梯度_w₁ = 2×(w₁ + 2w₂ - 8)×1

代入w₁=5, w₂=5梯度_w₁ = 2×(5+10-8)×1 = 14

对 w₂ 的梯度(偏导数)
把 w₁ 当作常数,只对 w₂ 求导。
d(u)/dw₂ = 2(w₂ 的系数是 2)

所以:梯度_w₂ = 2×(w₁ + 2w₂ - 8)×2

代入w₁=5, w₂=5梯度_w₂ = 2×7×2 = 28

同时更新两个参数

  • w₁_new = 5 - 0.1×14 = 3.6

  • w₂_new = 5 - 0.1×28 = 2.2

验证:3.6×1 + 2.2×2 = 3.6 + 4.4 = 8,完美拟合。

5.3 多参数的关键观察

每个参数的梯度为什么不同?

梯度的通用公式:对第 k 个参数梯度_wk = 2×(y_pred - y_true)×x_k

  • w₁ 的梯度:2×7×1 = 14(因为 x₁ = 1)

  • w₂ 的梯度:2×7×2 = 28(因为 x₂ = 2)

同一个误差 7,乘以不同的输入特征,得到不同的梯度。

如果某个输入特征很大(比如面积是 100 平米),那么对应参数的微小变化会导致预测值剧烈变化,梯度就大,更新步幅也大。

每个参数独立更新,互不干扰。

5.4 多参数带来的新问题:解不唯一

根据一组数据(x₁=1, x₂=2, y=8),有无数种参数组合都能让预测值等于 8:

  • (w₁=2, w₂=3)2×1+3×2=8(真实规律)

  • (w₁=4, w₂=2)4×1+2×2=8

  • (w₁=3.6, w₂=2.2)3.6×1+2.2×2=8

  • (w₁=100, w₂=-46)100×1-46×2=8

参数越多,解越不唯一。模型可能学到任何一种组合。

如果数据有噪声,模型为了拟合噪声,会把参数调到极端值(如 100 和 -46 互相抵消),这样在新数据上必然崩溃。

这就是多参数场景下过拟合更严重的原因。

5.5 L2 正则化在多参数下的作用

损失函数:
Loss_L2(w₁,w₂) = (w₁+2w₂-8)² + λ×(w₁² + w₂²)

惩罚项是所有参数平方的和。任何参数过大都会增加惩罚。

设 λ = 0.5,初始 w₁=5, w₂=5:

对 w₁ 的梯度

  • 误差部分:2×(5+10-8)×1 = 14

  • 惩罚部分:2×0.5×w₁ = 1×5 = 5

  • 总梯度:14+5 = 19

  • 更新:5 - 0.1×19 = 3.1

对 w₂ 的梯度

  • 误差部分:2×7×2 = 28

  • 惩罚部分:2×0.5×w₂ = 1×5 = 5

  • 总梯度:28+5 = 33

  • 更新:5 - 0.1×33 = 1.7

L2 对每个参数独立施加惩罚,惩罚力度与参数大小成正比。

L2 正则化的收敛点推导(多参数)

令两个总梯度都为 0:

2×(w₁+2w₂-8)×1 + 2×0.5×w₁ = 0... ①
2×(w₁+2w₂-8)×2 + 2×0.5×w₂ = 0... ②

化简 ①:(2w₁+4w₂-16) + w₁ = 03w₁ + 4w₂ = 16

化简 ②:(4w₁+8w₂-32) + w₂ = 04w₁ + 9w₂ = 32

解方程组:
由①得:w₁ = (16 - 4w₂)/3
代入②:4×(16-4w₂)/3 + 9w₂ = 32
(64 - 16w₂)/3 + 9w₂ = 32
64 - 16w₂ + 27w₂ = 96
11w₂ = 32w₂ ≈ 2.91
w₁ = (16 - 4×2.91)/3 = (16 - 11.64)/3 ≈ 1.45

收敛点(w₁≈1.45, w₂≈2.91)

不加正则时,针对这组数据有无数个解;但加了 L2 正则后,解唯一,且所有参数都被拉向 0。

5.6 扩展到任意 N 个参数

对于 N 个参数,模型为:
y_pred = w₁×x₁ + w₂×x₂ + ... + w_N×x_N

损失函数Loss = (y_pred - y_true)²

第 k 个参数的梯度(通用公式):
梯度_wk = 2×(y_pred - y_true)×x_k

L2 正则化的梯度
梯度_wk = 2×(y_pred - y_true)×x_k + 2×λ×w_k

更新规则(对每个参数同时执行):
w_k_new = w_k_old - lr × 梯度_wk


六、L1 正则化:特征选择

6.1 L1 正则化的形式

L1 正则化在损失函数中增加λ×|w|

Loss_L1(w) = (w - 2.1)² + λ×|w|

这里的|w|是 w 的绝对值。设 λ = 0.5。

Loss_L1(w) = (w - 2.1)² + 0.5×|w|

6.2 L1 正则化的梯度

(w-2.1)²求导:2w - 4.2

0.5×|w|求导:

  • 当 w > 0 时,|w| = w,导数为0.5

  • 当 w < 0 时,|w| = -w,导数为-0.5

  • 当 w = 0 时,不可导(工程上通常用次梯度,取 [-0.5, 0.5] 之间的值)

关键区别:L1 的惩罚梯度是一个常数(0.5 或 -0.5),不随 w 的大小变化。

6.3 计算第一次更新(w=10 > 0)

  • 误差部分梯度:2×10 - 4.2 = 15.8

  • 惩罚部分梯度:+0.5

  • 总梯度:15.8 + 0.5 = 16.3

  • 更新:10 - 0.1×16.3 = 8.37

6.4 L1 vs L2 的收敛对比

轮次无正则化L1 正则化 (λ=0.5)L2 正则化 (λ=0.5)
初始10.0010.0010.00
18.428.377.42
27.127.035.59
36.106.004.30
54.664.552.71
103.183.081.50
202.362.281.41
302.142.101.40
收敛2.102.001.40

6.5 L1 为什么能让 w 变成 0

观察 w 接近 0 时两种正则化的表现。

假设当前 w = 0.1,误差部分梯度约为2×0.1 - 4.2 ≈ -4.0(想把 w 拉向 2.1):

  • L2:惩罚梯度 =2×0.5×0.1 = 0.1(很小)
    总梯度 = -4.0 + 0.1 = -3.9(负数)
    更新:w_new = 0.1 - 0.1×(-3.9) = 0.1 + 0.39 = 0.49
    w 增大了,远离 0

  • L1:惩罚梯度 =+0.5(常数)
    总梯度 = -4.0 + 0.5 = -3.5(仍然为负)
    更新:w_new = 0.1 - 0.1×(-3.5) = 0.1 + 0.35 = 0.45
    w 也增大了,但原因不同

再往 0 靠近,假设 w = 0.01:

  • L2:惩罚梯度 =2×0.5×0.01 = 0.01,几乎为零
    总梯度 ≈ -4.0,w 被迅速拉大,L2 在 0 附近几乎没有抵抗力

  • L1:惩罚梯度 =+0.5,依然是常数
    总梯度 = -3.5,w 仍然被拉大

等等,那 L1 到底是怎么让 w 归零的?

上面的分析有个遗漏:当 w变号时,L1 的惩罚梯度会改变方向。

当 w 从正值被拉向 0,一旦越过 0 变成负值:

  • 惩罚梯度从+0.5变成-0.5

  • 如果 w 是负的,-0.5表示"惩罚想把 w 拉大(向 0 靠近)"

此时总梯度 = 误差梯度(可能是负的,想把 w 拉向正数 2.1)+ 惩罚梯度(是正的,想把 w 拉向 0)

如果误差梯度较小(比如 -0.3),而惩罚梯度是 +0.5,总梯度 = +0.2(正数),更新会让 w减小(从负值变得更负,远离 0)。

所以 L1 的机制是:当 w 在 0 附近时,L1 的恒定惩罚形成了一个"死区",任何越过 0 的尝试都会被反向弹回,最终卡在 0。

L2 没有这个特性,因为 L2 在 0 附近的惩罚梯度趋近于 0,无法形成有效的死区。

6.6 L1 在多参数下的特征选择

当有多个参数时,L1 正则化会把不重要的参数直接推到 0:

  • 对真正重要的参数(误差梯度大):能抵抗住 L1 的恒定惩罚,保持非零

  • 对不重要的参数(误差梯度小):L1 的恒定惩罚占主导,不断把 w 推向 0,最终归零

结果:模型变成稀疏的,只依赖少数几个真正重要的特征。


七、代码实现

7.1 无正则化梯度下降(PyTorch)

import torch w = torch.tensor([10.0], requires_grad=True) x = torch.tensor([1.0]) y_true = torch.tensor([2.1]) lr = 0.1 for i in range(30): y_pred = w * x loss = (y_pred - y_true) ** 2 loss.backward() with torch.no_grad(): w -= lr * w.grad w.grad.zero_() print(f"轮次{i+1}: w = {w.item():.4f}")

7.2 L2 正则化(内置 weight_decay)

import torch import torch.optim as optim w = torch.tensor([10.0], requires_grad=True) x = torch.tensor([1.0]) y_true = torch.tensor([2.1]) lr = 0.1 optimizer = optim.SGD([w], lr=lr, weight_decay=0.5) for i in range(30): optimizer.zero_grad() y_pred = w * x loss = (y_pred - y_true) ** 2 loss.backward() optimizer.step()

7.3 L1 正则化(手动添加)

import torch w = torch.tensor([10.0], requires_grad=True) x = torch.tensor([1.0]) y_true = torch.tensor([2.1]) lr = 0.1 lambda_l1 = 0.5 for i in range(30): y_pred = w * x loss = (y_pred - y_true) ** 2 + lambda_l1 * torch.abs(w) loss.backward() with torch.no_grad(): w -= lr * w.grad w.grad.zero_()

7.4 多参数完整示例(PyTorch)

import torch w1 = torch.tensor([5.0], requires_grad=True) w2 = torch.tensor([5.0], requires_grad=True) x1 = torch.tensor([1.0]) x2 = torch.tensor([2.0]) y_true = torch.tensor([8.0]) lr = 0.1 lambda_l2 = 0.5 for i in range(20): y_pred = w1 * x1 + w2 * x2 loss = (y_pred - y_true) ** 2 + lambda_l2 * (w1**2 + w2**2) loss.backward() with torch.no_grad(): w1 -= lr * w1.grad w2 -= lr * w2.grad w1.grad.zero_() w2.grad.zero_() print(f"轮次{i+1}: w1={w1.item():.4f}, w2={w2.item():.4f}")

八、总结

方法解决的问题梯度公式对参数的作用
梯度下降如何找到让损失最小的参数梯度 = 2×误差×x_k让每个参数朝损失减小的方向移动
L2 正则化防止参数过大导致过拟合梯度 = 2×误差×x_k + 2×λ×w_k所有参数都变小,但不归零,解唯一
L1 正则化识别并删除不重要的特征梯度 = 2×误差×x_k + λ×sign(w_k)不重要的参数直接变成 0

梯度下降是引擎,驱动所有参数向最优值移动。

L2 是刹车,让所有参数都别跑太快,整体收缩。

L1 是筛选器,把不重要的参数直接剔除,让模型变稀疏。

梯度下降不是机器学习的专属工具。它是整个AI领域共享的“底层语法”——无论是最早期的感知机,还是最新的大语言模型,都在执行同一套更新规则。

L2正则化让所有参数变小但不归零。L1正则化把不重要的参数直接清零。两者配合梯度下降,在“拟合数据”和“保持参数合理”之间寻找平衡——这就是AI模型从数据中“学会”规律,同时避免“死记硬背”的全部逻辑。