chapter 02 / classical-ml · 预计学习时间 120-150 分钟

经典机器学习算法
分类的四种世界观

AUDIO // 本章语音导读
本章目录
  1. 从回归到分类:一个看似微小的改动
  2. 逻辑回归:Sigmoid 与概率视角
  3. 交叉熵损失:完整推导
  4. Softmax:推广到多分类
  5. 决策树:用问题切分世界
  6. 交互实验室:决策边界对决
  7. 集成学习:随机森林与梯度提升
  8. SVM:最大间隔与核技巧
  9. 代码实战:四种算法同台竞技
  10. 章节测验

从回归到分类:一个看似微小的改动

第 1 章预测的是连续值(房价)。现在改成预测类别:邮件是不是垃圾?肿瘤是良性还是恶性?标签 $y \in \{0, 1\}$。

能不能直接用线性回归,输出 $>0.5$ 算类别 1?理论上可以,实际很糟糕:① 输出值域是 $(-\infty, +\infty)$,没有概率解释,「预测值 3.7」是什么意思?② MSE 对远离边界的「过于正确」的点也施加损失,一个极端但分类正确的样本会把决策边界拉歪。

我们需要两个新零件:把输出压缩成概率的函数,和与概率匹配的损失函数。这两个零件——sigmoid/softmax 和交叉熵——会一路用到 GPT:LLM 的预训练损失就是 softmax + 交叉熵,只是类别从 2 个变成约 10 万个(词表里每个 token 是一类)。这一章的推导是第 7 章的直接地基。

逻辑回归:Sigmoid 与概率视角

保留线性骨架 $z = \mathbf{w}^\top\mathbf{x} + b$(这个 $z$ 有个会用一辈子的名字:logit),再套一个挤压函数:

$$\sigma(z) = \frac{1}{1 + e^{-z}}, \qquad \hat{p} = \sigma(\mathbf{w}^\top\mathbf{x} + b) = P(y{=}1 \mid \mathbf{x})$$

sigmoid 把任意实数单调地压进 $(0,1)$:$z=0$ 时输出 0.5(最不确定),$z$ 越大越接近 1。它的导数有个优美的形式(推导:对 $\sigma(z)=(1+e^{-z})^{-1}$ 用链式法则后整理):

$$\sigma'(z) = \sigma(z)\,(1 - \sigma(z))$$
为什么是 sigmoid 而不是随便找个 S 形函数?因为它是从「对数几率」反推出来的:假设几率的对数是线性的,$\ln\frac{p}{1-p} = \mathbf{w}^\top\mathbf{x} + b$,解出 $p$ 恰好就是 sigmoid。所以逻辑回归的真名是「对数几率回归」——它假设的是线性的 logit,决策边界($p=0.5$ 即 $z=0$ 处)因此是一条直线/超平面。记住这一点,待会去实验室看它在月牙数据上的挣扎。

交叉熵损失:完整推导

损失函数不拍脑袋,走第 1 章学过的最大似然路线。单个样本 $y \in \{0,1\}$ 服从伯努利分布,两种情况可以合写成一个式子:

$$P(y \mid \mathbf{x}) = \hat{p}^{\,y}\,(1-\hat{p})^{\,1-y}$$

全数据集的似然是各样本连乘。取对数(连乘变求和,且不改变最优点),再取负号变成「越小越好」的损失,除以 $n$ 取平均:

$$L = -\frac{1}{n}\sum_{i=1}^n \Big[ y^{(i)} \ln \hat{p}^{(i)} + (1 - y^{(i)}) \ln (1 - \hat{p}^{(i)}) \Big]$$

这就是二元交叉熵(Binary Cross-Entropy)。直觉检查:若真实 $y=1$,损失是 $-\ln\hat{p}$——预测 $\hat{p}\to 1$ 损失趋于 0,$\hat{p}\to 0$ 损失爆炸到无穷。对自信的错误施以无界惩罚,这正是分类任务想要的性格。

