🏠 总目录📚 本教程 挑战B · 四种解法对决
📑 本页目录(点开跳转)

挑战项目 B · 四种解法对决

4–6 天 | 难度 ★★★★☆ | 前置:第 2–6、15–16 章


🎯 为什么选这个项目

第 2 章说了「没有免费的午餐」,但那只是一句话。 这个项目让你亲手把它变成一张数据表——从此选型不再靠感觉。

   同一批数据,四种解法正面对决:
   ① 线性模型(逻辑回归/岭回归)
   ② 树模型(LightGBM / GBDT)
   ③ 神经网络(MLP)
   ④ 预训练模型微调(如果数据是文本/图像)

   ×  在【三种不同规模的数据量】上各跑一遍
      (100 行 / 1000 行 / 全量)

   → 你会得到一张【什么时候该用什么】的决策表
     这张表比任何博客的"经验之谈"都可靠,因为是你自己测的

这个项目训练的是选型判断力 —— 工程师最值钱、也最难自学的能力。

🔑 它同时是一个理论的实证检验数学原理第 11 章 NFL"算法的专长是守恒的"——一个模型在某类问题上变强,必然在另一类上变弱。 这个项目就是把那句话画成一张交叉的曲线图。


🧭 开工前:一个能省你两天的建议

   ❌ 常见的做法:先跑线性模型,跑完再跑树,跑完再跑NN……
      → 跑到第三天发现实验函数有 bug,前面全白干

   ✅ 正确的做法:Day 1 只做一件事——
      让【4 个模型 × 1 个数据量 × 1 个数据集】跑通,哪怕分数很烂
      → 确认框架没问题,再去填满整个矩阵 ⭐

这就是"先跑通全流程"在实验项目上的版本。


📊 实验设计

数据集(选 2–3 个,覆盖不同类型)

类型 推荐数据集 获取
表格·分类 Adult 收入预测 / Titanic fetch_openml("adult")
表格·回归 California Housing fetch_california_housing()
文本·分类 20 Newsgroups fetch_20newsgroups()
图像·分类 CIFAR-10 子集 torchvision.datasets

💡 至少要有一个表格数据集和一个非表格数据集——结论会完全不同,这正是重点。

实验矩阵

                100 行    1000 行    全量
   线性模型       ?          ?         ?
   树模型         ?          ?         ?
   神经网络       ?          ?         ?
   预训练微调     ?          ?         ?

   每格记录:CV 分数 ± 标准差 / 训练时间 / 调参耗时

🧠 ADHD 任务切分

第一阶段:搭实验框架(Day 1)⭐ 先把架子搭好,后面全是填空

第二阶段:跑满矩阵(Day 2–3)

第三阶段:深挖差异(Day 4)—— 项目的精华

第四阶段:产出决策表(Day 5–6)


🔨 实验框架骨架

import time, numpy as np, pandas as pd
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.pipeline import Pipeline

RESULTS = []

def run_experiment(name, pipeline, X, y, n_samples=None, seeds=(0,1,2)):
    """统一实验入口 —— 所有对比都必须走这个函数,保证公平"""
    if n_samples:
        idx = np.random.RandomState(0).choice(len(X), n_samples, replace=False)
        X, y = X[idx], y[idx]
    scores, t0 = [], time.time()
    for s in seeds:
        cv = StratifiedKFold(5, shuffle=True, random_state=s)
        scores.extend(cross_val_score(pipeline, X, y, cv=cv, scoring="roc_auc"))
    rec = dict(model=name, n=len(X), mean=np.mean(scores),
               std=np.std(scores), secs=time.time()-t0)
    RESULTS.append(rec)
    print(f"{name:<20} n={len(X):<7} {rec['mean']:.4f} ± {rec['std']:.4f}"
          f"  ({rec['secs']:.1f}s)")
    return rec

# 用完导出
# pd.DataFrame(RESULTS).to_csv("results.csv", index=False)

🕳️ 专属坑

说明
调参预算不公平 最容易毁掉整个结论。给每个模型相同的调参次数或时间
忘了测噪声底线 没有基准方差,你无法判断 0.005 的差距是不是真的
小数据上只跑一次 100 行数据的方差极大,必须多种子多折
预处理没进 Pipeline 第 5 章那个 76.5% 的教训
只比分数不比成本 训练慢 10 倍换 0.2% 提升,工程上往往不划算
数据集选得太单一 全是表格数据的话,你只会得出"树模型最强"这个片面结论
小数据用了不同的子集 100 行的那一格如果每个模型抽的是不同 100 行,比较无效。固定抽样种子
文本/图像给树模型的输入不合理 把 TF-IDF 直接喂 LightGBM 可以,但别拿原始像素喂它再说"树模型不行"

