老周在城南开了一家面馆,开了十年,生意不温不火。他听人说“AI 智能菜单”能把客人爱吃的菜排在最前面,于是想试一试。可怎么试?总不能把老配方直接全换掉——万一客人不买账,十年口碑就砸了。聪明的做法是:把客人随机分成两拨,一拨继续用老菜单,另一拨用新菜单,过一段时间比较两拨人的满意度、客单价和回头率。 看起来简单,老周却很快遇到了连锁难题:怎么分组才公平?90% 的客人去吃新菜,剩下 10% 的对照桌够不够看?为什么总评分明明是涨的,可把客人按年龄拆开一看,每一桌客人给新菜单的评分都在降?如果新菜单同时换了汤底、加了卤蛋、改了份量,到底是哪个改动起了作用?试吃要试几天才算数?两组评分差 0.3 分,到底是真变好了,还是碰巧? 这一整套问题,正是推荐系统工程师每天都在面对的“AB 测试与效果归因”。老周的面馆是微缩的推荐系统:客人是流量,菜单是排序策略,评分是业务指标。读完这篇文章,你就能明白老周这 14 天的试吃实验是怎么做对的,也就能把同一套方法论搬回自己的推荐系统。

岗位关联

对 AI 从业者而言,AB 测试是你写给业务方的“疗效证明”。学会严谨地设计实验、识别统计陷阱、把指标变化归因到具体策略,你的模型才能从“感觉有效”变成“证据确凿”。

目录
  1. 可视化演示
  2. AB测试基础
  3. 实验设计
  4. 辛普森悖论
  5. 效果归因
  6. 实验周期
  7. 显著性检验
  8. 实践要点
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

模拟推荐系统AB测试的流量分桶、指标对比和辛普森悖论,直观理解实验设计与结果解读的关键要点

本节配有交互动效(进入视口后自动加载,约 3KB)。

流量分桶与随机分配 对照组:50%用户走旧策略 实验组:50%用户走新策略 hash(user_id) % N 决定分桶 随机分桶确保两组用户统计可比性

AB测试基础

老周面馆想换新菜单,但不敢全换。最稳妥的办法是“半店试新”:把客人随机分成两拨,一拨继续看老菜单,一拨看新菜单。这就是 AB 测试最朴素的形态——同时经营两套方案,用真实客人的行为投票,而不是老板拍脑袋。老周在门口放了一台抽签机,客人进门先抽个红蓝签,红签走左边坐老菜单区,蓝签走右边坐新菜单区。

在推荐系统里,老周的“客人”就是流量,抽签机就是分桶逻辑。做法是把用户流量随机切分成两个桶(bucket),一桶走旧策略,叫对照组;另一桶走新策略,叫实验组。注意,这里的单元是“用户”而不是“每次点击”:同一个用户被分到实验组后,他后续所有请求都应该走实验策略,否则他刚看完新推荐的商品,刷新一下又被老策略推荐一遍,体验错乱,指标也无法干净归因。这就是“最小实验单元”的由来——推荐系统里默认取用户 ID 作为分桶粒度。

随机化是 AB 测试的基石。就像掷硬币决定客人进哪扇门,随机的目的不是“公平”,而是让实验组和对照组在用户画像上只存在抽样误差,从而把指标差异的锅稳稳扣在策略头上。工程上通常对用户 ID 做哈希取模,保证同一个用户稳定落在同一组。有了随机分桶和对照结构,我们才能给新旧策略的差距算一笔明白账。

老周把客人们分成两拨之后,很快发现事情远没有想象中简单:两拨客人的口味本来就不一样怎么办?90% 对 10% 的分法靠不靠谱?这些正是下一节要处理的“实验设计”难题——分桌只是第一步,把桌子摆得均衡才是真功夫。

