📑 本页目录(点开跳转)
14 · 辛普森悖论与七个陷阱
⏱ 40 分钟 | ⭐ 每一个都能让你得出完全相反的结论
🎯 一句话
数据不会说谎,但它会让你自己骗自己。 这一章是七个「结论看起来完全合理、但完全错误」的模式 —— 认出它们,比学任何新方法都值。
🔄 陷阱一:辛普森悖论 ⭐⭐
每个子群里 A 都比 B 好,合起来却是 B 比 A 好。
一个实算的例子(下面的数字是跑出来的,不是编的):
新算法 vs 旧算法,看转化率 分人群看:
| 人群 | 旧算法 | 新算法 | 谁更好 |
|---|---|---|---|
| 老用户 | 900/10000 = 9.00% | 190/2000 = 9.50% | 新 ✅ |
| 新用户 | 40/2000 = 2.00% | 220/10000 = 2.20% | 新 ✅ |
| 总体 | 940/12000 = 7.83% | 410/12000 = 3.42% | 旧 ⭐💀 |
💀 新算法在两个人群里都更好,总体却差了一倍多。
新算法在【两个人群里都更好】,总体却差了一倍多
为什么会这样:
老用户天然转化率高(9%),新用户天然低(2%)
流量分配:
· 老用户里,新算法只拿到 17% 的流量
· 新用户里,新算法拿到 83% 的流量 ⭐
→ 新算法的样本大量集中在"天然难转化"的新用户上
→ 总体平均被拖下来
🔑 根因:分组变量(新老用户)同时影响「分到哪个算法」和「结果」 —— 它是个混杂变量(第 13 章)。
⭐ 到底该信哪个?
❓ 分人群的结论 vs 总体的结论,哪个对?
⭐ 答案取决于【为什么流量分配不均】:
情况 A:流量分配是【随机】的,只是碰巧不均
→ 信【分人群】(要做分层加权)
情况 B:流量分配是【由某个机制决定】的
(比如新算法就是专门给新用户上的)
→ 要问清楚你到底想回答什么问题
💡 这也是为什么 A/B 实验要随机分流 + 要查 SRM(第 12 章): 随机分流从源头上避免了辛普森悖论。 一旦出现 SRM,就要警惕这类反转。
🛠️ 二十行代码:复现它,然后修好它
import pandas as pd
df = pd.DataFrame([
("老用户", "旧", 900, 10000), ("老用户", "新", 190, 2000),
("新用户", "旧", 40, 2000), ("新用户", "新", 220, 10000),
], columns=["人群", "算法", "转化", "曝光"])
df["转化率"] = df["转化"] / df["曝光"]
print(df.pivot(index="人群", columns="算法", values="转化率"))
# 新 旧
# 新用户 0.0220 0.0200 ← 新算法赢
# 老用户 0.0950 0.0900 ← 新算法赢
g = df.groupby("算法")[["转化", "曝光"]].sum()
print(g["转化"] / g["曝光"])
# 新 0.0342 ← 反过来了 💀
# 旧 0.0783
# ⭐⭐ 修法:分层加权(也叫标准化)—— 用【同一套人群权重】去加权两个算法
w = df.groupby("人群")["曝光"].sum() / df["曝光"].sum() # 各人群在总体中的占比
rate = df.pivot(index="人群", columns="算法", values="转化率")
print((rate.T * w).T.sum())
# 新 0.0585 ✅ 和分人群的结论一致了
# 旧 0.0550
⭐ 「分层加权」这四个字是这一章唯一的技术解法: 悖论的根源是两个算法各自的人群构成不同, 所以只要强制它们用同一套人群权重,反转就消失了。
⚠️ 但要注意:这只在「流量分配本可以是随机的」时才有意义。 如果新算法根本就是为新用户设计的,那么加权后的数字回答的是 「假如把它推给现有人群构成会怎样」——是不是你要的问题,要自己想清楚。
📉 陷阱二:幸存者偏差
「我们的付费用户满意度 4.8 分!」
→ 不满意的早就退款走了,根本不在样本里
「模型上线后用户投诉少了」
→ 可能是用户放弃投诉了
🔗 第 2 章的评估幸存者偏差是同一个东西的另一种形态: 你的样本是被某个过程筛选过的。
💀 它在建模里的重灾区:只能用「通过的人」训练
风控/信贷模型的死结:
被拒的申请人【没有"最后还没还款"这个标签】
→ 你只能用通过审批的那批人训练
→ 模型学到的是「在已通过的人里,谁会违约」
→ 但它上线后要判断的是【全部申请人】 💀
一个典型的量级:
· 通过率 30% 的场景,训练样本只覆盖了申请人分布的 30%
· 在这 30% 上离线 AUC 0.78
· 换成"全部申请人 + 事后补到的真实表现"重新评估 → 只有 0.66 ⭐
→ 掉的那 12 个点,全在「明显该拒、但模型从没见过」的那批人上
三个对策(按有效性排):
| 对策 | 说明 | 代价 |
|---|---|---|
| 随机放行一小撮 ⭐⭐ | 每天随机通过 0.5–2% 本该拒的申请 | 真金白银的坏账,但它是唯一的无偏样本 |
| 用外部数据补标签 | 征信、联合建模方的后续表现 | 覆盖不全、合规约束 |
| 把「被拒」当有信息的删失建模 | 而不是直接丢掉这些行 | 依赖假设,效果不如前两个 |
⭐ 注意第一条和第 7 章的随机流量是同一件事: 反馈闭环系统里,"花钱买一小块无偏数据"往往是最划算的一笔投资 —— 因为没有它,你连"模型在变好还是变坏"都无法判断。
🎢 陷阱三:均值回归 ⭐
现象:给「表现最差的 10% 用户」推送召回消息
→ 下个月他们的活跃度明显上升
→ 结论:推送有效!❌
真相:
「上个月表现最差」里有一部分是【偶然的低谷】
→ 即使什么都不做,他们下个月也会回到正常水平
⭐ 识别方法:看对照组。 如果你按"最差 10%"筛人,必须在这批人里再随机分成实验组和对照组 —— 只和"他们自己上个月"比,一定会高估效果。
💀 这个陷阱在「挽留」「召回」「唤醒」类项目里几乎必然出现。
一个能自己心算的数字:
假设某指标 = 真实水平 + 噪声,相邻两期的相关系数 ρ = 0.6
挑出「第一期最低的 10%」这批人,
他们第二期的平均值会自动回升 —— 回升幅度约等于
【挑选时偏离均值的 (1 − ρ) 倍】= 40% ⭐
→ 你什么都不做,也能报告一个"活跃度提升 40%"的成功项目
⭐⭐ 最阴险的一点:样本量越大,这个假效果的 p 值越小。 很多人以为「p < 0.001 总不会错了吧」—— p 值只否定「这是随机波动」,它从不证明「这是你的干预造成的」。 均值回归造成的差异是系统性的,不是随机的,所以它一定显著。
⏱️ 陷阱四:前视偏差(用了当时拿不到的信息)
回测策略时用了「当天收盘价」来做当天早上的决策
→ 回测收益爆表,实盘亏损
🔗 这是第 4 章特征穿越在分析场景的形态。 凡是「回测/复盘」类分析,都要问一句:这个数字在决策时点真的存在吗?
📊 陷阱五:只看相对值 / 只看绝对值
「转化率提升 50%!」
→ 从 0.02% 涨到 0.03%,实际多了 3 个订单 😐
「多了 500 个订单!」
→ 总量 50 万,相对提升 0.1%,在噪声范围内 😐
⭐ 规则:永远同时报【相对值 + 绝对值 + 置信区间】
🧮 陷阱六:比率的陷阱
① 比率的平均 ≠ 平均的比率
两个城市的 CTR:10% 和 20%
❌ 平均 CTR = 15%
✅ 要按曝光量加权
如果城市 A 有 100 万曝光(10%),城市 B 有 1 万(20%)
→ 真实 CTR ≈ 10.1%,不是 15%
② 分母变化伪装成分子变化 ⭐
CTR 跌了 → 可能是点击少了,也可能是曝光暴涨
⭐ 看比率时永远同时看分子和分母
🔗 第 11 章排查第一步就查这条。
🎯 陷阱七:指标被优化后就失效了(古德哈特定律)⭐⭐
「当一个指标成为目标,它就不再是一个好指标。」
用「停留时长」当目标
→ 模型学会推容易让人反复刷但没价值的内容
→ 时长涨了,用户满意度和留存反而降了
用「点击率」当目标
→ 标题党
三个对策:
| 对策 | 说明 |
|---|---|
| 加护栏指标 ⭐ | 主指标涨的同时,这些不能掉(留存、投诉率、多样性) |
| 多目标 | 同时优化几个互相制衡的目标 |
| 定期换/校准指标 | 指标用久了会被"学会",要定期回头验证它还代表价值吗 |
🔗 强化学习第 1 章的奖励黑客是同一个现象的 RL 版本: 模型会忠实地优化你写下的那个东西,而不是你想要的那个东西。
💀 一个不涉及模型、但更能说明问题的案例
指标:客服「一次解决率」(FCR)—— 一通电话内解决问题的比例
动作:把它定成团队 KPI,要求 ≥ 85%
人(和模型一样)很快学会了怎么优化它:
· 没解决的问题【不建工单】,让用户过会儿再打一次
· 第二通电话是一张全新的单,第一通就"解决"了 💀
结果:
· FCR 从 71% 涨到 89% ✅ KPI 达成
· 同期投诉量涨了 34% 💀
· 三个月后才有人发现 ——
因为【没有任何一张图把 FCR 和投诉量放在一起】⭐
⭐⭐ 这个案例给出了古德哈特定律真正的解药: 不是"找一个更好的指标"(不存在),而是—— 把主指标和护栏指标画在同一张图上、同一个看板上、同一个周报里。
💡 判断标准很朴素:如果一个指标涨了,没有任何机制会让你顺便看到代价, 那它迟早会被优化到失效。这和模型无关,是激励结构的问题。
📋 一张自查表
看到任何一个「结论」时,问这七句:
[ ] 分人群看还成立吗? (辛普森)⭐
[ ] 样本是怎么来的、谁被筛掉了?(幸存者)
[ ] 有对照组吗? (均值回归)⭐
[ ] 这些数据在决策时点存在吗? (前视)
[ ] 相对值和绝对值都看了吗?
[ ] 分母变了吗? (比率)⭐
[ ] 这个指标被优化后还代表价值吗?(古德哈特)⭐
⭐ 三个带星的是最高频的。如果只记三条,记它们。
⚠️ 一张坑表(自查表的「怎么修」版)
| 坑 | 后果 | 怎么修 |
|---|---|---|
| 只看总体,不分人群 ⭐ | 辛普森反转:新方案两个人群都赢,总体却输 | 默认按 3–5 个维度出分组表 |
| 分了人群,但各用各的权重 | 还是不可比,只是错得更隐蔽 | 分层加权:用同一套人群权重 ⭐ |
| 挑极端组做干预,和它自己上期比 ⭐ | 均值回归伪装成效果,ρ=0.6 时白送 40% 的"提升" | 在极端组内部再随机分对照组 |
| 拿「显著」当因果的证据 💀 | 大样本下伪效应必然显著 | p 值只否定随机,不证明因果 |
| 只用通过筛选的样本训练/评估 | 幸存者偏差:离线 0.78 → 全量 0.66 | 花钱买一小块随机放行样本 ⭐ |
| 回测用了当时不存在的数据 | 回测收益爆表,实盘亏损 | 每个特征标注「可用时间」,回测按它裁剪 |
| 只报相对提升 | 「提升 50%」实际是 3 个订单 | 相对 + 绝对 + 置信区间三件套 |
| KPI 只考核单一指标 💀 | 古德哈特:指标涨、业务跌,还要三个月才发现 | 主指标和护栏指标画在同一张图上 ⭐⭐ |
| 代理指标定下来就不再验证 | 关系漂移后,你在优化一个不再代表价值的东西 | 定期重验(第 15 章) |
🔗 和站内其他章的关系
| 相关的地方 | 和这一章的关系 |
|---|---|
| 第 2 章幸存者偏差 | 陷阱二 |
| 第 4 章特征穿越 | 陷阱四 |
| 第 8 章分人群告警 | 陷阱一的监控形态 |
| 第 11 章看分母 | 陷阱六 |
| 第 12 章 SRM | SRM 是辛普森的预警信号 |
| 强化学习 01奖励黑客 | 陷阱七的 RL 版 |
✅ 检查点
- 用那个实算例子说明辛普森悖论。为什么会发生?
- 辛普森悖论出现时,该信分人群还是总体?技术上怎么修?修完的数字是多少?
- 随机分流和 SRM 检查与辛普森悖论是什么关系?
- 风控模型为什么必然有幸存者偏差?那个 AUC 的数字是多少?三个对策里哪个最有效、代价是什么?
- 均值回归怎么骗人?ρ=0.6 时白送多大的"提升"?为什么 p 值保护不了你?
- 比率的两个陷阱是什么?
- 古德哈特定律说什么?用那个 FCR 的案例说明。真正的解药是什么?
- 自查表里最高频的三条是哪三条?
👀 答案
- 新算法在老用户(9.50% vs 9.00%)和新用户(2.20% vs 2.00%)两个人群都更好,总体却是 3.42% vs 7.83%,旧的赢。因为老用户天然转化率高(9%)、新用户低(2%),而新算法 83% 的流量落在新用户上,被拖下来了。
- 取决于流量分配不均的原因:如果是随机的、只是碰巧不均 → 信分人群;如果是由某个机制决定的 → 要先问清你到底想回答什么问题。技术解法是分层加权(标准化):用同一套人群权重去加权两个算法。修完是 新 0.0585 vs 旧 0.0550,新算法赢,和分人群结论一致。
- 随机分流从源头避免了辛普森悖论(分组变量不再影响分到哪一组);SRM 一旦出现就要警惕这类反转——它说明分流不随机了。
- 因为被拒的申请人没有"最后还没还款"这个标签,只能用通过审批的人训练,而上线后要判断的是全部申请人。数字:通过率 30% 的场景,离线 AUC 0.78,换成全部申请人重新评估只有 0.66,掉的 12 个点全在「明显该拒、模型从没见过」的人身上。最有效的对策是每天随机放行 0.5–2% 本该拒的申请,代价是真金白银的坏账——但它是唯一的无偏样本。
- 挑"表现最差的 10%"做干预,他们下月自然会回升(偶然低谷),会被误认为干预有效。ρ=0.6 时回升幅度约等于挑选时偏离均值的 40%——什么都不做也能报一个"提升 40%"。识别:必须在这批人里再随机分实验组和对照组。p 值保护不了你,因为均值回归造成的差异是系统性的、一定显著;p 值只否定"这是随机波动",从不证明"这是你的干预造成的",而且样本越大 p 越小。在挽留/召回/唤醒类项目里几乎必然出现。
- ①比率的平均不等于平均的比率(要按分母加权)②分母变化伪装成分子变化(CTR 跌可能是曝光暴涨)。
- 当一个指标成为目标,它就不再是好指标。案例:把客服「一次解决率 FCR」定成 KPI,客服学会把没解决的问题不建工单、让用户再打一次——第二通是新单,第一通就"解决"了;FCR 从 71% 涨到 89%,同期投诉量涨 34%,三个月后才被发现,因为没有任何一张图把 FCR 和投诉量放在一起。真正的解药不是"找一个更好的指标"(不存在),而是把主指标和护栏指标画在同一张图/看板/周报里——如果一个指标涨了却没有任何机制让你顺便看到代价,它迟早会被优化到失效。
- 辛普森(分人群看还成立吗)、均值回归(有对照组吗)、分母变了吗。(外加古德哈特也是高频。)
🛑 可以停在这里
⚡ 走神救援
⭐⭐辛普森悖论:新算法在老用户 9.50%>9.00%、新用户 2.20%>2.00% 两个人群都赢,总体却 3.42% vs 7.83% 大输——因为老用户天然转化高而新算法 83% 流量落在新用户上。根因是分组变量同时影响"分到哪组"和"结果"(混杂变量);⭐该信哪个取决于流量为什么不均;随机分流从源头避免它,SRM 是它的预警信号。陷阱二幸存者偏差(不满意的早走了)。⭐陷阱三均值回归:挑"最差10%"做召回,他们下月自然回升 → 唯一可靠识别是在这批人里再随机分对照组,在挽留/召回类项目里几乎必然出现。陷阱四前视偏差(回测用了当时拿不到的数)。陷阱五:永远同时报相对值+绝对值+置信区间("提升50%"可能只是3个订单)。陷阱六比率:比率的平均≠平均的比率(要按分母加权)、⭐分母变化伪装成分子变化。⭐⭐陷阱七古德哈特:当指标成为目标就不再是好指标(优化停留时长→推让人反复刷但没价值的内容)→ 加护栏指标、多目标、定期校准;这是强化学习「奖励黑客」的产品版。自查表最高频三条:分人群还成立吗、有对照组吗、分母变了吗。 ⭐辛普森的技术解法是分层加权:用同一套人群权重加权两个算法,上面那组数就从「旧赢」变回「新 0.0585 vs 旧 0.0550」,和分人群一致。💀幸存者偏差在建模里的重灾区是风控:被拒的人没有标签,只能拿通过的人训练,离线 AUC 0.78、换成全部申请人重新评估只有 0.66 —— 掉的 12 个点全在"明显该拒、模型从没见过"的人身上;最有效的解法是每天随机放行 0.5–2%(要付真金白银的坏账,但它是唯一无偏的样本,和第 7 章的随机流量是同一件事)。⭐均值回归有个能心算的数字:相邻两期相关系数 ρ=0.6 时,挑"最低 10%"做干预,下期自动回升约等于挑选时偏离均值的 40% —— 什么都不做也能报一个成功项目;⭐⭐而且样本越大 p 值越小,因为均值回归是系统性的不是随机的,p 值只否定"随机波动",从不证明"是你的干预造成的"。💀古德哈特的真实案例:客服「一次解决率」定成 KPI 后,客服学会不建工单让用户再打一次(第二通是新单,第一通就"解决"了)→ FCR 从 71% 涨到 89%、投诉量同期涨 34%,三个月没人发现,因为没有任何一张图把两者放在一起;⭐⭐解药不是找更好的指标(不存在),而是把主指标和护栏指标画在同一张图上。
下一节 👉 15-长期效应与代理指标.md