1统计学习方法(第2版)

统计学习方法概论

机器学习基础

监督学习假设空间模型评估

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第1章:统计学习方法概论(Introduction to Statistical Learning Methods)

一、导读

1.1 本章学习目标

第1章是整本《统计学习方法》的开篇之作,它并不深入讲解某个具体算法,而是为读者建立统计学习的全局视野。统计学习的核心思想是从数据中学习模型,利用模型对未知数据进行预测和决策。在后续章节逐一介绍感知机、朴素贝叶斯、决策树、支持向量机等具体方法之前,你需要先理解这些方法背后的共同框架——它们都是统计学习三要素(模型、策略、算法)的不同实例化。

本章的核心学习目标包括:

  • 理解统计学习的本质:从数据中学习模型,利用模型进行预测,这一过程涉及哪些基本要素?
  • 掌握监督学习的基本框架:输入空间、输出空间、特征空间、假设空间之间是什么关系?
  • 理解经验风险与结构风险最小化:为什么仅最小化训练误差会导致过拟合?如何防止?
  • 掌握模型评估的方法:训练误差、测试误差、泛化能力之间有什么关系?
  • 理解正则化的作用:为什么正则化可以控制模型复杂度?L1和L2正则化有什么区别?
  • 了解泛化理论的基本结论:泛化误差上界如何给出理论保证?

1.2 为什么第一章如此重要

很多初学者急于跳入具体算法的实现,觉得第一章"太理论"或"太抽象"。这种想法是极其危险的。正如建筑设计师需要理解力学原理,机器学习从业者也需要理解统计学习的理论框架。没有这个框架,后续学习就容易陷入"只会调包,不知其所以然"的困境。

李航老师在本书中反复强调一个观点:统计学习方法的三要素是模型、策略和算法。每一章介绍的具体方法,都是这三要素的一个具体实现。理解了第一章的框架,你就能看清不同方法之间的共性和差异,而不是把它们当作孤立的技巧来记忆。

1.3 核心问题引导

在阅读本章时,请带着以下问题思考:

什么是统计学习?它与传统的程序设计有什么本质区别?

为什么我们需要定义假设空间?假设空间过大或过小分别会导致什么问题?

经验风险最小化为什么不够?什么情况下它会失效?

结构风险最小化是如何解决过拟合问题的?正则化在其中扮演什么角色?

泛化误差上界告诉我们什么?它与样本量和模型复杂度有什么关系?

生成模型和判别模型有什么本质区别?各自适用于什么场景?


二、核心概念详解

2.1 统计学习的本质

统计学习(Statistical Learning)是关于计算机基于数据构建概率统计模型并运用模型对数据进行预测和分析的方法。其核心思想可以用一句话概括:从数据中学习规律,用规律预测未来。

与传统程序设计的区别在于:传统程序设计中,程序员根据明确的规则编写代码(例如排序算法的比较规则);而在统计学习中,规则(模型)是从数据中自动学习得到的。我们不需要告诉计算机"什么是猫",只需要给它大量标注了"猫"或"不是猫"的图片,它就能自动学习到区分猫的规律。

python
import numpy as np

