第 02 章 · 课程地图
这一章要解决什么:32 章从哪读起、哪些是重点、卡住了回看哪一章。
最容易踩的坑:把这本书当"特征清单"读。 它不是"给你 20 个特征公式",而是教你判断一个特征值不值得做。 只抄公式不看判断方法,换一份数据就失效了。
本章你需要完成的代码:无(这一章是地图,不用敲代码)
2.1 全书一张图
上一层:监督学习基础(另一本书)
┌──────────────────────────────────────┐
│ X/y 切分 · 四个指标 · 按实体划分 │
│ 交叉验证 · 树/森林/提升 · 正则化 │
└──────────────────────────────────────┘
↓ 本书从这里开始
┌──────────────────────────────────────────────────────────────┐
│ A 视角转变(01–04) │
│ 为什么横截面特征到顶了 · 模型只看到一行 │
└──────────────────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────────┐
│ B 造时序特征(05–10) ★ 本书第一个重点 │
│ 滑动窗口 · 分组与排序 · 冷启动 NaN · 差分斜率 · 滚动统计 │
│ 构造纪律 │
└──────────────────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────────┐
│ C 让特征能用(11–16) │
│ 缩放 · 编码 · ColumnTransformer · 特征选择 │
│ 消融实验 · 特征账本 │
└──────────────────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────────┐
│ D 泄漏专题(17–22) ★★ 全书重心 │
│ 三种泄漏 · 亲手做出 R²=1.000000 · 防泄漏检查清单 │
└──────────────────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────────┐
│ E 别过拟合(23–27) │
│ 过拟合的形状 · 早停 · 正则化 · 调参 · 调参的收益上限 │
└──────────────────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────────┐
│ F 集成与收口(28–32) │
│ 多窗口平均 · 模型融合 · ❖ 阶段目标 · 从清单到流程 │
└──────────────────────────────────────────────────────────────┘★ 图例(两个符号含义不同,别混)
| 符号 | 含义 |
|---|---|
| ★★ | 全书重心:第 17–22 章的泄漏专题。如果只读一部分,读它。 |
| ★ | 该组内的重点章:这组的知识主要靠它承载 |
| ◆ | 补充章:源课程里没有独立步骤,是本书为"讲通"而补的 |
分界线在 C 组和 D 组之间:
A + B + C = 怎么造出好特征("加法")
D = 怎么识别假特征("减法") ← 更值钱为什么"减法"更值钱:造一个特征的成本是几分钟,但用错一个特征的代价是上线后失效。 这本书把最多的篇幅给了"怎么发现自己在骗自己"。
2.2 32 章逐章清单
A 视角转变(01–04)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 01 | 环境与数据准备 | 三层数据、校验和、自检脚本 | |
| 02 | 课程地图 | 这一章(依赖关系与读法) | |
| 03 | 为什么横截面特征到顶了 | 三个收益的量级对比 | |
| 04 | 信息结构:模型只看到一行 | ◆ | "特征"到底是什么 —— 模型只看到一行数字 |
B 造时序特征(05–10)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 05 | 滑动窗口:把一段曲线压成几个数 | ★ | 窗口 = 采样;rolling 的三个默认语义 |
| 06 | rolling 的分组与排序 | 跨设备串线 —— 最危险的静默错误 | |
| 07 | 冷启动 NaN 与 dropna 的代价 | 为什么 fillna(0) 比丢行更毒 | |
| 08 | 差分与斜率 | 绝对值说"多健康",变化量说"往哪走" | |
| 09 | 滚动统计与极差 | 极差作为稳定性指标 | |
| 10 | 特征构造的纪律 | ◆ | 统一判据:预测这一刻,我拿得到吗 |
C 让特征能用(11–16)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 11 | 缩放:让系数可比 | ★ | Standard vs MinMax;"缩放提精度"的真因 |
| 12 | 类别编码 | 为什么 Label 编码会误导线性模型 | |
| 13 | ColumnTransformer | ◆ | 把数值列与类别列的处理合成一个预处理器 |
| 14 | 特征选择:相关性与 k 曲线 | 冗余怎么识别 | |
| 15 | 消融实验 | ★ | 逐组拿掉重训 —— 把"重要"变成数字 |
| 16 | 特征账本 | ◆ | 给每列记账(交付物) |
D ★★ 泄漏专题(17–22)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 17 | 三种泄漏总览 | ◆ | 划分 / 预处理 / 特征;统一判据 |
| 18 | 泄漏①:划分泄漏 | ★★ | 按行随机为什么会虚高 |
| 19 | 泄漏②:预处理泄漏 | ★★ | Pipeline 的真正意义 |
| 20 | 泄漏③:特征泄漏 | ★★ | 未来信息;cycle_frac 这类钩子 |
| 21 | 亲手做出 R² = 1.000000 | ★★ | 高潮:一列 soh − 0.80 就能骗过所有人 |
| 22 | 防泄漏检查清单 | ★★ | 交付物;从清单到流程卡点 |
E 别过拟合(23–27)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 23 | 过拟合的形状 | 训练涨、验证不涨 —— 怎么分辨真假 | |
| 24 | 早停 | 训练停在合适的位置 | |
| 25 | 正则化:L1 / L2 / 树深度 | 三种"刹车"分别刹在哪 | |
| 26 | 超参搜索 | GroupKFold + 网格/随机搜索 | |
| 27 | 调参的收益上限 | ◆ | 为什么调参只涨千分之几 |
F 集成与收口(28–32)
| 章 | 标题 | 记号 | 你会学到 |
|---|---|---|---|
| 28 | 多窗口平均 | 不同回看窗口;共同测试集口径 | |
| 29 | 模型融合 | 权重必须用验证集定 | |
| 30 | ❖ 阶段目标:精度优化报告 | ★ | 一条命令产出完整报告 |
| 31 | 从清单到流程卡点 | ◆ | 让纪律真正生效 |
| 32 | 下一本:从离线到在线 | ◆ | 还有什么没解决 |
2.3 依赖关系:哪些章不能跳
硬依赖(跳了会看不懂):
05 滑动窗口 ──→ 06 分组排序 ──→ 07 冷启动 NaN
│
├──→ 08 差分斜率
└──→ 09 滚动统计 ──→ 10 构造纪律
│
↓
17 三种泄漏总览
│
┌─────────────────────────┼─────────────────────────┐
↓ ↓ ↓
18 划分泄漏 19 预处理泄漏 20 特征泄漏
│
↓
21 亲手做出 1.000000
│
↓
22 防泄漏检查清单关键依赖说明:
| 依赖 | 为什么不能跳 |
|---|---|
| 05 → 06 | 05 讲 rolling 的语义,06 讲"忘了分组会怎样" —— 先懂语义才看得懂错误的可怕 |
| 10 → 17 | 10 提出统一判据"预测这一刻拿得到吗",17 把它扩展成三种泄漏的分类 |
| 11 → 19 | 19 的预处理泄漏要用到 11 讲的缩放与 Pipeline |
| 16 → 22 | 22 的清单复用 16 的"特征账本"格式 |
| 15 → 27 | 27 用 15 的消融方法论证"调参收益上限" |
软依赖(跳了会少一层理解,但不影响读下去):
03 三个收益量级 ──→ 决定你要不要读 C、E 两组
04 信息结构 ──→ 理解 05 为什么"窗口"这个动作有意义
12 编码 ──→ 13 ColumnTransformer 会顺带复习2.4 时间不够怎么读
四条路线,按可用时间选。
路线 1:只有 3 小时 —— 读"最贵的 3 章"
03(为什么到顶了)→ 15(消融实验)→ 21(亲手做出 1.000000)为什么是这三章:
03 告诉你【该往哪改进】
15 告诉你【怎么判断一个特征值不值得做】
21 告诉你【分数可以完全骗过你】
↓
三章合起来 = 特征工程的完整世界观,不需要写代码路线 2:有一天 —— 加技能组
路线 1 + 05(滑动窗口)+ 06(分组排序)+ 18(划分泄漏)+ 20(特征泄漏)这五章加上路线 1 的三章,就是特征工程的 80%。
路线 3:有一周 —— 按 B + D 两组走
05 → 06 → 07 → 08 → 09 → 10 (B 组:怎么造)
13 → 14 → 15 → 16 (C 组:怎么判断)★ 15 必读
17 → 18 → 19 → 20 → 21 → 22 (D 组:怎么不骗自己)★★ 全组必读跳掉 01/02(自己看环境)、11/12(上一本讲过)、23–29(诊断与调参)、30–32(收口)。
路线 4:按顺序全读(推荐)
每一章都依赖前面建立的口径,尤其是"只含历史"这条纪律贯穿全书。
点开:每章的"最小可读单元"是什么?
如果你时间极度碎片化,可以从任何一章的这个部分开始:
| 部分 | 价值 | 适合什么时候读 |
|---|---|---|
| 开头「这一章要解决什么」 | 判断这一章要不要读 | 挑选章节时 |
| 「可运行示例」+ 真实输出 | 核心内容 | 有时间动手时 |
| 「常见坑」 | 速查表 | 遇到问题时 |
| 「本章练习」 | 检验理解 | 学完一章后 |
| 「面向工程实践」 | 怎么用 | 准备落地时 |
★ 如果只有 10 分钟:读开头 + 「常见坑」。 常见坑是每章信息密度最高的部分 —— 它直接列出"你会怎么错"。
★ 如果想深入:先自己做练习,再点开答案对照。
一个具体建议:
读第 06 章(分组与排序)时:
① 先看开头("最危险的静默错误")
② 直接跳到「常见坑」,看那三行错误的代码
③ 再回头读「可运行示例」,看它错得到底多离谱(0.8123 vs NaN)
④ 最后做练习这个"先看坑、再看原理"的顺序,在读"常见错误"类章节时比顺序读更有效。
2.5 每条路线都会遇到的三条纪律
这三条纪律在全书反复出现。贴在这里,卡住时回看。
纪律一:口径比代码重要
# ❌ 含当前行 —— 特征里混进了当前行的标签
df["soh_win_mean5"] = g["soh"].transform(lambda s: s.rolling(5).mean())
# ✅ 只含历史 —— shift(1) 把当前行推出去
df["soh_win_mean5"] = g["soh"].transform(lambda s: s.shift(1).rolling(5).mean())记住这三件事的顺序:
① 先按(实体, 时间)排序 sort_values(["cell_id", "cycle"])
② 再按实体分组 groupby("cell_id")
③ 最后只含历史 shift(1) 之后才 rolling任何一步漏掉,结果都错,而且不报错。
纪律二:分数不是判据
本书里有三次"分数不提醒你"的实测:
① 忘了分组 → 特征值错了,分数几乎没变
② fillna(0) 代替 dropna → 线性模型掉 0.056,树模型却无感
③ 加一列 soh − 0.80 → R² 恰好 1.000000所以:
不要用"分数没变"证明"我没写错"。 要用结构检查(值域、NaN 数、量纲、恒等关系)来证明。
纪律三:信息上限由特征决定,不由超参决定
第 27 章会看到:调参后测试 R² 反而【略降】
↓
为什么?因为特征已经把可预测性吃到 0.999
调参能动的只有千分之几
↓
推论:分数卡住时,先问"特征里还有信息吗",而不是"参数调够了吗"2.6 常见坑
① 把这本书当"特征公式清单" → 它教的是判断方法,不是 20 个公式
② 跳过 05–06 直接做特征 → rolling 的语义没搞清,后面全是静默错误
③ 跳过 D 组(17–22) → 这是全书重心,跳了等于没读这本书
④ 只看"可运行示例"不看"常见坑" → 常见坑是信息密度最高的部分
⑤ 只读不做练习 → 特征工程是"手感",看懂和做对差很远
⑥ 记住结论但不记口径 → 换一份数据就失效★ 关于 ⑥
"用过去 5 个窗口的均值" 这句话本身是【不完整】的
↓
完整说法必须包含四个信息:
· 按什么分组(每支设备内)
· 排好序了吗(按循环次数升序)
· 含不含当前窗口(不含,用 shift(1))
· 窗口长度是多少(5 个窗口 ≈ 15 圈)
↓
【少一个,别人就无法复现你的特征】这也是第 16 章"特征账本"要解决的问题 —— 它强迫你把每个特征的口径写清楚。
2.7 完整示例与输出
本章不需要运行代码。
但建议现在就做一件事:确认你的数据包解压正确。
cd code
python check_env.py期望看到(节选):
✅ Python 版本:CPython 3.13.x
✅ numpy 2.5.x
✅ pandas 3.0.x
✅ matplotlib 3.11.x
✅ sklearn 1.9.x
✅ 数据文件:…/code/data/battery
cycle_raw.csv(共 3,767 KB,69,592 行含表头)
soh_features.csv(共 1,221 KB,21,240 行含表头)
soh_features_v2.csv(共 2,959 KB,21,240 行含表头)
cells.csv(60 支设备的真值)
⚠️ xgboost 未安装(可选)
✅ 全部通过。下一步:从第 03 章开始,把代码敲进 demos/ 里跑起来。如果这一步没通过,先回第 01 章。
本章练习
练习 1:找出你该读的路线
根据你的可用时间,从 2.4 节的四条路线里选一条,然后回答:
- 你选哪条?为什么?
- 这条路线里,哪一章是你最需要的?
- 有没有哪一章是"我暂时不需要,但以后一定会回来读"的?
参考答案
没有标准答案 —— 这一题的目的是让你主动规划,而不是被动线性阅读。
一个示例回答(假设你是"有一天时间、已经做过特征工程"的人):
- 我选路线 2。我已经在项目里做特征,但分数总是卡住,说明问题不在"会不会写", 而在"判断得对不对"。
- 我最需要第 15 章(消融实验)。我现在的做法是"加一堆特征看分数涨没涨", 没有系统性地"逐组拿掉重训"。第 15 章会告诉我"加 10 列可能等于没加"。
- 第 22 章(防泄漏检查清单) 以后一定会回来 —— 因为它是交付物, 我要在每次上线前对着它过一遍。
★ 这个练习的真正价值
"哪一章我最需要" 这个问题逼你想清楚【你现在的瓶颈是什么】
↓
是"不会造特征" → 读 B 组
是"造了但不知道有没有用" → 读 C 组
是"分数高但不敢信" → 读 D 组(★ 最常见)
是"卡住了想调参" → 读 E 组
↓
【先定位瓶颈,再选路线】—— 而不是从第 01 章开始顺序读★ 一个反直觉的建议
如果你的分数已经很高(比如 R² > 0.99),最该读的是 D 组,不是 E 组。
R² = 0.999 时,你的第一反应可能是"再调调参挤到 0.9995"
↓
但更该问的是:"这个 0.999 是真的吗?"
↓
本书第 21 章会给你一个 1.000000 的真实例子 —— 而那完全是假的分数越高,越该怀疑。 这是本书最重要的一条元纪律。
练习 2:画出你自己的依赖图
本书的章节顺序是为教学设计的,不一定是你项目里的执行顺序。
请为你自己的一个真实项目,画出:
- 你现在的特征是从哪来的(原始数据 → 特征的过程);
- 这个过程里哪些步骤可能泄漏;
- 你会按什么顺序去做(不一定是本书的章号顺序)。
参考答案
示例(假设你在做一个"用户流失预测"项目):
① 特征来源
原始事件流(用户每天的行为日志,一行 = 一个事件)
↓ 按用户-天聚合
日粒度行为表(一行 = 一个用户一天)
↓ 滚动窗口
用户特征表(一行 = 一个用户,含过去 7/30/90 天的统计)② 可能泄漏的地方(对照本书三种泄漏)
| 本书的泄漏类型 | 我的项目里对应的风险 | 用本书哪一章的判据 |
|---|---|---|
| 划分泄漏 | 同一用户的多天数据跨训练/测试集 | 18 章:按用户划分,不是按行 |
| 预处理泄漏 | 先对全量用户算归一化统计量,再划分 | 19 章:fit 只能在训练集上 |
| 特征泄漏 | "距上次活跃天数"用了未来的登录记录 | 20 章:预测这一刻拿得到吗 |
★ 第 3 类是最需要小心的:
# ❌ 用了未来信息:这个"最后活跃距今"是从全量数据算的
user["days_since_last_active"] = (NOW - user["last_active_date"]).dt.days
# ✅ 对每个预测时点,只用那一刻之前的记录
def days_since_last_active_asof(events, asof_date):
past = events[events["date"] <= asof_date]
return (asof_date - past["date"].max()).days③ 我的执行顺序
① 先定"预测时点"(as-of date)—— 这是全书的统一判据
↓
② 按用户划分(不是按行)
↓
③ 构造只含历史的特征(shift / as-of join)
↓
④ 做消融,看哪一组真的值钱
↓
⑤ 写特征账本,标记每一列的"预测时刻可得性"
↓
⑥ 上线前过一遍防泄漏清单★ 与我不同的地方(关键)
本书的章号顺序:05→06→07→...→22
我项目的顺序: ①定判据 → ②划分 → ③特征 → ④消融 → ⑤账本 → ⑥清单
差别:我把"划分"(本书 18 章)放到了"特征"(本书 05–10 章)之前
↓
为什么?因为【划分方式决定了特征里能不能含跨实体信息】
先定划分,才不会白做一批用不上的特征★★ 这一题最重要的一句话
本书的章号是教学顺序,不是执行顺序。 在你的项目里,正确的顺序是:先定"预测时点",再定划分,最后做特征。
这个顺序错了,后面全部返工。
练习 3:找出本书"没讲"的东西
一本书的边界和它的内容一样重要。请列出至少三件这本书不会讲的事, 并说明"为什么它不讲"或"该去哪里学"。
参考答案
参考列表:
| 没讲的东西 | 为什么不讲 | 去哪学 |
|---|---|---|
| 按时间划分 vs 按实体划分的取舍 | 上一本第 09–12 章讲过;本书只引用 | 《监督学习实战》第 09–12 章 |
| 模型选型的四个维度 | 属于"选模型",不属于"造特征" | 《监督学习实战》第 26 章 |
| 深度学习的特征提取(CNN/Transformer 自动学特征) | 本书专注表格数据的经典特征工程;那是另一个领域 | 深度学习专门教材 |
| 流式/在线特征(特征实时计算) | 需要特征平台(Feature Store),是工程架构话题 | 第 32 章会指出这个缺口 |
| 标签质量与标注 | 本书假设"标签是对的";标签本身的问题另属一个专题 | 需另外学习 |
| 因果推断("改变 X 能不能影响 Y") | 预测任务不问因果;上一本第 20 章提过"相关≠因果" | 因果推断专门教材 |
| 图像/文本/语音的特征工程 | 那些是表示学习(representation learning)的领域 | 各领域的专门资料 |
★ 为什么"列出没讲的东西"是一个好练习
只知道"这本书讲了什么" → 你会误以为它覆盖了全部
↓
知道"它没讲什么" → 你才知道什么时候该去找别的资料
↓
【一本书的价值,一半来自它划清的边界】★ 其中一个缺口特别重要:在线特征
本书全程假设:数据是【静态的一张表】
↓
但真实生产环境是【流式的】:
特征要实时计算、历史要在线查得到、口径要一致(训练/服务一致)
↓
这就是"训练-服务偏差"(training-serving skew)的来源
↓
本书第 32 章会明确把这个缺口指出来,并说明它为什么是"下一本书"的主题★ 一个自我检验
如果你读完这本书,能对任何一个新项目说出:
① 我的预测时点是什么?
② 我按什么划分?
③ 每一列在预测时点拿得到吗?
④ 哪一组特征真的值钱(消融怎么说)?
⑤ 我凭什么相信这个分数(结构检查是什么)?那这本书的目的就达到了 —— 它教的就是这五个问题。
面向工程实践:把"路线"变成"团队规范"
① 这一章的地图不只给读者,也可以给团队
一个新同事加入你的建模项目:
↓
❌ "你先看看这些代码" → 他会花两周才明白为什么这样划分
✅ "先看这五章(03/15/18/20/22)" → 他三天就能明白项目的纪律
↓
【把书当入职材料,比写一份内部文档更省事,而且更完整】② 一个可以直接用的"特征工程 checklist 起点"
## 我的特征工程流程
### 第一步:定预测时点(对应第 04、10 章)
- [ ] 我在什么时刻做预测?(as-of date)
- [ ] 那一刻,每条记录的状态是什么?
### 第二步:定划分方式(对应上一本第 09–12 章)
- [ ] 我按什么划分?(按实体 / 按时间)
- [ ] 划分后,训练集和测试集的实体有交集吗?(必须为 0)
### 第三步:造特征(对应第 05–10 章)
- [ ] 先排序、再分组、只含历史
- [ ] 每个特征的口径写清了吗?(分组 / 排序 / 含不含当前 / 窗口长度)
### 第四步:验证特征价值(对应第 14–16 章)
- [ ] 相关性有没有冗余?
- [ ] 消融实验做了吗?哪一组真的值钱?
- [ ] 特征账本写了吗?
### 第五步:守泄漏(对应第 17–22 章)
- [ ] 三种泄漏都排查了吗?
- [ ] 防泄漏清单过了一遍吗?
### 第六步:知道何时停手(对应第 23–27 章)
- [ ] 学习曲线走平了吗?(走平 → 改特征,不要调参)★ 这份 checklist 的用法
不要把它当"打勾清单"(打完就完事)
↓
要把它当"卡点":每一步不通过就不进入下一步
↓
第 31 章会讲怎么把它真正变成一个【流程卡点】而不是一张纸③ 关于"该读多少"的一个诚实建议
这本书 32 章,全读需要 2~4 周(按每天 1 小时算)
↓
但【读完不是目标】—— 目标是"下次做特征时不再犯那三类错"
↓
所以更有效的做法是:
先读路线 2 的那 8 章
→ 立刻用在你手上的项目上
→ 遇到具体问题时再回来查对应的章
↓
【把书当工具,而不是当课程】