⚖️ 「调参预算公平」具体怎么保证

这是本项目最容易被质疑、也最值得写进 README 的一点。三种做法:

做法 说明 推荐度
等次数 每个模型都随机搜 30 组 ⭐ 最简单,够用
等时间 每个模型都给 10 分钟调参预算 更公平,但结果依赖机器
都用默认参数 谁都不调 也是一个有效的对比维度 ⭐
from sklearn.model_selection import RandomizedSearchCV
BUDGET = 30                                    # ⭐ 所有模型共用这一个数字
search = RandomizedSearchCV(pipe, param_dist, n_iter=BUDGET,
                            cv=cv, scoring="roc_auc", random_state=0)

💡 "都用默认参数"这一列很有信息量: 它回答了「开箱即用哪个最强」——而在真实工作里, 你常常没有时间给每个模型调 30 组参数。


✅ 通关标准

  1. 完整的实验矩阵(4 模型 × 3 数据量 × 至少 2 个数据集),每格带 ± 标准差
  2. 测过噪声底线,并用它判断哪些差距是真实的
  3. 调参预算公平,且在 README 里说明了怎么保证的
  4. 画出「数据量 vs 分数」四条曲线,能指出交叉点并解释原因
  5. 产出你自己的选型决策树
  6. 记录了至少 3 个「和预期不同」的发现

🏆 加分


💡 预期你会发现的(做完再看,别剧透自己)

👀 点开有剧透

✅ 检查点

  1. 这个项目和哪条理论直接对应?它把那条理论变成了什么?
  2. Day 1 该做什么?为什么不是"先把线性模型跑完"?
  3. 为什么必须先测噪声底线?没测会怎样?
  4. 「调参预算公平」有哪三种做法?为什么"都用默认参数"这一列有价值?
  5. 小数据那一格最容易犯什么错?
  6. 为什么必须至少有一个非表格数据集?
  7. 「成本也是维度」是什么意思?举一个例子。
  8. 四条曲线的交叉点说明了什么?
👀 答案
  1. 对应 NFL「算法的专长是守恒的」——一个模型在某类问题上变强必然在另一类上变弱。这个项目把那句话画成了一张交叉的曲线图
  2. 让 4 个模型 × 1 个数据量 × 1 个数据集先跑通,哪怕分数很烂。因为如果先跑完一整列才发现实验函数有 bug,前面全白干。
  3. 因为没有基准方差你无法判断 0.005 的差距是不是真的。同一配置跑 5 个种子记下标准差,之后所有比较都以它为尺子。
  4. 等次数(都搜 30 组,最简单够用)、等时间(更公平但依赖机器)、都用默认参数。第三种有价值是因为它回答了「开箱即用哪个最强」——真实工作里你常常没时间给每个模型调 30 组。
  5. 每个模型抽的是不同的 100 行——这样比较无效。必须固定抽样种子。而且 100 行的方差极大,必须多种子多折。
  6. 因为全是表格数据的话,你只会得出"树模型最强"这个片面结论排名会随数据类型改变,这正是 NFL 的可见证据。
  7. 训练时间和调参耗时也要记进表。例子:训练慢 10 倍换 0.2% 提升,工程上往往不划算——有时第二名才是正确选择。
  8. 说明不同数据量下的最优模型不同——小数据上归纳偏置强的模型(线性/树)赢,大数据上偏置弱的(NN)赢。交叉点就是你的选型分界线。

🛑 可以停在这里

走神救援

四种解法(线性/树/NN/预训练微调) × 三种数据量 × 至少两类数据集,跑满实验矩阵得出自己的选型决策表。⭐ 它是 NFL「算法的专长守恒」的实证版——把那句话画成一张交叉曲线图Day1 只做一件事:让 4×1×1 先跑通(别先跑完一整列再发现框架有bug)。铁律:①统一实验函数保证公平②先测噪声底线(没有基准方差就判断不了0.005是不是真的)③调参预算必须相当——等次数/等时间/都用默认参数(这列回答"开箱即用哪个最强",很有价值) ④预处理进Pipeline ⑤小数据要固定抽样种子,否则各模型抽的不是同一批行 ⑥成本也是维度(慢10倍换0.2%不值,第二名常是正确答案) ⑦必须有非表格数据集否则只会得出"树模型最强"的片面结论。精华在第三阶段:画数据量vs分数四条曲线找交叉点——那就是你的选型分界线

下一个挑战 👉 20-挑战项目C-过拟合实验室.md

打卡记录保存在你的浏览器里,首页能看到总进度