提升率=Xˉ实验−Xˉ对照Xˉ对照×100%\displaystyle \text{提升率} = \frac{\bar{X}_{\text{实验}} - \bar{X}_{\text{对照}}}{\bar{X}_{\text{对照}}} \times 100\%
这个公式把“两组差多少”翻译成“相对老策略提升百分之几”,是 AB 报告里最常用的标准话术。
  1. 实验组均值 $\bar{X}_{\text{实验}}$新策略下指标的平均水平,比如新菜单那组客人的平均满意度分数。
  2. 对照组均值 $\bar{X}_{\text{对照}}$老策略下的平均水平,是评判的基准线,相当于“面馆原来的底子”。
  3. 分子做差 $\bar{X}_{\text{实验}} - \bar{X}_{\text{对照}}$计算两组之间的绝对差距,正数代表实验组更好,负数代表更差,零代表没区别。
  4. 分母归一 $\div \bar{X}_{\text{对照}}$把绝对差距变成相对比例,这样点击率、时长、客单价等量纲不同的指标也能横向比较。
  5. 乘以 $100\%$换算成百分比,业务方更习惯读“提升了 5%”而不是“差 0.002”。

实验设计

老周一开始图省事,把 90% 的客人分到新菜单,剩下 10% 用老菜单。结果一周下来,账房先生抱怨:“老菜单那桌根本没几桌客人,样本少得看不出规律。” 流量分配就像分食材:给实验组太多,对照组就瘦得看不出差异;给得太少,实验组又撑不起统计威力。两边都饿着,这顿饭就做不成。

分流比例通常取 50/50 或 90/10。50/50 的统计功效最高,适合风险可控的模型迭代;90/10 适合高风险策略,把风险面控制在 10% 的流量内,但要接受检测灵敏度下降。与之配套的是样本量估算:实验开始前,就要预估“至少需要多少用户”才能让真实差异显形。如果真实提升是 1%,样本太少时它会被噪声淹没;样本够了,1% 才能从噪声里浮出来。

样本量估算依赖几个参数:基线指标水平、期望检测到的最小提升幅度 $\delta$、显著性水平 $\alpha$(通常取 0.05)和统计功效 $1-\beta$(通常取 0.8)。$\sigma$ 是指标本身的波动程度,波动越大,需要的样本越多。分组均衡性同样关键:两组用户的新老占比、活跃度、设备分布要大体一致,否则指标差异可能来自“两组根本不是同一类人”。老周后来学乖了,按常客/新客、早市/晚市做了分层,确保两拨客人画像一致。

老周最终定下 50/50 的分流,又按客群做了分层,确保两拨客人结构一致。可就在他以为万事大吉时,第一周的账本出现了诡异现象——这正是辛普森悖论登场的时候。

n=(z1−α/2+z1−β)2×2σ2δ2\displaystyle n = \frac{(z_{1-\alpha/2} + z_{1-\beta})^2 \times 2\sigma^2}{\delta^2}
这是最常用的两组均值比较的样本量公式,回答“想检出 δ 那么大的差异,每组最少要多少人”。
  1. 显著性临界值 $z_{1-\alpha/2}$对应 $\alpha=0.05$ 时取值 1.96,它决定了“多离谱才不算巧合”的门槛。
  2. 功效临界值 $z_{1-\beta}$对应功效 0.8 时取值约 0.84,它决定了“真有差异时有多大概率能发现”。
  3. 波动项 $2\sigma^2$两组各自的方差之和。客人口味越飘忽,评分越不稳定,就需要更多样本。
  4. 最小提升幅度 $\delta^2$想要检测的差异越小,分母越小,需要的样本量就越大——想看清绣花针,得凑很近。
  5. 整体关系 $n \propto (\cdots)^2 / \delta^2$样本量与阈值的平方成正比、与期望提升的平方成反比,这就是“差之毫厘,谬以千里”的数学版本。

辛普森悖论

试吃了一周,老周兴奋地发现新菜单整体评分比老菜单高。可他把账本按客群拆开一看,懵了:无论是年轻客人还是老年客人,给新菜单的评分竟然都比老菜单低。整体更高、分组更低,这账怎么算都对不上。老周怀疑账房先生算错了,可重新验算了三遍,数字没变。

这就是著名的辛普森悖论。原因在于两组客人的结构不均衡:新菜单那区碰巧坐满了“好说话”的年轻客人,老菜单那区多是“挑剔”的老主顾。年轻客人本来打分就高,把整体平均分拉上去了,于是掩盖了新菜单在每个客群内部都更差的事实。换句话说,整体比较被“人群结构”这个混淆因素带偏了。

数学上,整体率就是各子群率的加权平均,权重是各子群的人数占比。当实验组和对照组在子群占比上不一致时,整体对比的方向就可能与所有子群的对比方向相反。识别方法很直接:把指标按新老客、渠道、设备等维度分层,一层层对比;应对方法则是在实验前保证两组各维度分布一致,或事后用分层加权重新计算。