# 传统程序:明确的规则
def sort_bubble(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

# 统计学习:从数据中学习规则
# 假设我们有一组数据,想学习 x 和 y 之间的关系
X_train = np.array([1, 2, 3, 4, 5])
y_train = np.array([2.1, 3.9, 6.2, 7.8, 10.1])

# 通过最小二乘法学习线性模型 y = w*x + b
w = np.sum((X_train - X_train.mean()) * (y_train - y_train.mean())) / np.sum((X_train - X_train.mean()) ** 2)
b = y_train.mean() - w * X_train.mean()
print(f"学习到的模型: y = {w:.2f}*x + {b:.2f}")
print(f"预测 x=6: y = {w * 6 + b:.2f}")

这段代码展示了统计学习的基本范式:给定训练数据 (X_train, y_train),通过某种学习准则(这里是最小二乘法)自动确定模型参数 w 和 b,然后用学习到的模型对新数据进行预测。

2.2 监督学习的基本框架

监督学习(Supervised Learning)是统计学习中最重要的一类。在监督学习中,我们拥有一组训练数据(training data),每条数据由输入(特征)和输出(标签)组成。学习的目标是找到一个模型,使得它对未知数据的预测尽可能准确。

2.2.1 输入空间、输出空间与特征空间

输入空间(Input Space)是所有可能输入的集合。在图像分类中,输入空间是所有可能的图像;在文本分类中,输入空间是所有可能的文档。

输出空间(Output Space)是所有可能输出的集合。在二分类问题中,输出空间是 {+1, -1} 或 {0, 1};在回归问题中,输出空间通常是实数集 R。

特征空间(Feature Space)是输入空间中元素经过特征提取后的表示空间。特征的选择对学习效果至关重要——好的特征能够捕捉数据的本质规律,差的特征则会让学习变得困难。

python
import numpy as np

# 输入空间:原始数据
# 例如,一个学生的信息:[年龄, 学习时长, 出勤率]
raw_data = np.array([
    [18, 40, 0.95],
    [19, 35, 0.88],
    [20, 50, 0.92],
    [17, 25, 0.78],
])

# 特征空间:经过特征工程后的表示
# 例如,添加交互特征和多项式特征
def feature_engineering(X):
    # 原始特征
    age, hours, attendance = X[:, 0], X[:, 1], X[:, 2]
    # 新特征:学习强度
    intensity = hours * attendance
    # 新特征:年龄分组
    age_group = (age >= 19).astype(float)
    return np.column_stack([X, intensity, age_group])

X_features = feature_engineering(raw_data)
print(f"原始特征维度: {raw_data.shape[1]}")
print(f"特征工程后维度: {X_features.shape[1]}")

2.2.3 假设空间

假设空间(Hypothesis Space)是所有可能模型的集合。学习的过程就是在假设空间中搜索最优模型的过程。假设空间的选择决定了模型的能力上限。

以线性模型为例,假设空间是所有形如 f(x) = w·x + b 的函数的集合。不同的参数 (w, b) 对应不同的模型,整个假设空间就是所有可能的参数组合。

python
import numpy as np

# 假设空间:所有线性模型 f(x) = w*x + b
# 不同的 (w, b) 对应不同的模型

# 生成假设空间中的一个网格
w_range = np.linspace(-2, 4, 50)
b_range = np.linspace(-3, 3, 50)

# 对于每个 (w, b),计算训练误差
X_train = np.array([1, 2, 3, 4, 5], dtype=float)
y_train = np.array([2.1, 3.9, 6.2, 7.8, 10.1])

best_loss = float('inf')
best_w, best_b = 0, 0

for w in w_range:
    for b in b_range:
        y_pred = w * X_train + b
        loss = np.mean((y_pred - y_train) ** 2)
        if loss < best_loss:
            best_loss = loss
            best_w, best_b = w, b

print(f"最优模型: y = {best_w:.2f}*x + {best_b:.2f}")
print(f"训练误差: {best_loss:.4f}")

这段代码展示了在假设空间中搜索最优模型的过程。实际中,我们不会用网格搜索,而是用更高效的优化算法(如梯度下降)来找到最优参数。

2.3 统计学习的三要素

统计学习方法 = 模型 + 策略 + 算法。这是贯穿全书的核心框架。

2.3.1 模型(Model)

模型是要学习的条件概率分布 P(Y|X) 或决策函数 Y = f(X) 的假设空间。不同的模型对应不同的假设空间:

  • 感知机:f(x) = sign(w·x + b)
  • 朴素贝叶斯:P(Y|X) = P(X|Y)P(Y) / P(X)(特征条件独立假设)
  • 决策树:if-then 规则的集合
  • 逻辑斯谛回归:P(Y=1|x) = 1 / (1 + e^(-w·x))

2.3.2 策略(Strategy)

策略是按照什么准则进行学习或模型选择的准则。常见的策略包括:

  • 经验风险最小化(Empirical Risk Minimization, ERM):最小化训练数据上的损失函数
  • 结构风险最小化(Structural Risk Minimization, SRM):最小化经验风险 + 正则化项

损失函数(Loss Function)度量模型预测值与真实值之间的差距。常见的损失函数包括:

python
import numpy as np

# 0-1损失(分类错误数)
def zero_one_loss(y_true, y_pred):
    return np.mean(y_true != y_pred)

# 平方损失(回归)
def squared_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 绝对损失(回归)
def absolute_loss(y_true, y_pred):
    return np.mean(np.abs(y_true - y_pred))

# 对数损失(分类)
def log_loss(y_true, y_pred_prob):
    eps = 1e-15
    y_pred_prob = np.clip(y_pred_prob, eps, 1 - eps)
    return -np.mean(y_true * np.log(y_pred_prob) + (1 - y_true) * np.log(1 - y_pred_prob))

# 示例
y_true = np.array([1, 0, 1, 1, 0])
y_pred = np.array([1, 0, 0, 1, 1])
print(f"0-1损失: {zero_one_loss(y_true, y_pred):.2f}")
print(f"平方损失: {squared_loss(y_true, y_pred):.2f}")

2.3.3 算法(Algorithm)

算法是求解最优模型的计算方法。给定模型和策略后,学习问题变成了一个最优化问题。算法需要高效地求解这个最优化问题。

常见的优化算法包括:

  • 梯度下降法(Gradient Descent)
  • 牛顿法(Newton's Method)
  • 拟牛顿法(Quasi-Newton Method, 如 BFGS)
  • 随机梯度下降法(Stochastic Gradient Descent, SGD)
python
import numpy as np

# 梯度下降法示例:最小化 f(w) = w^2 + 2w + 1
def gradient_descent(lr=0.1, n_iter=100, w_init=5.0):
    w = w_init
    history = [w]
    for _ in range(n_iter):
        grad = 2 * w + 2  # f'(w) = 2w + 2
        w = w - lr * grad
        history.append(w)
    return w, history

w_opt, history = gradient_descent()
print(f"最优解: w = {w_opt:.4f}")
print(f"理论最优解: w = -1.0")
print(f"收敛过程(前10步): {[f'{w:.4f}' for w in history[:10]]}")

2.4 经验风险与结构风险最小化

2.4.1 经验风险最小化(ERM)

训练误差(经验风险)是模型在训练数据上的损失函数的平均值:

R_emp(f) = (1/N) * Σ L(y_i, f(x_i))

经验风险最小化就是选择使训练误差最小的模型。当样本容量足够大时,经验风险最小化是有效的。但当样本容量较小而模型复杂度过高时,ERM 会导致过拟合——模型在训练数据上表现很好,但在未知数据上表现很差。

python
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# 过拟合示例
np.random.seed(42)
X = np.linspace(0, 1, 15)
y = np.sin(2 * np.pi * X) + np.random.randn(15) * 0.3

# 不同复杂度的多项式拟合
degrees = [1, 3, 10]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

for ax, degree in zip(axes, degrees):
    coeffs = np.polyfit(X, y, degree)
    p = np.poly1d(coeffs)
    X_test = np.linspace(0, 1, 100)
    
    ax.scatter(X, y, color='blue', s=30, zorder=5)
    ax.plot(X_test, p(X_test), 'r-', linewidth=2)
    ax.set_title(f'Degree = {degree}')
    ax.set_ylim(-2, 2)
    
    train_loss = np.mean((p(X) - y) ** 2)
    ax.text(0.5, -1.8, f'Train Loss: {train_loss:.4f}', ha='center')

plt.tight_layout()
plt.savefig('/tmp/overfitting_demo.png', dpi=100)
print("过拟合示例已保存")

当 degree=1 时,模型太简单,无法捕捉数据的规律(欠拟合);当 degree=10 时,模型过于复杂,完美地拟合了训练数据中的噪声(过拟合);当 degree=3 时,模型复杂度适中,能够较好地捕捉数据的真实规律。

2.4.2 结构风险最小化(SRM)

结构风险最小化在经验风险的基础上加上正则化项:

R_srm(f) = (1/N) * Σ L(y_i, f(x_i)) + λ * J(f)

其中 J(f) 是正则化项,度量模型的复杂度;λ ≥ 0 是正则化系数,控制经验风险和模型复杂度之间的权衡。

常见的正则化项包括:

  • L1正则化:J(f) = ||w||_1 = Σ|w_i|,倾向于产生稀疏解
  • L2正则化:J(f) = ||w||_2^2 = Σw_i^2,倾向于使参数值较小且均匀
python
import numpy as np

# 正则化效果对比
np.random.seed(42)
n_samples = 50
X = np.random.randn(n_samples, 10)  # 10个特征
true_w = np.array([1, 0.5, -0.3] + [0] * 7)
y = X @ true_w + np.random.randn(n_samples) * 0.5

# 无正则化(普通最小二乘)
w_ols = np.linalg.lstsq(X, y, rcond=None)[0]

# L2正则化(岭回归)
alpha = 1.0
w_ridge = np.linalg.solve(X.T @ X + alpha * np.eye(X.shape[1]), X.T @ y)

# L1正则化(Lasso,用坐标下降法近似)
from numpy.linalg import norm

def lasso_coord_descent(X, y, alpha, n_iter=1000):
    n, p = X.shape
    w = np.zeros(p)
    for _ in range(n_iter):
        for j in range(p):
            r = y - X @ w + X[:, j] * w[j]
            rho = X[:, j] @ r / n
            w[j] = np.sign(rho) * max(abs(rho) - alpha, 0) / (np.sum(X[:, j] ** 2) / n)
    return w

w_lasso = lasso_coord_descent(X, y, alpha=0.1)

print(f"{'参数':<12} {'OLS':>8} {'L2':>8} {'L1':>8}")
print("-" * 40)
for i in range(10):
    print(f"w[{i}]{'(true='+str(true_w[i])+')':<8} {w_ols[i]:>8.4f} {w_ridge[i]:>8.4f} {w_lasso[i]:>8.4f}")
print("-" * 40)
print(f"{'||w||_1':<12} {norm(w_ols, 1):>8.4f} {norm(w_ridge, 1):>8.4f} {norm(w_lasso, 1):>8.4f}")

从结果可以看出:L1正则化(Lasso)倾向于将不重要的特征系数压缩为0,产生稀疏解;L2正则化(Ridge)使所有系数都较小但不为0;无正则化的OLS则可能产生较大的系数值。

2.5 泛化能力与泛化误差上界

2.5.1 泛化误差

泛化误差(Generalization Error)是模型在未知数据上的误差。我们真正关心的不是训练误差,而是泛化误差——模型在"未来"数据上的表现。

泛化误差的期望可以表示为:

R(f) = E[L(Y, f(X))]

由于我们无法直接计算泛化误差(因为我们不知道未来的数据),所以需要用测试误差来近似估计。

2.5.2 泛化误差上界

统计学习理论给出了泛化误差的上界。一个经典的结论是:

R(f) ≤ R_emp(f) + √((log|H| + log(1/δ)) / (2N))

其中 R(f) 是泛化误差,R_emp(f) 是经验风险,|H| 是假设空间的"大小"(VC维等度量),N 是样本量,δ 是置信度。

这个上界告诉我们几个重要结论:

样本量越大,泛化误差越接近经验风险

假设空间越复杂(|H| 越大),泛化误差上界越大

需要在模型复杂度和拟合能力之间取得平衡

python
import numpy as np

# 泛化误差上界的数值演示
def generalization_bound(emp_risk, vc_dim, n_samples, delta=0.05):
    """计算泛化误差上界"""
    return emp_risk + np.sqrt((vc_dim * np.log(2 * n_samples) + np.log(1 / delta)) / (2 * n_samples))

# 固定 VC 维,观察样本量的影响
vc_dim = 10
sample_sizes = [10, 50, 100, 500, 1000, 5000]
print(f"{'样本量':>8} {'经验风险':>10} {'泛化上界':>10} {'Gap':>10}")
print("-" * 42)
for n in sample_sizes:
    emp_risk = 0.1  # 假设经验风险固定为 0.1
    bound = generalization_bound(emp_risk, vc_dim, n)
    print(f"{n:>8} {emp_risk:>10.4f} {bound:>10.4f} {bound - emp_risk:>10.4f}")

print()

# 固定样本量,观察 VC 维的影响
n_samples = 200
vc_dims = [2, 5, 10, 20, 50]
print(f"{'VC维':>8} {'经验风险':>10} {'泛化上界':>10} {'Gap':>10}")
print("-" * 42)
for vc in vc_dims:
    emp_risk = 0.1
    bound = generalization_bound(emp_risk, vc, n_samples)
    print(f"{vc:>8} {emp_risk:>10.4f} {bound:>10.4f} {bound - emp_risk:>10.4f}")

2.6 生成模型与判别模型

统计学习方法可以分为生成方法(Generative Approach)和判别方法(Discriminative Approach)。

2.6.1 生成模型

生成模型学习联合概率分布 P(X, Y),然后通过贝叶斯定理求出条件概率分布 P(Y|X)。典型的生成模型包括:朴素贝叶斯、隐马尔可夫模型、混合高斯模型。

python
import numpy as np

# 生成模型的思路:先学 P(X|Y) 和 P(Y),再用贝叶斯定理求 P(Y|X)
# 简化的二分类生成模型示例

# 训练数据
X_train = np.array([[1, 2], [2, 3], [3, 3], [6, 5], [7, 8], [8, 8]])
y_train = np.array([0, 0, 0, 1, 1, 1])

# 学习每个类别的均值和方差(假设高斯分布)
class_0 = X_train[y_train == 0]
class_1 = X_train[y_train == 1]

mu_0, mu_1 = class_0.mean(axis=0), class_1.mean(axis=0)
sigma_0, sigma_1 = class_0.var(axis=0), class_1.var(axis=0)
prior_0 = len(class_0) / len(X_train)
prior_1 = len(class_1) / len(X_train)

# 预测
def gaussian_pdf(x, mu, sigma):
    return np.prod(1 / np.sqrt(2 * np.pi * sigma) * np.exp(-0.5 * (x - mu) ** 2 / sigma))

x_test = np.array([4, 4])
p_x_given_0 = gaussian_pdf(x_test, mu_0, sigma_0) * prior_0
p_x_given_1 = gaussian_pdf(x_test, mu_1, sigma_1) * prior_1
p_x = p_x_given_0 + p_x_given_1
p_0_given_x = p_x_given_0 / p_x
p_1_given_x = p_x_given_1 / p_x

print(f"测试点: {x_test}")
print(f"P(Y=0|X) = {p_0_given_x:.4f}")
print(f"P(Y=1|X) = {p_1_given_x:.4f}")
print(f"预测类别: {1 if p_1_given_x > p_0_given_x else 0}")

2.6.2 判别模型

判别模型直接学习条件概率分布 P(Y|X) 或决策函数 Y = f(X)。典型的判别模型包括:感知机、逻辑斯谛回归、支持向量机、决策树、条件随机场。

判别模型的优势在于:直接针对预测任务建模,不需要对数据的生成过程做假设,通常在分类和回归任务上表现更好。

生成模型的优势在于:可以处理缺失数据,可以生成新样本,当样本量较小时收敛速度更快。


三、实战案例

3.1 模型选择:交叉验证

python
import numpy as np

def k_fold_cross_validation(X, y, model_class, model_params, k=5):
    """k折交叉验证"""
    n = len(X)
    indices = np.arange(n)
    np.random.shuffle(indices)
    
    fold_size = n // k
    scores = []
    
    for i in range(k):
        start = i * fold_size
        end = start + fold_size if i < k - 1 else n
        
        val_idx = indices[start:end]
        train_idx = np.concatenate([indices[:start], indices[end:]])
        
        X_train, X_val = X[train_idx], X[val_idx]
        y_train, y_val = y[train_idx], y[val_idx]
        
        model = model_class(**model_params)
        model.fit(X_train, y_train)
        score = model.score(X_val, y_val)
        scores.append(score)
    
    return np.mean(scores), np.std(scores)

# 简单模型类用于演示
class SimpleLinearClassifier:
    def __init__(self, lr=0.01, n_iter=100):
        self.lr = lr
        self.n_iter = n_iter
    
    def fit(self, X, y):
        self.w = np.zeros(X.shape[1])
        self.b = 0.0
        for _ in range(self.n_iter):
            z = X @ self.w + self.b
            pred = 1 / (1 + np.exp(-z))
            error = pred - y
            self.w -= self.lr * X.T @ error / len(y)
            self.b -= self.lr * np.mean(error)
        return self
    
    def predict(self, X):
        z = X @ self.w + self.b
        return (1 / (1 + np.exp(-z)) >= 0.5).astype(int)
    
    def score(self, X, y):
        return np.mean(self.predict(X) == y)

# 生成测试数据
np.random.seed(42)
X = np.random.randn(200, 5)
w_true = np.array([1, -0.5, 0.3, 0, 0])
y = (X @ w_true + np.random.randn(200) * 0.5 > 0).astype(int)

# 交叉验证
mean_score, std_score = k_fold_cross_validation(
    X, y, SimpleLinearClassifier, {'lr': 0.1, 'n_iter': 200}, k=5
)
print(f"5折交叉验证准确率: {mean_score:.4f} ± {std_score:.4f}")

3.2 偏差-方差分解

python
import numpy as np

def bias_variance_decomposition():
    """
    偏差-方差分解实验
    展示模型复杂度与偏差、方差的关系
    """
    np.random.seed(42)
    n_train = 30
    n_test = 1000
    n_trials = 100
    
    # 真实函数
    X_test = np.linspace(0, 1, n_test)
    f_true = np.sin(2 * np.pi * X_test)
    
    results = {}
    
    for degree in [1, 3, 5, 9, 14]:
        predictions = np.zeros((n_trials, n_test))
        
        for trial in range(n_trials):
            X_train = np.random.rand(n_train)
            y_train = np.sin(2 * np.pi * X_train) + np.random.randn(n_train) * 0.5
            coeffs = np.polyfit(X_train, y_train, degree)
            predictions[trial] = np.polyval(coeffs, X_test)
        
        # 偏差^2: (E[f_hat] - f)^2
        mean_pred = predictions.mean(axis=0)
        bias_sq = np.mean((mean_pred - f_true) ** 2)
        
        # 方差: E[(f_hat - E[f_hat])^2]
        variance = np.mean(np.mean((predictions - mean_pred) ** 2, axis=0))
        
        # 不可约误差
        irreducible = 0.25  # sigma^2 = 0.5^2
        
        results[degree] = {
            'bias_sq': bias_sq,
            'variance': variance,
            'irreducible': irreducible,
            'total_error': bias_sq + variance + irreducible
        }
    
    print(f"{'多项式阶数':>10} {'偏差²':>10} {'方差':>10} {'不可约误差':>10} {'总误差':>10}")
    print("-" * 55)
    for degree, metrics in results.items():
        print(f"{degree:>10} {metrics['bias_sq']:>10.4f} {metrics['variance']:>10.4f} "
              f"{metrics['irreducible']:>10.4f} {metrics['total_error']:>10.4f}")

bias_variance_decomposition()

3.3 正则化路径

python
import numpy as np

def regularization_path():
    """展示不同正则化强度下模型参数的变化"""
    np.random.seed(42)
    n, p = 100, 20
    X = np.random.randn(n, p)
    true_w = np.zeros(p)
    true_w[:5] = [2, -1.5, 1, -0.5, 0.3]
    y = X @ true_w + np.random.randn(n) * 0.5
    
    alphas = np.logspace(-2, 2, 50)
    ridge_coefs = []
    
    for alpha in alphas:
        w = np.linalg.solve(X.T @ X + alpha * np.eye(p), X.T @ y)
        ridge_coefs.append(w)
    
    ridge_coefs = np.array(ridge_coefs)
    
    print(f"{'正则化强度':>12} {'||w||_2':>10} {'非零系数数':>10} {'训练MSE':>10}")
    print("-" * 45)
    for i in [0, 10, 20, 30, 40, 49]:
        w = ridge_coefs[i]
        mse = np.mean((X @ w - y) ** 2)
        n_nonzero = np.sum(np.abs(w) > 0.01)
        print(f"{alphas[i]:>12.4f} {np.linalg.norm(w):>10.4f} {n_nonzero:>10} {mse:>10.4f}")

regularization_path()

四、本章小结

第1章为统计学习方法建立了统一的理论框架:

统计学习的三要素:模型(假设空间)、策略(学习准则)、算法(优化方法)。每一章的具体方法都是这三要素的一个实例化。

经验风险最小化是直观的学习策略,但容易导致过拟合。结构风险最小化通过引入正则化项来控制模型复杂度。

泛化误差上界揭示了样本量、模型复杂度和泛化能力之间的定量关系:样本量越大、模型越简单,泛化能力越强。

生成模型学习联合概率 P(X,Y),判别模型直接学习条件概率 P(Y|X) 或决策函数。两者各有优劣。

正则化是控制过拟合的重要手段,L1正则化产生稀疏解,L2正则化使参数值均匀缩小。

本章最重要的启示是:不要只关注算法的实现,更要理解算法背后的理论框架。只有建立了这个框架,你才能在面对新问题时选择合适的模型和策略,而不是盲目地尝试各种算法。


五、思考与练习

思考题

为什么说"没有免费午餐定理"(No Free Lunch Theorem)意味着没有一种算法能在所有问题上都表现最好?这与模型选择有什么关系?

经验风险和泛化误差之间的关系是什么?在什么条件下它们会接近?

L1正则化为什么能产生稀疏解?从几何角度解释L1和L2正则化的区别。

生成模型和判别模型在什么情况下各更有优势?能否给出直觉上的解释?

VC维是什么?它与假设空间的复杂度有什么关系?

编程练习

实现一个多项式回归模型,在不同阶数(1, 3, 5, 10, 15)下拟合正弦曲线加噪声的数据。绘制训练误差和测试误差随阶数变化的曲线,验证过拟合现象。

实现L1和L2正则化的线性回归,在同一数据集上比较两者的参数稀疏性和预测精度。

实现k折交叉验证,用它来选择多项式回归的最优阶数。


1/12统计学习
0%