深度学习入门站 · 理解深度学习
首页 › 第 2 章

监督学习

带着标准答案学习:从最简单的线性回归出发,看懂模型、损失、训练和泛化。
图 2-1:监督学习流程与回归/分类
图 2-1:监督学习流程与回归/分类

这一章讲的是机器学习里最基础、也最重要的一种学习方式——监督学习(Supervised Learning)。你可以把它理解成"带着标准答案学习":我们给模型一堆"题目+答案",让它自己摸索出规律,以后再遇到新题目也能答对。学完这一章,你会搞懂模型的"输入-输出-参数"到底是什么意思,还会亲眼看到最最简单的模型——线性回归——是怎么被训练出来的。

什么是监督学习?

想象你是一个二手车贩子,想根据一辆车的车龄和行驶里程来估价。你手里有一堆历史成交记录:每辆车是什么情况、最后卖了多少钱。这就是一份"题目+答案"的题库。你希望从这些记录里总结出一条规律,以后来一辆新车,你报个价八九不离十。

这个过程就是监督学习。专业一点说:我们有一个输入 $x$(车龄、里程),一个输出 $y$(价格),想要找到一个函数 $f$,把输入变成输出:

$$y = f[x]$$

当你拿输入 $x$ 去算输出 $y$ 的时候,这个动作叫推理(inference)——就是"用模型做预测"。

🏷️
生活类比
监督学习就像学生做练习册:题目是 $x$,标准答案是 $y$。学生(模型)反复做题、对答案、改错,最后学会了解题方法。而"没有答案的题"(比如高考真题)就是测试数据——用来检验学生是不是真的学会了,而不是把练习册背下来了。

模型与参数:一个公式家族

我们选的公式 $y = f[x]$ 并不是唯一的。公式里通常还藏着一些旋钮,叫参数,用 $\phi$ 表示。参数怎么拧,公式的行为就怎么变:

$$y = f[x, \phi]$$

举个例子,直线的公式是 $y = \phi_0 + \phi_1 x$。这里 $\phi_0$ 是截距(直线和 $y$ 轴的交点),$\phi_1$ 是斜率(直线有多陡)。只要你愿意,可以拧出无数条不同的直线——所以这个公式其实代表了一个"直线家族",而参数 $\phi$ 决定了我们选家族里的哪一位成员。

💡
**核心思想**:模型 = 一个公式家族(所有可能的输入输出关系);参数 = 家族里具体的某一位成员。**训练(学习)**就是找到能最好地解释数据的那个参数。

最简单的模型:线性回归

假设我们只有 12 辆车的成交记录,横轴是车龄,纵轴是价格,散点图大概是从左上往右下掉的一团点。最朴素的猜想是:价格和车龄是直线关系,也就是用一条直线来拟合这些点:

$$y = \phi_0 + \phi_1 x$$

问题来了:怎么判断哪条直线"最好"?光靠肉眼不够,我们需要一个打分器。

损失函数:模型的"考试分数"

对每个数据点,模型都会预测一个价格 $f[x_i, \phi]$,而真实成交价是 $y_i$。两者差得越多,说明这条线越不靠谱。把每个点的差距平方后加起来,就得到损失(Loss)——一个代表"模型有多差"的数字:

$$L(\phi) = \sum_{i=1}^{I} (f[x_i, \phi] - y_i)^2 = \sum_{i=1}^{I} (\phi_0 + \phi_1 x_i - y_i)^2$$

因为这里用的是"差的平方和",所以叫最小二乘损失。为什么要平方?因为差值是正是负都算"错",平方后方向就无所谓了,而且大误差会被放大惩罚。损失越低,说明线拟合得越好。

于是"找最好的直线"变成了一个数学问题:

$$\hat{\phi} = \arg\min_{\phi} L(\phi)$$

也就是:把参数拧到让损失最小为止。

🎯
生活类比
损失函数就像投篮的"偏航记录":每个数据点是一次投篮,预测值离篮筐(真实值)多远,就记一个误差。把所有误差的平方加起来,就是一个总分数。我们想要的直线,就是那个"总偏差最小"的投篮姿势。

训练:一路"下山"找最低点

损失 $L$ 可以看成以参数 $\phi_0$、$\phi_1$ 为横纵坐标的"地形图":每个参数组合对应一个损失值,把损失画成高度,就得到一个碗状曲面。我们的目标,就是走到这个碗的最底端。

怎么走?从随机位置开始,朝最陡的下坡方向迈一步,然后重新看方向再迈一步,一直走到走不动为止(坡度变平了)。这个过程叫梯度下降(Gradient Descent)——"梯度"就是坡最陡的方向。

import numpy as np

# 训练数据:车龄 x,价格 y(虚构示例)
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([9.5, 8.3, 7.1, 6.0, 4.8, 3.9])

phi0, phi1 = 0.0, 0.0     # 参数初始值(随便挑一个起点)
lr = 0.01                 # 学习率:每步迈多大
for step in range(2000):
    pred = phi0 + phi1 * x
    # 损失函数的梯度(对 phi0 和 phi1 求偏导)
    grad0 = np.mean(2 * (pred - y))
    grad1 = np.mean(2 * (pred - y) * x)
    phi0 -= lr * grad0    # 朝反方向(下坡)更新参数
    phi1 -= lr * grad1

print(f"截距 phi0 = {phi0:.2f}, 斜率 phi1 = {phi1:.2f}")

跑完这段代码,你就亲眼看到了一条直线被"训练"出来:参数从 $0$ 开始,一步步被梯度下降推到最优点。这就是后面所有深度学习训练的最基本原理。

测试与泛化:真本事还是死记硬背?

模型在训练数据上表现好,不代表真本事。万一它把练习册答案都背下来了,换道新题就露馅。所以训练完,我们要在没见过的测试数据上再考一次,看看它的泛化能力。

这里有两个常见的"翻车"姿势:

  • 欠拟合(Underfitting):模型太简单,直线根本描述不了真实规律——就像学生只学了加减法就去考微积分。
  • 过拟合(Overfitting):模型太能"记",把训练数据里的偶然噪声也当成了规律——就像学生把练习册页码都背下来,换个排版就不会了。
🧠
监督学习的完整流程:定义模型 → 定义损失 → 训练(梯度下降找最小损失)→ 测试(检查泛化)。这个套路贯穿整本书,后面所有花里胡哨的模型,本质上都是在这条主线上换零件。

🎯 小测验

1. 监督学习中,模型的"学习"本质上是学习什么?
2. 为什么损失函数要用"差的平方"而不是直接用"差"?
3. 模型在训练数据上表现极好,但在测试数据上一塌糊涂,这叫什么?