老周恍然大悟:不是新菜单好,而是“碰巧”坐在新菜单区的年轻客人多。他赶紧重新设计均衡分流,确保两拨客人结构一致。这个教训也让他牢记:看推荐系统的整体指标时,一定要留个心眼——整体涨了,不等于每个用户群都涨了。

Rˉ=n1Rˉ1+n2Rˉ2n1+n2\displaystyle \bar{R} = \frac{n_1 \bar{R}_1 + n_2 \bar{R}_2}{n_1 + n_2}
整体平均分不是“大家评分的平均值”,而是“每桌平均分按人数加权”的结果——人多的一桌,嗓门大。
  1. 子群均值 $\bar{R}_1, \bar{R}_2$年轻客人和老年客人各自的平均评分,比如 8.2 分和 5.1 分。
  2. 子群人数 $n_1, n_2$每群的人数,这是加权平均里的“权重”,人越多权重越大。
  3. 分子加权求和 $n_1\bar{R}_1 + n_2\bar{R}_2$每个子群用自己的评分乘以人数,相当于“每个人投一票”。
  4. 分母总人数 $n_1 + n_2$把所有票数归一化,得到整体平均。
  5. 结论只要两组里 $n_1$、$n_2$ 的比例不同,即使每个子群内实验组都更差,加权后的整体也可能更高——这就是悖论之源。

效果归因

解决了分组问题后,新菜单的评分终于稳稳超过老菜单。但老周又有了新烦恼:新菜单同时改了三个地方——换了汤底、加了卤蛋、改了大碗份量。到底是哪个改动让客人更满意?这就好比推荐系统里同时上了新排序模型、新召回路和新页面样式,指标涨了,功劳该记在谁头上?

效果归因,就是把 AB 实验观察到的指标变化,拆解回具体的策略或特征贡献。第一步是“指标拆解”:业务指标往往是多层漏斗的乘积,GMV 等于流量乘以转化率再乘以客单价。哪个环节变了,改动的影响范围就收敛到哪个环节。如果转化率没动、客单价动了,那问题多半出在定价策略而不是排序模型。

拆解之后做“特征贡献度”分析:只换一个特征时,可以设计消融实验——把新特征去掉再跑一遍对照;多个策略叠加时,则把各改动安排到相互正交的流量桶里,让每个桶之间只差一个改动,然后用分层拆解把总提升分配到各来源。最后还需要“置信评估”:归因结论要给出置信区间,不能只看点估计,因为样本波动可能让贡献度虚高,就像老周如果只尝一口汤底,根本分不清是盐多了还是味精多了。

老周把三个改动拆成三组小实验,发现功劳全是卤蛋的:汤底没人吃出差别,大碗份量反而拖慢了翻台率。他果断把卤蛋写进菜单,把收益稳稳落袋。这就是归因的价值——把“整体有效”变成“哪一步有效”,下次迭代就能只做对的事。

GMV=UV×CVR×AOV\displaystyle GMV = UV \times CVR \times AOV
GMV 不是单一数字,而是三个环节的乘积。对数化之后,乘法变成加法,归因就变成“谁贡献了几成”。
  1. 访客数 $UV$来到店里的客人总数,对应推荐系统的曝光用户数。
  2. 转化率 $CVR$客人中真正下单的比例,对应推荐系统的点击率、成交率。
  3. 客单价 $AOV$平均每单花了多少钱,对应推荐系统的客单金额。
  4. 连乘关系三个环节是乘法联动,任何一个翻倍都能让 GMV 翻倍,所以归因要先定位“哪一环变了”。
  5. 对数拆解 $\log GMV = \log UV + \log CVR + \log AOV$取对数后总变化等于各环节变化之和,贡献度从此可以相加,这是实际归因中常用的技巧。

实验周期

试吃进行到第五天,新菜单评分还在涨。老周差点就要拍板换菜单,账房先生拦住了他:“周末还没到,通宵打游戏的年轻客人还没来呢。而且客人们对新菜的新鲜劲儿没过,评分里掺了'尝鲜水分'。” 老周这才意识到,时间本身就是实验的变量。