现在求梯度。对 $z$ 用链式法则:$\frac{\partial L_i}{\partial z} = \frac{\partial L_i}{\partial \hat{p}}\cdot\frac{\partial \hat{p}}{\partial z}$。代入 $\sigma' = \sigma(1-\sigma)$,一串看似复杂的项神奇地相消(强烈建议手推一次),剩下:

$$\frac{\partial L_i}{\partial z} = \hat{p}^{(i)} - y^{(i)} \qquad\Longrightarrow\qquad \nabla_\mathbf{w} L = \frac{1}{n}\sum_i \big(\hat{p}^{(i)} - y^{(i)}\big)\,\mathbf{x}^{(i)}$$
又是「误差 × 输入」!和第 1 章线性回归的梯度形状一模一样——这不是巧合。MSE+恒等输出、交叉熵+sigmoid、多分类交叉熵+softmax,这三对组合的梯度全是 $(\hat{y}-y)\cdot x$。背后的统一理论叫「广义线性模型 + 规范链接函数」:损失和输出函数配对正确时,梯度永远干净得像没经过任何非线性。这也是深度学习框架里 sigmoid/softmax 总和交叉熵融合成一个算子的原因(数值稳定 + 梯度简洁)。
如果用 MSE 配 sigmoid 做分类,梯度会出什么问题?
$\frac{\partial}{\partial z}\frac{1}{2}(\hat{p}-y)^2 = (\hat{p}-y)\cdot \sigma'(z) = (\hat{p}-y)\cdot\hat{p}(1-\hat{p})$。多出来的 $\hat{p}(1-\hat{p})$ 因子在 $\hat{p}$ 接近 0 或 1 时趋于零——也就是说模型错得越自信(如 $y=1$ 但 $\hat p \approx 0$),梯度反而越接近零,几乎学不动。交叉熵恰好消掉了这个因子,错得越离谱梯度越大。这是「损失函数要与输出层匹配」最生动的反例,也是早期神经网络训练慢的原因之一。
VIDEO 01
Logistic Regression(逻辑回归,清楚明白版)
StatQuest with Josh Starmer 8:47
观看指南
  • 01:20 为什么直接用直线拟合 0/1 标签会出问题——对应本章 §1。
  • 03:30 S 形曲线与概率解释;注意他强调「拟合的是对数几率」。
  • 06:00 与线性回归的异同总结——验证你对「换损失不换骨架」的理解。

Softmax:推广到多分类

$K$ 类时,让模型输出 $K$ 个 logit $z_1,\dots,z_K$,用 softmax 归一化成概率分布:

$$\hat{p}_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}, \qquad L = -\ln \hat{p}_{y}\ \text{(只罚正确类别的概率)}$$

几个工程上必须知道的细节:

决策树:用问题切分世界

换一种完全不同的世界观:不学权重,学一连串问题。「面积 > 90㎡?」→ 是 →「房龄 < 10 年?」→ …… 每个内部节点是一次特征切分,每个叶子是一个预测。它天生处理非线性、不在乎特征量纲、人类可读。

怎么选「最好的问题」?

贪心地选让子节点最纯的切分。两种纯度度量:

$$\text{熵:} H(S) = -\sum_k p_k \log_2 p_k \qquad\qquad \text{基尼:} G(S) = 1 - \sum_k p_k^2$$

都在「各类均匀混合」时最大、「只剩一类」时为 0。信息增益 = 父节点熵 − 子节点熵的加权平均;CART 算法用基尼(无对数,算得快),效果与熵几乎无差。对切分点 $t$ 的搜索就是:对每个特征的每个候选阈值,算一遍加权纯度,取最优——你将在实验室里亲眼看到这种「轴对齐切分」画出的矩形拼图边界。

单棵树的致命弱点是高方差(第 1 章偏差-方差语言):不加限制地长,它能把训练集切到每个叶子一个样本——完美记住所有噪声。去实验室把树深调到 12 看看边界长什么样:support 为 1 的细碎矩形,就是过拟合的形状。控制手段:限制深度/叶子最小样本数(预剪枝)、代价复杂度剪枝(后剪枝)——或者,干脆换思路:种一片森林。
VIDEO 02
Decision and Classification Trees(决策树)
StatQuest with Josh Starmer 18:08
观看指南
  • 04:00 用真实数字一步步算基尼不纯度——跟着算一遍胜过看十遍公式。
  • 10:30 数值特征怎么选切分阈值(相邻值取中点遍历)——正是实验室里 JS 实现的逻辑。
  • 15:00 叶子样本过少的问题——过拟合的前兆。

