🏠 总目录📚 本教程 14 · 辛普森悖论与七个陷阱
📑 本页目录(点开跳转)

14 · 辛普森悖论与七个陷阱

40 分钟 | ⭐ 每一个都能让你得出完全相反的结论


🎯 一句话

数据不会说谎,但它会让你自己骗自己。 这一章是七个「结论看起来完全合理、但完全错误」的模式 —— 认出它们,比学任何新方法都值。

旧算法新算法9%2%7.8%3.4%老用户 ↑新用户 ↑总体 ↓两个子群都在涨,合起来却在跌
两条绿线是两个子群,都在上升;橙线是总体,却在下降。⭐ 原因不在数字本身,在流量分配:新算法 83% 的样本落在了天然难转化的新用户上。

🔄 陷阱一:辛普森悖论 ⭐⭐

每个子群里 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 版

✅ 检查点

  1. 用那个实算例子说明辛普森悖论。为什么会发生?
  2. 辛普森悖论出现时,该信分人群还是总体?技术上怎么修?修完的数字是多少?
  3. 随机分流和 SRM 检查与辛普森悖论是什么关系?
  4. 风控模型为什么必然有幸存者偏差?那个 AUC 的数字是多少?三个对策里哪个最有效、代价是什么?
  5. 均值回归怎么骗人?ρ=0.6 时白送多大的"提升"?为什么 p 值保护不了你?
  6. 比率的两个陷阱是什么?
  7. 古德哈特定律说什么?用那个 FCR 的案例说明。真正的解药是什么?
  8. 自查表里最高频的三条是哪三条?
👀 答案
  1. 新算法在老用户(9.50% vs 9.00%)和新用户(2.20% vs 2.00%)两个人群都更好,总体却是 3.42% vs 7.83%,旧的赢。因为老用户天然转化率高(9%)、新用户低(2%),而新算法 83% 的流量落在新用户上,被拖下来了。
  2. 取决于流量分配不均的原因:如果是随机的、只是碰巧不均 → 信分人群;如果是由某个机制决定的 → 要先问清你到底想回答什么问题。技术解法是分层加权(标准化):用同一套人群权重去加权两个算法。修完是 新 0.0585 vs 旧 0.0550,新算法赢,和分人群结论一致。
  3. 随机分流从源头避免了辛普森悖论(分组变量不再影响分到哪一组);SRM 一旦出现就要警惕这类反转——它说明分流不随机了。
  4. 因为被拒的申请人没有"最后还没还款"这个标签,只能用通过审批的人训练,而上线后要判断的是全部申请人。数字:通过率 30% 的场景,离线 AUC 0.78,换成全部申请人重新评估只有 0.66,掉的 12 个点全在「明显该拒、模型从没见过」的人身上。最有效的对策是每天随机放行 0.5–2% 本该拒的申请,代价是真金白银的坏账——但它是唯一的无偏样本。
  5. 挑"表现最差的 10%"做干预,他们下月自然会回升(偶然低谷),会被误认为干预有效。ρ=0.6 时回升幅度约等于挑选时偏离均值的 40%——什么都不做也能报一个"提升 40%"。识别:必须在这批人里再随机分实验组和对照组。p 值保护不了你,因为均值回归造成的差异是系统性的、一定显著p 值只否定"这是随机波动",从不证明"这是你的干预造成的",而且样本越大 p 越小。在挽留/召回/唤醒类项目里几乎必然出现。
  6. 比率的平均不等于平均的比率(要按分母加权)②分母变化伪装成分子变化(CTR 跌可能是曝光暴涨)。
  7. 当一个指标成为目标,它就不再是好指标。案例:把客服「一次解决率 FCR」定成 KPI,客服学会把没解决的问题不建工单、让用户再打一次——第二通是新单,第一通就"解决"了;FCR 从 71% 涨到 89%,同期投诉量涨 34%,三个月后才被发现,因为没有任何一张图把 FCR 和投诉量放在一起。真正的解药不是"找一个更好的指标"(不存在),而是把主指标和护栏指标画在同一张图/看板/周报里——如果一个指标涨了却没有任何机制让你顺便看到代价,它迟早会被优化到失效。
  8. 辛普森(分人群看还成立吗)、均值回归(有对照组吗)、分母变了吗。(外加古德哈特也是高频。)

🛑 可以停在这里

走神救援

⭐⭐辛普森悖论:新算法在老用户 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

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