推荐系统实验同样要面对两个时间陷阱:周内效应和新奇效应。周内效应指周末和工作日的用户行为模式不同——工作日中午来吃面的多是上班族,周末则是家庭客群,两拨人的口味和耐心都不一样。新奇效应指用户对新策略产生好奇,点击率短期虚高,等新鲜劲儿过去才回落到真实水平。只看周一到周三的“上升”,很可能被新奇效应骗得提前上线。

因此实验周期要覆盖至少一个完整的业务周期,通常以 7 天或 14 天为单位,条件允许时跑满 28 天把月度效应也包进来。所需天数可以估算:把需求的样本量除以每日可分配的流量。实际操作中还要保证时间一致性——实验组和对照组必须在同一时间段运行,不能拿上周的数据当对照组,因为上周可能有大促、有节假日,这周没有,比较就失去了意义。

老周把试吃拉长到整整 14 天,跨过两个周末,等到新奇效应消退后的最后一周才看稳态数据。果然,第 8 天开始评分曲线不再上蹿下跳,结论变得踏实可靠。他也明白了一个道理:实验周期不是“越长越好”,而是“刚好覆盖完一个完整业务节律”。

T=⌈nD×r⌉\displaystyle T = \left\lceil \frac{n}{D \times r} \right\rceil
实验天数 = 需要的样本量 ÷ 每天能攒到的实验组人数,天数只舍不入,多跑一天永远比少跑一天稳妥。
  1. 需求样本量 $n$上一节样本量公式算出来的每组最少用户数,它是“实验的饭量”。
  2. 日均活跃流量 $D$每天进店的客人总数,对应推荐系统的日活用户数。
  3. 实验组流量占比 $r$分给实验组的流量比例,90/10 分法下 $r=0.1$。
  4. 乘积 $D \times r$每天实际能攒到的实验组样本量,相当于“每天能喂饱多少客人”。
  5. 向上取整 $\lceil \cdot \rceil$天数只能多不能少,还差半天也得多跑一天,否则样本量不达标。

显著性检验

到了第 14 天,新菜单平均分比老菜单高 0.3 分。老周很开心,账房先生又泼冷水:“这 0.3 分,会不会是陈师傅那桌客人心情好乱打的分?” 换句话说:差异到底是策略造成的,还是抽样运气造成的?老周答不上来,这正是统计学登场的时刻。

显著性检验的核心是反证法:先假设新策略没有效果(零假设),然后计算在当前样本下出现“这么大差异”的概率——这个概率就是 p 值。p 值越小,说明“纯靠运气”越难解释,证据越充分。注意,p 值回答的是“差异是不是运气”,而不是“策略有多好”——这是初学者最容易混淆的点。

对于转化率这类比例型指标,通常构造 z 统计量把差异归一化。分子是两组转化率之差,分母是差异的标准误,衡量这个差值的波动幅度。z 值就是“差异相当于多少个标准误”。一般把拒绝线画在 z = ±1.96(对应 p = 0.05),落在这个范围之外就认为差异显著。但显著不等于“提升大”——这要靠置信区间来回答:区间给出差异的真实可能范围,如果区间下限都大于 0,才敢说“至少提升了这么多”。最后还要区分统计显著与业务显著:样本量足够大时,0.01% 的差异也会“显著”,但这点提升可能根本不值得上线。

老周算完 z 值,发现 0.3 分的差异对应的 p 值是 0.003,远小于 0.05,置信区间下限是 0.15 分。他终于敢拍板:换菜单!不过账房先生又补了一句:“先别急,我们还得按流程把结果再复核一遍。” 这就引出了最后一节的实践要点。

z=p^A−p^Bp^A(1−p^A)nA+p^B(1−p^B)nB\displaystyle z = \frac{\hat{p}_A - \hat{p}_B}{\sqrt{\frac{\hat{p}_A(1-\hat{p}_A)}{n_A} + \frac{\hat{p}_B(1-\hat{p}_B)}{n_B}}}
z 值把“两组差多少”除以“这个差值本身有多飘”,得到的倍数如果超过 1.96,就说明差异大得不像是运气。
  1. 实验组转化率 $\hat{p}_A$新菜单区的下单比例,比如 6.2%。
  2. 对照组转化率 $\hat{p}_B$老菜单区的下单比例,比如 5.0%。
  3. 分子之差 $\hat{p}_A - \hat{p}_B$两组转化率的差距,这是我们要判断“靠不靠谱”的对象。
  4. 分母标准误 $\sqrt{\frac{\hat{p}_A(1-\hat{p}_A)}{n_A} + \frac{\hat{p}_B(1-\hat{p}_B)}{n_B}}$衡量差异的波动幅度。样本越多,分子里的 $n$ 越大,标准误越小,差异看得越清楚。
  5. 对照阈值 $\pm 1.96$若 $|z| > 1.96$,则 p 值小于 0.05,差异统计显著,可以认为不是运气。