交互实验室:决策边界对决

同一份数据,三种算法看到的世界完全不同。逻辑回归只能画直线;kNN 的边界跟着数据走但锯齿斑驳;决策树只会画横平竖直的矩形。必做实验:①月牙数据下对比三者;②XOR 数据让逻辑回归当场翻车(线性模型的极限,第 3 章神经网络的出场理由);③树深调到 12 看过拟合、调回 2 看欠拟合;④kNN 的 k=1 vs k=15 对比(方差 vs 偏差)。

decision-boundary.compare

点击画布放点 · 背景色块 = 模型对该区域的预测类别 · 训练集准确率实时显示

训练集准确率 = 注意:训练集 100% ≠ 好模型(想想第 1 章的过拟合)

集成学习:随机森林与梯度提升

「三个臭皮匠」的两种科学化方式,方向相反:

Bagging → 随机森林:并联降方差

对训练集做 $B$ 次有放回抽样(bootstrap),各训练一棵不剪枝的深树,预测时投票。$B$ 个方差为 $\sigma^2$、两两相关系数 $\rho$ 的估计器取平均后,方差变为:

$$\rho\sigma^2 + \frac{1-\rho}{B}\sigma^2$$

第二项随 $B$ 消失,但第一项卡在 $\rho\sigma^2$——树之间越相关,平均的收益越有限。随机森林的点睛之笔由此而来:每次分裂只从随机抽的 $\sqrt{d}$ 个特征里选,强行让树彼此「想得不一样」,把 $\rho$ 压下去。这就是「多样性比个体强度更重要」的数学表达。

Boosting → 梯度提升:串联降偏差

反过来用一串浅树(弱学习器),每棵专门修正前面所有树的残余错误。第 $m$ 步的精妙视角:把当前模型的预测 $F_{m-1}(x)$ 看作「参数」,对它求损失的负梯度 $r_i = -\frac{\partial L(y_i, F)}{\partial F}\big|_{F_{m-1}}$,训练一棵小树去拟合这个负梯度,然后 $F_m = F_{m-1} + \eta \cdot \text{tree}_m$。MSE 下负梯度恰好就是残差 $y - F(x)$,所以直觉版叙事是「每棵树学习上一轮的残差」——但负梯度视角才是它叫「梯度提升」的原因:这是在函数空间里做梯度下降。

XGBoost(2014)把这套做到工业极致:目标函数二阶泰勒展开(牛顿法而非单纯梯度)、对叶子权重加 L2 正则、缺失值自动学习默认方向、直方图加速与并行。在中小规模表格数据上,「XGBoost/LightGBM 优于神经网络」直到 2026 年仍是基本事实——别看完本课程就觉得万物皆深度学习。

VIDEO 03
Gradient Boost Part 1: Regression Main Ideas(梯度提升主思想)
StatQuest with Josh Starmer 15:52
观看指南
  • 03:00 从一个常数预测开始(初始模型 $F_0$ = 均值)。
  • 06:30 用树拟合残差、乘学习率后叠加——对应 $F_m = F_{m-1} + \eta\cdot\text{tree}_m$。
  • 12:00 为什么要乘学习率(每步只信一点点)——和第 1 章梯度下降的 η 是同一个哲学。

SVM:最大间隔与核技巧

可分数据有无数条分隔直线,哪条最好?SVM 的回答:离两边最近样本都最远的那条——最大化间隔(margin)。几何推导:点到超平面 $\mathbf{w}^\top\mathbf{x}+b=0$ 的距离是 $\frac{|\mathbf{w}^\top\mathbf{x}+b|}{\|\mathbf{w}\|}$,约定支持向量处 $|\mathbf{w}^\top\mathbf{x}+b|=1$,则间隔为 $\frac{2}{\|\mathbf{w}\|}$。最大化间隔等价于:

$$\min_{\mathbf{w},b}\ \frac{1}{2}\|\mathbf{w}\|^2 \quad \text{s.t.}\quad y^{(i)}(\mathbf{w}^\top\mathbf{x}^{(i)} + b) \ge 1,\ \forall i \qquad (y \in \{-1,+1\})$$

凸二次规划,有全局最优。现实数据有噪声,引入松弛变量 $\xi_i \ge 0$ 允许个别点越界,代价由超参 $C$ 控制(软间隔,1995)。用拉格朗日乘子法转成对偶问题后,发生两件大事:

$$\max_{\alpha}\ \sum_i \alpha_i - \frac{1}{2}\sum_{i,j} \alpha_i \alpha_j y^{(i)} y^{(j)} \langle \mathbf{x}^{(i)}, \mathbf{x}^{(j)} \rangle$$
核技巧:把内积替换成核函数 $K(\mathbf{x}, \mathbf{x}')$,等价于先把数据映射到高维空间 $\phi(\mathbf{x})$ 再做线性 SVM,却从不显式计算 $\phi$。RBF 核 $K(\mathbf{x},\mathbf{x}') = e^{-\gamma\|\mathbf{x}-\mathbf{x}'\|^2}$ 对应无限维特征空间——在原空间里画出任意弯曲的边界,代价只是算个指数。「同心圆」数据逻辑回归无解,RBF-SVM 轻松拿下(代码实战里亲手验证)。这种「升维让不可分变可分」的思想,与深度学习「学一个好的表示空间」殊途同归——只不过 SVM 的映射是固定的,神经网络的映射是学出来的。这是两个时代的分水岭。
VIDEO 04
Support Vector Machines Part 1(SVM 主思想)
StatQuest with Josh Starmer 20:32
观看指南
  • 04:30 最大间隔分类器及其对离群点的敏感——为什么需要软间隔。
  • 12:00 一维不可分数据升到二维后线性可分——核技巧的几何直觉,全片最重要的画面。
  • 17:30 多项式核与 RBF 核的直观对比。

代码实战:四种算法同台竞技

python · classifiers_showdown.py
# 四种世界观在两个数据集上的对决
import numpy as np
from sklearn.datasets import make_moons, make_circles
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC

datasets = {
    "moons":   make_moons(n_samples=500, noise=0.25, random_state=0),
    "circles": make_circles(n_samples=500, noise=0.1, factor=0.4, random_state=0),
}
models = {
    "LogReg(线性)":   LogisticRegression(),
    "Tree(d=4)":      DecisionTreeClassifier(max_depth=4),
    "RandomForest":   RandomForestClassifier(n_estimators=200),
    "GradBoost":      GradientBoostingClassifier(),          # 浅树串联
    "SVM-RBF":        SVC(kernel="rbf", C=1.0, gamma="scale"),
}
for dname, (X, y) in datasets.items():
    Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0)
    print(f"\n== {dname} ==")
    for mname, m in models.items():
        acc = m.fit(Xtr, ytr).score(Xte, yte)     # 注意:评测用测试集!
        print(f"  {mname:14s} {acc:.3f}")
# 预期:moons/circles 上 LogReg 明显落后(线性边界的极限),
# RBF-SVM 与集成方法接近满分。把 noise 调大再跑——排名会怎么变?
什么时候该选树模型(XGBoost),什么时候该选神经网络?
2026 年的实用判据依然是:表格数据(特征已是人造的、有语义的列)→ 先试梯度提升树;样本量在几千到几百万、特征几十到几千维时,树模型往往更准、更快、更省调参。感知类数据(图像/音频/文本——原始信号,特征需要学出来)→ 深度学习无可替代,因为它的本质优势是表示学习(第 3、4 章)。混合场景(表格+文本列)常见做法是 LLM/embedding 抽特征喂给 XGBoost。面试和实战都常考这个判断。

章节测验