第 6 章 · 线性模型与梯度下降

从本章开始进入「真模型」:线性回归、逻辑分类、以及梯度下降——整个深度学习的发动机。这一章的每个概念(参数、损失、梯度、学习率)都会在神经网络(第 7 章)里原样复用,只是换了个更大的假设空间。线性代数的最小配置:矩阵乘向量、导数链式法则,遇到不懂随时回离散/高数补。

6.1 线性回归:第一个「学习」出来的模型

问题:给定 n 条数据(面积 xᵢ,房价 yᵢ),找一条直线 y = w·x + b 尽量贴合。参数 w(斜率)与 b(截距)就是「要学习的东西」——机器学习的「学习」= 调这些参数。

损失函数量化「贴合程度」,最常用均方误差(MSE):

L(w,b)=‘1‘‘n‘∑‘i=1‘‘n‘(wxi+b−yi)2L(w, b) = \frac`{1}``{n}`\sum_`{i=1}`^`{n}`(w x_i + b - y_i)^2

(平方有两个好处:正负误差不抵消;处处可导,梯度好算。)「学习」= 找 (w, b) 使 L 最小。线性回归有解析解(正规方程 w = (XᵀX)⁻¹Xᵀy,线性代数的变现),但更普适的路径是数值优化——因为神经网络没有解析解。

6.2 梯度下降:沿着下坡走

梯度下降(gradient descent)的思想朴素到像走路:站在山上(损失面的某点),不知道全貌,但能感觉脚下哪边朝下(梯度方向 = 上坡最陡,负梯度 = 下坡最陡),往那迈一步,重复:

重复:
  w ← w − η · ∂L/∂w
  b ← b − η · ∂L/∂b

η(eta)学习率是唯一的超参数,它的三态人生:太小慢到天荒地老,太大步子跨过谷底来回震荡甚至发散,刚好稳定下降。调学习率是深度学习调参的第一课(第 7 章)。

线性回归的 MSE 损失面是碗形(凸函数),梯度下降必然到谷底;神经网络的损失面是崇山峻岭(非凸),梯度下降只能到「某个局部谷」——但实践发现,高维空间里的局部谷大多够好(这是个安慰性的理论未解之谜)。

随机梯度下降(SGD):真实数据百万条,每步全算 MSE 太贵;SGD 每次只抽一小批(mini-batch,32/256 条)算梯度就走。批小 = 噪声大但走得勤,噪声反而帮着跳出小坑(实践玄学但真实有效)。深度学习的「训练」一词,实际指的就是 mini-batch SGD 的千万次循环。

6.3 逻辑回归:分类不是回归的亲戚

分类(是/不是垃圾邮件)不能用直线拟合(输出 0/1),给线性函数套一个挤压函数 sigmoid:

‘^y‘=σ(w⋅x+b),σ(z)=‘1‘‘1+e−z‘\hat`{y}` = \sigma(w \cdot x + b), \quad \sigma(z) = \frac`{1}``{1 + e^{-z}}`

σ 把任意实数压进 (0, 1),天然解读为「概率」。损失换交叉熵(cross-entropy):预测对时候罚 0,预测错时罚 ∞ 方向暴涨(比 MSE 对分类的梯度健康得多,不会「一开始错得离谱却学得慢」):

L=−[ylog⁡‘^y‘+(1−y)log⁡(1−‘^y‘)]L = -\big[y \log \hat`{y}` + (1-y)\log(1-\hat`{y}`)\big]

「线性模型 + sigmoid + 交叉熵」= 逻辑回归。名字带回归但干分类的活;它是神经网络的一个神经元(第 7 章的感知机即此),也是大模型输出层的一部分(softmax 是 sigmoid 的多类版,第 10 章)。

6.4 泛化的数学:正则化

第 5 章的过拟合在线性模型里已有精确解法。过拟合的线性表现:某些 w 特别大(模型靠极端系数硬凑训练集)。正则化 = 在损失里加「参数大小」的罚款:

L‘ridge‘=MSE+λ∑w2(‘L2正则,岭回归‘)L_`{ridge}` = MSE + \lambda \sum w^2 \quad (\text`{L2 正则, 岭回归}`)

λ 是「简洁性 vs 拟合性」的旋钮:λ 大则 w 被压小、模型变钝但泛化稳;L1 版本(惩罚 |w|)还会把没用的 w 压到恰好 0(自动特征选择)。奥卡姆剃刀(第 5 章)的数学形态:在拟合同样好的假设里,选参数小的。深度学习的正则化是同思想的变体全家桶(weight decay、dropout、数据增强),第 7 章遇到不再展开。

6.5 实战:手写梯度下降

用纯 Python(不用任何库)对一组点拟合直线,把全章概念焊死:

import random

data = [(1, 2.1), (2, 4.3), (3, 6.2), (4, 8.1), (5, 10.2)]   # 近似 y = 2x
w, b, lr = 0.0, 0.0, 0.01

for epoch in range(2000):
    dw = db = 0.0
    for x, y in data:                       # 每条数据累积梯度
        err = w * x + b - y
        dw += 2 * err * x                   # ∂L/∂w
        db += 2 * err                       # ∂L/∂b
    w -= lr * dw / len(data)                # 一步下降
    b -= lr * db / len(data)
    if epoch % 500 == 0:
        print(f"epoch {epoch}: w={w:.3f} b={b:.3f}")

# 输出收敛到 w≈2.0, b≈0.1 附近 → 模型「学习」到了数据的规律

跑完盯着 w、b 一步步爬向真值,「梯度下降」从名词变成体感。这就是 PyTorch/TF 在后台做的全部事情(第 7 章换成亿级参数 + 自动求导 + GPU 并行)。

常见认知误区

  • 「损失降到 0 才好」。训练损失 0 = 过拟合警报(第 5 章);盯验证集,让训练损失「适当残留」。
  • 「学习率越大学得越快」。过大直接发散(loss 飙到 nan),现象是「前几步 loss 不降反升」;调参从 1e-3 起步,再上下探。
  • 「梯度下降找全局最优」。它只找局部;凸问题(线性回归)必到全局,非凸问题(神经网络)听天由命但实践够用。
  • 「特征不重要了,模型大就行」。垃圾特征(第 5 章的数据课)喂大模型照样垃圾;线性模型时代学特征工程,大模型时代学数据清洗,本质一样。

练习

  1. 动手:跑 6.5 的代码;分别把 lr 调成 0.0001、0.1、0.5 跑三次,记录三种收敛命运(慢、稳、炸),画出 loss 曲线对比。
  2. 动手:把数据换成 y = 3x + 1,验证模型能否学到;再给数据加随机噪声(random.gauss),观察拟合出的 w、b 与真值的偏差,理解「噪声决定拟合下限」。
  3. 手算:损失 L = (w−3)²,手推 ∂L/∂w = 2(w−3);用学习率 0.1 从 w = 0 迭代 5 步,列出每步的 w 值(0, 0.6, 1.08, 1.464, …),验证「步长随梯度变小而变小」。
  4. 思考:第 4 章符号 AI 的知识是人写的 if-then,本章的「知识」是拟合出的 w 和 b。对比两种「知识存储」:哪个可解释、哪个可迁移、哪个易更新?你的答案是否暗示了神经+符号结合的正确分工?