实践要点

老周把这次试吃的全流程写成了一张“开店 SOP”贴在后厨:先定目标、再分桌、跑满时长、分层看数、最后签字确认。之后每次换菜谱都按这套流程走,再也没翻过车。推荐系统的 AB 测试同样需要一套可复用的决策流程,而不是“跑完看 p 值”的一锤子买卖。

标准的决策流程是:明确假设与核心指标 → 确定最小可接受的提升幅度(MDE)→ 估算样本量与实验周期 → 均衡分流 → 上线并全程监控 → 分层分析与显著性检验 → 归因与复盘 → 决定上线或回滚。MDE 决定了实验的“分辨率”:如果业务上低于 1% 的提升不值得动,那实验就按检出 1% 差异来设计样本量,而不是盲目追求“显著”。

监控要同时盯两组指标与线上总盘,防止实验污染——比如实验期间又上线了另一个策略,那结果就说不清是谁的功劳。解读结果时,把统计显著、业务提升、长短期影响合在一起看,并警惕多重比较:指标看得够多,总有假阳性冒出来。上线后还要继续跟踪,验证短期提升是否转化为长期留存。以下公式给出了“能可靠检出的最小差异”,它是实验设计的起点,也是决策的标尺。

如今老周的菜单更新,都是用“两拨客人试吃 + 分层核对 + 显著性把关”的流程推出来的。AI 推荐系统的迭代,本质上和老周换菜谱是同一件事——用真实用户的行为投票,用统计方法辨别真假,用归因找到真正的功臣。这套流程走熟了,每一条策略的上线与回滚,都会变得有理有据。

δmin⁡=(z1−α/2+z1−β)×SEdiff\displaystyle \delta_{\min} = (z_{1-\alpha/2} + z_{1-\beta}) \times SE_{diff}
比 $\delta_{\min}$ 还小的提升,再多的样本也分不清是真话还是噪声——所以实验前就要约定“多小的提升不值得上线”。
  1. 显著性临界值 $z_{1-\alpha/2}$取 1.96,对应“别把巧合当真”的严格程度。
  2. 功效临界值 $z_{1-\beta}$取约 0.84,对应“别把真效果漏掉”的敏感程度。
  3. 差异标准误 $SE_{diff}$两组指标差值的波动幅度,样本越大它越小。
  4. 最小可检测提升 $\delta_{\min}$在这个实验设计下,能可靠识别出的最小差异。它决定了实验的“分辨率”。
  5. 整体含义把两个临界值相加再乘上波动,就是“既要少犯错、又要看得清”所需的分辨率下限。

AI 应用场景

排序模型升级的 AB 验证

阶段:模型评估

解决的问题:从逻辑回归(LR)切换到 DeepFM 这类深度学习排序模型,直接全量上线风险极高。传统做法只凭离线 AUC 决定是否上线,但离线指标与线上业务指标经常背离——离线 AUC 涨了,线上点击率不涨反跌的情况并不少见。AB 测试用线上真实用户行为做金标准,把风险控制在部分流量内。

具体案例:某电商推荐团队训练了新的 DeepFM 排序模型,先切 10% 流量跑 14 天 AB 实验,实验组点击率提升 3.2%、p 值为 0.01;随后扩大到 50% 流量再验证一周,确认无负向指标后全量上线,并持续监控 30 天的长期指标。

新特征上线的归因分析

阶段:特征工程

解决的问题:一次迭代同时加入了“实时点击序列特征”和“价格敏感度特征”,整体 CTR 涨了,但无法确定哪个特征贡献更大。用正交分桶做分层归因,把总提升分摊到各特征,避免把功劳记错人。

具体案例:某短视频推荐团队在两个正交实验桶中分别验证“实时兴趣特征”和“热门内容降权”两个改动,结果发现实时兴趣特征贡献了约 80% 的提升,而热门内容降权不仅无益还拉低了内容多样性,随后回滚后者,用省下的流量把实验精力集中到有效方向。

