偏差—方差分析与数据划分:参考答案

目录

\[ \begin{align}\begin{aligned}\newcommand{\ba}{\boldsymbol{a}} \newcommand{\bb}{\boldsymbol{b}} \newcommand{\be}{\boldsymbol{e}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bw}{\boldsymbol{w}} \newcommand{\bx}{\boldsymbol{x}} \newcommand{\by}{\boldsymbol{y}} \newcommand{\bz}{\boldsymbol{z}} \newcommand{\bd}{\boldsymbol{d}} \newcommand{\bv}{\boldsymbol{v}} \newcommand{\bs}{\boldsymbol{s}}\\\newcommand{\btheta}{\boldsymbol{\theta}} \newcommand{\bbeta}{\boldsymbol{\beta}} \newcommand{\bgamma}{\boldsymbol{\gamma}} \newcommand{\bsigma}{\boldsymbol{\sigma}} \newcommand{\md}{\mbox{d}} \newcommand{\bmu}{\boldsymbol{\mu}} \newcommand{\bone}{\boldsymbol{1}} \newcommand{\bzero}{\boldsymbol{0}} \newcommand{\bepsilon}{\boldsymbol{\epsilon}} \newcommand{\bphi}{\boldsymbol{\phi}} \newcommand{\bh}{\boldsymbol{h}} \newcommand{\bc}{\boldsymbol{c}} \newcommand{\br}{\boldsymbol{r}} \newcommand{\bQ}{\boldsymbol{Q}} \newcommand{\bK}{\boldsymbol{K}} \newcommand{\bV}{\boldsymbol{V}} \newcommand{\bSigma}{\boldsymbol{\Sigma}} \newcommand{\bg}{\boldsymbol{g}} \newcommand{\bxi}{\boldsymbol{\xi}} \newcommand{\bvarepsilon}{\boldsymbol{\varepsilon}} \newcommand{\bdelta}{\boldsymbol{\delta}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bJ}{\boldsymbol{J}} \newcommand{\bp}{\boldsymbol{p}} \newcommand{\bi}{\boldsymbol{i}} \newcommand{\bo}{\boldsymbol{o}} \newcommand{\bE}{\boldsymbol{E}} \newcommand{\bH}{\boldsymbol{H}} \newcommand{\bL}{\boldsymbol{L}} \newcommand{\bu}{\boldsymbol{u}} \newcommand{\bLambda}{\boldsymbol{\Lambda}} \newcommand{\trans}{^{\rm\scriptsize T}} \newcommand{\var}{\mathrm{var}}\\\newcommand{\bA}{\boldsymbol{A}} \newcommand{\bB}{\boldsymbol{B}} \newcommand{\bC}{\boldsymbol{C}} \newcommand{\bD}{\boldsymbol{D}} \newcommand{\bG}{\boldsymbol{G}} \newcommand{\bI}{\boldsymbol{I}} \newcommand{\bM}{\boldsymbol{M}} \newcommand{\bP}{\boldsymbol{P}} \newcommand{\bS}{\boldsymbol{S}} \newcommand{\bU}{\boldsymbol{U}} \newcommand{\bW}{\boldsymbol{W}} \newcommand{\bX}{\boldsymbol{X}} \newcommand{\bY}{\boldsymbol{Y}} \newcommand{\bZ}{\boldsymbol{Z}} \newcommand{\cotp}{\textcolor[RGB]{48,209,88}{TP}} \newcommand{\cotn}{\textcolor[RGB]{100,210,255}{TN}} \newcommand{\cofp}{\textcolor[RGB]{94,92,230}{FP}} \newcommand{\cofn}{\textcolor[RGB]{191,90,242}{FN}}\\\newcommand{\numcotp}{\textcolor[RGB]{48,209,88}{50}} \newcommand{\numcotn}{\textcolor[RGB]{100,210,255}{30}} \newcommand{\numcofp}{\textcolor[RGB]{94,92,230}{10}} \newcommand{\numcofn}{\textcolor[RGB]{191,90,242}{10}} \DeclareMathOperator*{\argmin}{arg\,min}\end{aligned}\end{align} \]

偏差—方差分析与数据划分:参考答案#

返回正文练习 · 返回答案索引

说明#