辛普森悖论排查

阶段:结果分析

解决的问题:新策略整体指标上涨,但按新老用户、设备、地区拆分后,大部分分段指标反而下跌,需要找到掩盖真实方向的混淆变量。

具体案例:某资讯推荐团队发现实验组整体人均时长上升,但按新老用户分层后发现新用户时长反而下降。排查分流日志后确认:新用户多被分进了实验组(老用户被客户端缓存挡在实验外),人群结构失衡制造了假象。修正分流后重新实验,结论完全反转。

Python 演示

python56 行
import mathimport random  def normal_cdf(x):    """标准正态分布累积概率(近似)"""    t = 1.0 / (1.0 + 0.2316419 * abs(x))    d = 0.3989423 * math.exp(-x * x / 2)    p = d * t * (0.3193815 + t * (-0.3565638 + t * (1.781478        + t * (-1.821256 + t * 1.330274))))    return 1.0 - p if x > 0 else p  def run_ab_test(n_c, n_e, p_c, p_e, seed=42):    """模拟一次AB实验, 返回两组转化率, 提升率, z值与p值"""    rng = random.Random(seed)     def _trial(n, p):        return sum(1 for _ in range(n) if rng.random() < p)     c_hat = _trial(n_c, p_c) / n_c    e_hat = _trial(n_e, p_e) / n_e    se = math.sqrt(c_hat * (1 - c_hat) / n_c + e_hat * (1 - e_hat) / n_e)    z = (e_hat - c_hat) / se    p_value = 2 * (1 - normal_cdf(abs(z)))    lift = (e_hat - c_hat) / c_hat * 100    return c_hat, e_hat, lift, z, p_value  def simpson_paradox():    """演示: 实验组在两类人群中都更差, 整体却更好"""    nc_young, nc_old = 2000, 8000    ne_young, ne_old = 9000, 1000    pc_young, pc_old = 0.060, 0.020    pe_young, pe_old = 0.050, 0.015    pc_all = (nc_young * pc_young + nc_old * pc_old) / (nc_young + nc_old)    pe_all = (ne_young * pe_young + ne_old * pe_old) / (ne_young + ne_old)    print("年轻人: 对照组 %.4f | 实验组 %.4f (实验组更差)" % (pc_young, pe_young))    print("老年人: 对照组 %.4f | 实验组 %.4f (实验组更差)" % (pc_old, pe_old))    print("整体:   对照组 %.4f | 实验组 %.4f (实验组更好!)" % (pc_all, pe_all))  if __name__ == "__main__":    c, e, lift, z, p = run_ab_test(5000, 5000, 0.050, 0.062)    print("对照组转化率: %.4f" % c)    print("实验组转化率: %.4f" % e)    print("相对提升: %.2f%%" % lift)    print("z 值: %.3f" % z)    print("p 值: %.4f" % p)    if p < 0.05:        print("结论: p < 0.05, 差异显著, 可以扩大流量或全量上线")    else:        print("结论: p >= 0.05, 差异不显著, 继续积累样本")    print()    print("===== 辛普森悖论演示 =====")    simpson_paradox()
目的:模拟一次转化率 AB 实验并计算 z 值与 p 值,同时演示辛普森悖论——实验组在每类人群中更差、整体却更好的反常现象。
  1. se = math.sqrt(c_hat * (1 - c_hat) / n_c + e_hat * (1 - e_hat) / n_e)计算两组转化率差异的标准误,样本量越大,波动越小。
  2. z = (e_hat - c_hat) / se把差异转换成“多少个标准误”,这是显著性检验的核心一步。
  3. p_value = 2 * (1 - normal_cdf(abs(z)))双尾检验的 p 值,p < 0.05 就认为差异显著。
  4. ne_young, ne_old = 9000, 1000实验组年轻人占绝大多数,正是这种结构失衡制造了辛普森悖论。
  5. pc_all = (nc_young * pc_young + nc_old * pc_old) / (nc_young + nc_old)整体率是子群率的加权平均,权重是人数占比。

常见误区

误区我觉得实验周期越长、样本越多,结论肯定越准,反正多跑几天又不花钱。

正解实验周期过长会引入时间干扰:用户行为随季节、大促、产品版本不断变化,“实验组这一周”和“对照组上一周”根本不是同一批环境。而且新奇效应消退后继续拖,只会浪费迭代速度。正确做法是先按样本量公式算出最少天数,再覆盖 2 到 3 个完整业务周期(如 14 到 28 天)即可,而不是无限期跑下去。

为何常见:直觉上“样本越多越好”在统计上是成立的,但现实里的流量会随时间漂移,初学者容易忽略时间维度上的干扰变量。

误区实验组点击率比对照组高,那新策略肯定有效,直接写报告申请全量上线吧。

正解整体上涨可能是辛普森悖论:实验组碰巧分到了更多高活跃用户,把均值拉高了,而每个细分人群里策略其实都在变差。上线前必须按新老客、渠道、设备等维度分层检查,确认方向一致后再排除混淆因素,否则等于被平均数骗了。

为何常见:人脑天然只看汇总数,因为汇总数直观方便,很少有人习惯“先拆开再看”,而平均值恰恰最容易掩盖结构差异。

误区书上说 p < 0.05 就是显著,那说明有 95% 的概率策略有效,稳了,直接上线。

正解p 值的真正含义是“假设策略无效,纯靠抽样运气看到这么大差异的概率”,它既不是策略有效的概率,也不是真实提升的幅度。样本量很大时,哪怕 0.01% 的微小差异也会 p < 0.05,这在业务上毫无意义。正确的结论要同时看统计显著性、置信区间下限和业务提升幅度,三者缺一不可。

为何常见:“显著性”这个词太有误导性,让人误以为“显著 = 重要”,而教材又往往只教结论不教语境,导致 p 值被当成万能通行证。

误区实验组指标不升反降,说明这次模型训练完全失败,代码白写了,赶紧删掉实验。

正解实验失败同样是宝贵信息:它可以定位到具体环节的负效应(比如排序模型让点击率涨了但人均时长降了),可以暴露数据分布的变化,也能为下一次迭代提供基线。效果归因不只在“涨了”时有价值,“跌了”时定位到负贡献特征同样关键。成熟的团队把每一次 AB 结果当作一次有标签的线上实验,沉淀为长期经验。

为何常见:许多人把 AB 测试当成“考试”而非“观测”,只关心过没过,忽略了失败结果里蕴含的归因价值。

误区反正新策略看起来更好,直接 95% 流量上实验组,这样结论出来得快。

正解实验组比例过大会带来两个问题:一是对照组样本被压缩,标准误变大,检测灵敏度反而下降;二是高风险策略会让 95% 的真实用户在未经验证时承担体验风险。而且“看起来更好”本身可能只是运气或新奇效应。稳妥的路径是 10% → 50% → 全量的灰度递增策略。

为何常见:直觉是“样本大 = 结论快”,忽略了 AB 测试中对照组同样需要足量样本,以及错误全量上线带来的风险成本。

面试题

Q1. 推荐系统 AB 测试中,为什么流量分桶要以“用户ID”为最小单元而不是“单次请求”?

单选题 · easy

  • A.用户行为有连续性和记忆效应← 正确答案
  • B.按请求分配实现起来更简单
  • C.用户ID随机分配计算效率更高
  • D.按请求分配更符合统计学原理

答案:A。同一用户多次请求之间存在强相关性,今天的行为会影响明天的推荐结果。若按请求分桶,同一用户可能上午走实验策略、下午走对照策略,体验错乱且指标互相污染。按用户 ID 分桶能保证同一用户稳定落在同一组,符合“最小实验单元”的设计原则。

Q2. 辛普森悖论描述的是哪种现象?

单选题 · mid

  • A.整体对比方向与各分组对比方向相反← 正确答案
  • B.实验组方差显著大于对照组方差
  • C.多重假设检验导致假阳性率上升
  • D.新策略上线后指标先升后降

答案:A。辛普森悖论指数据整体呈现的趋势与所有子群内部的趋势相反,根源是各子群占比在两组样本中不均衡,即存在混淆因素。B 是方差问题,C 是多重比较问题,D 是新颖效应问题,均与辛普森悖论无关。

Q3. 关于 p 值的理解,下列说法正确的是?

单选题 · mid

  • A.表示实验组比对照组真实提升 5%
  • B.表示差异由随机因素造成的概率小于 5%← 正确答案
  • C.表示实验组在 95% 的用户中都表现更好
  • D.表示备择假设为真的概率是 95%