以下答案与正文 11 道题逐题对应。推导题给出主要步骤;编程题给出一种参考实现。随机模拟结果会随随机种子和重复次数略有变化,只要与理论结果接近且差异能由模拟波动解释即可。

  1. \[\overline y(\bx)=\mathbb E_S\widehat y_S(\bx).\]

    在预测误差中加上并减去 \(\overline y(\bx)\)⁠,得到

    \[\widehat y_S(\bx)-y_{\mathrm t}(\bx) =\left\{\widehat y_S(\bx)-\overline y(\bx)\right\} +\left\{\overline y(\bx)-y_{\mathrm t}(\bx)\right\}.\]

    平方后对训练集取期望:

    \[\begin{split}\begin{aligned} &\mathbb E_S\!\left[ \left\{\widehat y_S(\bx)-y_{\mathrm t}(\bx)\right\}^2 \right]\\ &\quad= \mathbb E_S\!\left[ \left\{\widehat y_S(\bx)-\overline y(\bx)\right\}^2 \right] +\left\{\overline y(\bx)-y_{\mathrm t}(\bx)\right\}^2\\ &\qquad +2\left\{\overline y(\bx)-y_{\mathrm t}(\bx)\right\} \mathbb E_S\!\left\{ \widehat y_S(\bx)-\overline y(\bx) \right\}. \end{aligned}\end{split}\]

    最后一项中的期望为 0,因此交叉项消失。第一项是预测方差,第二项是偏差平方,于是得到式 (57)⁠。

  2. 根据式 (55)⁠,

    \[Y-\widehat y_S(\bx) =\varepsilon+ \left\{y_{\mathrm t}(\bx)-\widehat y_S(\bx)\right\}.\]

    平方并对训练集和新观测取期望。因为 \(\mathbb E(\varepsilon\mid\bx)=0\)⁠,并且测试噪声与训练过程相互独立,所以

    \[\mathbb E\!\left[ \varepsilon \left\{y_{\mathrm t}(\bx)-\widehat y_S(\bx)\right\} \mid\bx \right]=0.\]

    噪声平方项等于 \(\sigma^2(\bx)\)⁠,其余部分由第 1 题分成偏差平方与方差,因此

    \[\mathbb E_{S,Y\mid\bx}\!\left[ \left\{Y-\widehat y_S(\bx)\right\}^2 \right] =\sigma^2(\bx) +\operatorname{Bias}^2\!\left\{\widehat y(\bx)\right\} +\operatorname{Var}_S\!\left\{\widehat y(\bx)\right\}.\]
  3. 由独立同分布条件,

    \[\begin{split}\begin{aligned} \mathbb E_S(\widehat\mu) &=\frac{1}{n}\sum_{i=1}^{n}\mathbb E(Y_i)=\mu,\\ \operatorname{Bias}(\widehat\mu) &=\mathbb E_S(\widehat\mu)-\mu=0,\\ \operatorname{Var}_S(\widehat\mu) &=\frac{1}{n^2}\sum_{i=1}^{n}\operatorname{Var}(Y_i) =\frac{\sigma^2}{n}. \end{aligned}\end{split}\]

    \(\mu=6\)⁠、\(\sigma^2=1\) 时,结果为:

    表 9 两种样本量下的理论结果#

    样本量

    偏差

    方差

    相对于真实条件均值的均方误差

    \(50\)

    \(0\)

    \(1/50=0.02\)

    \(0.02\)

    \(500\)

    \(0\)

    \(1/500=0.002\)

    \(0.002\)

    这里的均方误差以 \(\mu\) 为比较对象,因此不含新观测噪声。如果改为预测一个新的随机观测 \(Y\)⁠,还要分别加上不可约噪声方差 1,得到 \(1.02\)\(1.002\)⁠。

  4. (64) 的主要条件包括:真实条件均值确实是给定特征的线性函数;误差在给定设计矩阵时的条件均值为 0;设计矩阵满列秩,使最小二乘估计能够唯一确定。要得到式 (65) 的简洁形式,还需要给定设计矩阵时不同观测误差相互不相关,并且具有共同方差 \(\sigma^2\)⁠。

    当样本量增加且新增样本仍能覆盖相同的特征范围时,\(\widetilde\bX\trans\cdot\widetilde\bX\) 中包含的信息通常增加,其逆矩阵在相关方向上的数值通常减小。因此,式 (65) 往往变小,不同训练集拟合出的直线也会更加集中。

    若输入 \(\bx\) 远离训练数据集中出现的区域,\(\widetilde\bx\trans\cdot(\widetilde\bX\trans\cdot\widetilde\bX)^{-1}\cdot\widetilde\bx\) 可能较大,所以外推位置的预测更容易随训练集变化。样本量增加并不自动保证所有方向上的方差都减小;新增数据还需要提供相应区域或方向的信息。

  5. 三次预测的平均值为

    \[\overline y=\frac{1.8+2.0+2.2}{3}=2.\]

    因此经验偏差平方为

    \[(\overline y-2)^2=0.\]

    按总体方差定义,

    \[\widehat{\operatorname{Var}} =\frac{(1.8-2)^2+(2.0-2)^2+(2.2-2)^2}{3} =\frac{0.08}{3} \approx0.0267.\]

    完整的期望测试均方误差为

    \[0.25+0+0.0267\approx0.2767.\]
  6. 第一处问题是“先用全部数据标准化”。这样做会让验证集和测试集的均值、标准差提前进入数据处理过程。正确做法是先划分数据,只用训练集计算标准化所需的均值和标准差,再用同一组数值处理三个数据集。

    第二处问题是根据测试结果修改网络宽度。网络宽度属于需要选择的方案,应根据验证集比较;测试集只能在标准化方法、模型结构、学习率、训练轮数和评价规则全部确定后用于最终评价。一个正确顺序是:

    1. 先按任务要求划分训练集、验证集和测试集;

    2. 只用训练集计算数据处理所需的数值,并训练各个候选方案;

    3. 用验证集选择学习率、网络宽度和训练轮数;

    4. 保持完整方案不变,在测试集上评价最终结果。

  7. 一种参考实现如下。这里用总体方差 ddof=0使模拟定义与正文中对所有可能训练集取方差的定义一致。

    import numpy as np
    
    
    def simulate_sample_mean(n, repeats=10_000, seed=2026):
        rng = np.random.default_rng(seed)
        samples = rng.normal(
            loc=6.0,
            scale=1.0,
            size=(repeats, n),
        )
        estimates = samples.mean(axis=1)
        assert estimates.shape == (repeats,)
        assert np.isfinite(estimates).all()
    
        bias = estimates.mean() - 6.0
        variance = estimates.var(ddof=0)
        mse_to_truth = np.mean((estimates - 6.0) ** 2)
        return {
            "n": n,
            "bias": bias,
            "variance": variance,
            "mse_to_truth": mse_to_truth,
            "theoretical_variance": 1.0 / n,
        }
    
    
    for n in (50, 500):
        print(simulate_sample_mean(n))
    

    重复次数足够大时,两组经验偏差都应接近 0,经验方差应分别接近 \(0.02\)\(0.002\)⁠,相对于 \(6\) 的经验均方误差也应接近相应方差。模拟偏差不会恰好等于 0,这是有限次重复带来的随机波动。

  8. 下面的程序把每一行预测看作一份独立训练集得到的结果,并在同一组固定输入上计算分解。

    import numpy as np
    
    
    def fit_polynomial_decomposition(
        degrees=(1, 3, 5, 9),
        n_train=50,
        repeats=500,
        n_test_points=200,
        noise_sd=0.3,
        seed=2026,
    ):
        rng = np.random.default_rng(seed)
        x_grid = np.linspace(-np.pi, np.pi, n_test_points)
        truth = np.sin(x_grid)
        results = {}
    
        x_train_all = rng.uniform(
            -np.pi, np.pi, size=(repeats, n_train)
        )
        y_train_all = (
            np.sin(x_train_all)
            + rng.normal(
                0.0, noise_sd, size=(repeats, n_train)
            )
        )
        independent_test_noise = rng.normal(
            0.0,
            noise_sd,
            size=(repeats, n_test_points),
        )
        noisy_test_labels = (
            truth[None, :] + independent_test_noise
        )
    
        for degree in degrees:
            predictions = np.empty((repeats, n_test_points))
    
            for r in range(repeats):
                coefficients = np.polynomial.polynomial.polyfit(
                    x_train_all[r], y_train_all[r], deg=degree
                )
                predictions[r] = np.polynomial.polynomial.polyval(
                    x_grid, coefficients
                )
    
            assert predictions.shape == (repeats, n_test_points)
            assert np.isfinite(predictions).all()
    
            mean_prediction = predictions.mean(axis=0)
            bias2 = np.mean((mean_prediction - truth) ** 2)
            variance = np.mean(
                np.var(predictions, axis=0, ddof=0)
            )
    
            test_mse = np.mean(
                (predictions - noisy_test_labels) ** 2
            )
    
            decomposition_sum = noise_sd**2 + bias2 + variance
            results[degree] = {
                "noise": noise_sd**2,
                "bias2": bias2,
                "variance": variance,
                "test_mse": test_mse,
                "decomposition_sum": decomposition_sum,
                "difference": test_mse - decomposition_sum,
            }
    
        return results
    
    
    results = fit_polynomial_decomposition()
    for degree, values in results.items():
        print(degree, values)
    

    次数较低时,平均预测通常难以表示 \(\sin(x)\) 的弯曲规律,因此偏差平方可能较大;次数较高时,不同训练集拟合出的曲线可能变化较大,因此方差可能上升。difference 不必恰好等于 0,因为 test_mse 使用了有限次数的独立测试噪声;增加 repeats 后,它通常会更接近 0。若高次多项式出现很大的数值,应先检查输入范围和多项式计算的数值稳定性。

  9. 比较时,除 L2 正则化强度外,应保持训练集、验证集、特征构造、随机种子集合和训练方法相同。每个强度先在训练集上拟合,再在验证集上计算同一种误差指标。一般来说:

    • 正则化过弱时,训练误差可能很低,但训练—验证差距较大,说明模型容易受训练数据中偶然变化的影响;

    • 适度正则化通常会使训练误差略有上升,同时缩小训练—验证差距;

    • 正则化过强时,训练误差和验证误差都可能升高,说明参数被过度收缩,偏差较大。

    根据验证误差选择一个强度后,应保持方案不变,并只在测试集上评价这个最终模型。不能把所有候选强度的测试误差都拿来选择最优值,否则测试集就参与了超参数选择。

  10. 训练错误率第一次达到 0 的宽度是 16,而宽度 8 时已经只有 0.01,因此插值阈值大致位于宽度 8--16 附近。测试错误率从宽度 2 的 0.35 降到宽度 4 的 0.27,随后在宽度 8 上升到 0.41;继续增大宽度后,又从 0.41 下降到宽度 32 的 0.25。

    这条曲线包含“下降—上升—再次下降”,而不是达到一个最低点后持续上升的单一 U 形曲线。表格只能说明这组宽度和这次实验中出现了类似模型规模双下降的形态,不能据此断言更宽的模型在其他数据、其他噪声水平或其他训练方法下一定更好。

  11. 一个可靠的实验流程如下:

    1. 事先确定训练集、验证集、测试集、随机种子集合、优化方法、学习率范围和每个模型的最大训练轮数;

    2. 选择一组由小到大的网络宽度,只改变宽度,记录相同训练轮数下的训练误差和验证误差,得到模型规模曲线;

    3. 选择一个能够把训练误差降到接近 0 的较宽模型,在固定宽度下记录不同训练轮数的训练误差和验证误差,得到训练时间曲线;

    4. 对多组随机种子重复实验,报告平均曲线和波动,不能只选择最像双下降的一次结果;

    5. 根据验证结果确定网络宽度、训练轮数和正则化设置,保持方案不变,再使用测试集评价一次。

    若宽度曲线出现“验证误差先降、在训练误差接近 0 的区域上升、随后再次下降”,可以称为模型规模双下降的经验证据。若固定宽度后,验证误差随训练轮数呈现类似形态,可以称为训练时间双下降的经验证据。

    增加训练数据通常能降低估计波动,但也可能改变模型相对于插值阈值的位置;增加观测标签噪声往往会使临界区域更不稳定;适当的权重正则化、数据增强或提前停止可能减弱峰值。以上影响都需要在其他条件相同的情况下分别比较,不能只凭一条曲线确定原因。