答案:B。p 值的严谨定义是“零假设为真时,观测到当前或更极端差异的概率”,通俗讲就是“纯靠抽样运气解释这么大差异的可能性”。它既不是策略有效的概率,也不是真实提升幅度。A、C、D 都是对 p 值的常见误读。

Q4. 确定 AB 实验周期时,需要考虑哪些因素?

多选题 · mid

  • A.覆盖完整用户活跃周期← 正确答案
  • B.留够新奇效应消退时间← 正确答案
  • C.算清离线训练所需时长
  • D.满足显著性检验的样本量← 正确答案

答案:ABD。实验周期必须覆盖工作日/周末等业务周期(A),等用户的新鲜感消退后再看稳态数据(B),且周期要足够长以积累满足显著性检验的样本量(D)。离线训练时长属于实验前的准备阶段,并不决定实验周期,因此 C 不选。

Q5. AB 实验中“最小实验单元”通常指的是?

单选题 · easy

  • A.单次请求
  • B.单个用户ID← 正确答案
  • C.单个点击
  • D.单台服务器

答案:B。用户行为在时间上存在连续性和记忆效应,今天的行为会影响后续推荐,因此同一个用户必须稳定归入同一组。推荐系统 AB 测试的最小实验单元一般取用户 ID,而不是请求或点击级单元。

Q6. 关于 AB 实验的效果归因,下列说法正确的是?

单选题 · hard

  • A.实验显著就能归因到具体特征
  • B.多策略叠加可分层拆解辅助归因← 正确答案
  • C.归因必须依赖深度学习模型
  • D.辛普森悖论不影响归因结论

答案:B。多个策略同时上线时,总提升是各策略贡献的叠加,可通过正交分桶、分层拆解和消融实验把贡献分摊到各改动。A 忽略了混杂因素,显著不等于因果关系清晰;C 把归因狭隘化为模型工具;D 错误,辛普森悖论恰恰会严重误导归因方向。

Q7. 判断一个新策略能否全量上线,正确的做法包括?

多选题 · hard

  • A.同时看统计显著性和业务提升幅度← 正确答案
  • B.上线前预先确定最小可接受提升← 正确答案
  • C.只看p值小于0.05就拍板
  • D.全量后继续跟踪长期指标← 正确答案

答案:ABD。上线决策要把统计显著(差异不是运气)与业务显著(提升值得动)结合来看(A),预先注册最小可接受提升可防止事后挑选指标(B),全量后仍需监控长期效果(D)。只盯 p 值是大样本时代最常见的翻车姿势,因此 C 不选。

Q8. 若实验组与对照组流量比为 90/10,最可能出现的问题是?

单选题 · mid

  • A.对照组标准误偏大、灵敏度下降← 正确答案
  • B.实验组指标一定被高估
  • C.实验结论一定发生辛普森悖论
  • D.显著性检验完全无法进行

答案:A。对照组的样本只占总流量的 10%,其指标估计的方差更大,差异检验的灵敏度随之下降,可能漏报真实效果(第二类错误)。但实验组指标不一定被高估,辛普森悖论也并非必然发生,显著性检验只是更难检测而非完全无法进行。

Q9. 老周面馆试吃新菜单时,客人因新鲜感给出的偏高评分,对应 AB 测试中的?

单选题 · easy

  • A.新奇效应← 正确答案
  • B.辛普森悖论
  • C.周内效应
  • D.幸存者偏差

答案:A。用户对新策略产生好奇,短期内指标虚高,随后回落到稳定水平,这就是新奇效应。应对办法是拉长实验周期,等曲线稳定后再统计。周内效应指工作日与周末的行为差异,辛普森悖论指分组结构失衡,均与“新鲜感”无关。

Q10. 下列哪些情况会导致 AB 实验结论不可靠?

多选题 · extreme

  • A.实验期间同时上线了另一个推荐策略← 正确答案
  • B.分流未按用户ID做稳定分组← 正确答案
  • C.使用双尾检验而非单尾检验
  • D.实验时长不足以覆盖完整业务周期← 正确答案

答案:ABD。实验期间叠加其他策略属于实验污染,会让指标变化无法归因(A);不稳定分组会导致用户串组、指标被稀释(B);时长不足一个业务周期会漏掉周末等行为差异(D)。双尾与单尾检验只是两种合理的统计选择,本身不会破坏实验可靠性,因此 C 不选。