想象你是一家餐厅的老板,招牌菜“红烧牛肉”卖了三年。朋友信誓旦旦说新配方更香,你心动了,但能直接换菜单吗?万一这周下雨没客人,营业额下滑,你根本分不清是配方的问题还是天气的问题。A/B 测试就是“开两桌对照实验”:一桌照旧,一桌换新,公平比较。而实验设计,是开跑之前就把账算清楚——要证明什么、拿什么衡量、需要多少客人、怎么分组、观察多久。设计不好,结论就是一笔糊涂账,甚至会把一道更差的菜当成招牌推出去。本文就带你走一遍实验设计的完整流程。
实验设计是数据驱动决策的施工蓝图。学会它,你才能在产品迭代、功能改版、算法上线时,用科学可信的证据说清“我的方案真的更好”——这是 AI 从业者把模型价值讲给业务听的硬核底气。
目录
可视化演示
展示A/B测试实验设计三大核心:假设检验框架(H0/H1与两类错误)、样本量与统计功效计算、流量分桶与实验周期规划。切换模式查看各维度,拖动滑块调节最小可检测效应(MDE)。
本节配有交互动效(进入视口后自动加载,约 3KB)。
假设检验框架与两类错误 原假设H0默认成立(新功能无效果),需数据提供足够统计证据才能拒绝,类似法庭无罪推定原则 第一类错误alpha(假阳性)通常设5%,第二类错误beta(假阴性)通常设20%,统计功效=1-beta=80% H0: effect=0 vs H1: effect!=0 假设检验是实验设计的逻辑基础
实验设计概述——先画蓝图再动工
换菜单前,成熟的主厨不会直接改动配方,而是先写一份试菜计划:接下来两周,每桌客人随机分到“旧配方桌”和“新配方桌”,记录点单率、剩菜量、回头客数。这份计划就是实验设计。它回答四个问题:要证明什么、拿什么衡量、拿多少人来试、试多久。
A/B 测试本质上是一个受控对比实验:把用户随机分成两组,一组看旧版本(对照组 A),一组看新版本(实验组 B),最后比较两组在目标指标上的差异。实验设计是整个流程的第一步,也是最容易出错的一步——设计错了,后面数据跑得再漂亮,结论也是空中楼阁。
完整的设计包含五个要素:假设设定(原假设与备择假设)、指标选择(主指标与护栏指标)、样本量计算、流量分桶规则、实验周期。这五件事互相牵连:样本量决定需要多少天,分桶比例决定每天能积累多少样本,指标方差决定样本量公式里的 σ²。从统计视角看,实验真正要估计的是两组均值之差 Δ,它的不确定性由两组样本量和方差共同决定。
蓝图里每一个数字都对应餐厅的一个具体决策:要招待多少客人(样本量)、怎么分桌(分桶)、记哪些账(指标)、观察几周(周期)。图画好了,厨房才不会乱。
- 两组均值之差$\bar{x}_B - \bar{x}_A$ 是实验组与对照组观测均值的差,即“新版看起来提升了多少”。
- 差的方差差值的波动等于两组各自的方差 σ² 除以各自样本量 n,再相加。
- 设计变量n 由样本量公式和分桶比例决定,σ² 由指标口径决定,Δ 由假设定义——一个公式串起全部设计决策。
假设设定——先立一个“无罪的被告”
法律上有“疑罪从无”,实验里也有同样的原则。你想证明新配方更好,但统计检验不会先去证明“它好”,而是先假设“它并没有更好”——这个默认立场叫原假设 H₀;你真正想证明的“新配方更好”叫备择假设 H₁。
为什么非得反着来?因为“证明两者没差别”几乎不可能——差异总归存在,只是大小问题。正确姿势是:假设没差别,然后收集数据,看有没有足够强的证据推翻这个假设。就像法庭上先假设被告无罪,检方拿出证据,证据足够强才能定罪。
技术细节包括单尾/双尾检验:如果只关心“新版是否提升”(单方向),用单尾检验;如果任何方向的差异都算有变化,用双尾检验。检验前还需定显著性水平 α,通常取 0.05,含义是“原假设为真时,我们错误地拒绝它的概率不超过 5%”——允许有 5% 的概率冤枉好人。
先立好“被告”和“举证标准”再开庭。假设定错了方向,后面的实验跑得再精确,也只是在错误的问题上自嗨。
- 原假设 H0假定新旧无差异或新版更差,先站在“新版无效”这一边。
- 备择假设 H1希望获得支持的方向,即新版确实带来提升。
- 显著性水平 αH0 为真却被拒绝的概率上限,α=0.05 表示允许 5% 的冤枉率。
指标选择——点单率还是投诉率?
判断新菜好不好,不能只看客人点没点。有人图新鲜点一次,吃完再也不来;有人嫌上菜慢,但碍于面子没投诉。单一指标永远有盲区,所以指标要分主次、成体系。
主指标是最终拍板的尺子,它必须直接反映业务目标,比如复购率、支付转化率、人均使用时长。护栏指标是“不能跌破的底线”:投诉率、退款率、页面加载延迟、收入。没有护栏,实验可能出现“转化率升了 20%、退款率翻倍”的灾难——看似赢了,实则亏了。
指标还有两个专业属性:口径和灵敏度。口径指指标的定义与埋点规则(什么算一次点击、一次转化算在谁头上),口径不一致,结果不可比;灵敏度指指标对变化的响应程度,太稀疏的指标(比如“百万用户里只有几人触达”)会让实验需要天文数字般的样本量。选定指标后,实验最终靠 z 统计量来判断两组差异是否显著。
好比一份菜谱要同时看“回头客率”(主)和“后厨事故率”(护栏)。指标在实验开始前就白纸黑字定好,实验结束才不会“什么好看就报什么”。
- 分子(信号)两组样本均值的差,代表新版相对旧版的净提升。
- 分母(噪声)两组标准误平方和的开方,度量这个提升估得有多不准。
- 判断标准双尾 α=0.05 时,|z|>1.96 就拒绝 H0,认为差异统计显著。
样本量计算——最少要招待多少客人
试菜要招待多少客人?3 个人不够——今天一个客人心情差,就能把评价拉低三成。3 万个人又太多——等测完,季节都换了。样本量是实验设计里最“数学”的一步。
计算样本量需要四个输入:显著性水平 α(假阳性上限,通常 0.05)、检验功效 1-β(β 是假阴性率,通常取 0.2 即功效 80%)、指标的方差 σ²(来自历史数据或预实验)、想检测出的最小效应 δ(业务方认为值得投入的最小提升)。输出的是“每组最少需要的用户数”。
直觉上,δ 越小(想分辨越细微的差异)、σ 越大(指标越不稳),需要的样本就越多。公式里 $(z_{\alpha/2}+z_\beta)^2$ 是固定常数,真正起决定作用的是 σ²/δ²。注意公式算的是“每组”人数,两组总共要 2n。
客人数量先算好,才知道实验要跑多久、分多少流量。否则跑了一周发现“数据不够、没法下结论”,重来一次的成本远比设计时多花一天要高。
- 临界值 z_{α/2}由 α 决定,α=0.05 时取 1.96,控制“冤枉新版”的概率。
- 功效临界值 z_β由 β 决定,功效 80% 时取 0.84,控制“漏掉真效果”的概率。
- 两倍方差 2σ²两组各有一个方差,合并后出现系数 2。
- 最小效应 δ²想检测出的最小提升,越小越难检测,需要越多样本。
流量分桶——把客人公平分成两桌
如果让服务员挑客人试新菜,老主顾全被分到新菜桌,结果当然“新菜更受欢迎”——这不是新菜好,是选人有偏。分桶的核心是“公平”:两个组除了版本不同,其他特征分布必须可比。
业界最通用的做法是用 user_id 做哈希取模:把用户 ID 映射成一个均匀分布的整数,除以 K 取余数,得到 0 到 K-1 的桶号;桶号小于 K/2 的进对照组,大于等于 K/2 的进实验组。同一个用户整个实验周期永远落在同一个桶,不会“串组”。K 通常取 100 或 1000,方便按 1% 的粒度控制灰度比例。
两个进阶概念:桶间隔离与正交分层。桶间隔离指同时跑多个实验时,一个用户进了实验 A 的实验组,就不该再进实验 B 的实验组,避免两个版本的改动互相污染。正交分层则是先用性别、城市、新老客等关键维度把用户分层,再在层内随机分流,确保两组关键人群比例一致;配合正交表,能让多个实验共用同一批流量而不互相干扰。
分桶就像餐厅排座:客人随机落座,而不是让熟客都坐新菜品鉴桌。分得公平,结论才立得住。
- 哈希映射把 user_id 均匀打散成整数,避免相邻 ID(如注册时间相近的用户)挤进同一组。
- 取模分桶对 K 取余,得到 0 到 K-1 的桶号;K=100 时正好对应 1% 的流量粒度。
- 判定分组桶号小于 K/2 进对照组,否则进实验组,支持 50/50 之外的灰度比例。
实验周期——测一周还是一季度?
样本量算出来了,但实验要跑多少天?周一中午的客流和周日晚上完全不同,月初和月末、淡季和旺季也不同。如果只测一天,你测到的是“这一天”而不是“这款产品”。
最短周期可以估算:所需总样本量除以每天能进入实验的用户数。公式是 $T_{\min} = 2n / (r \cdot U)$,其中 n 是单组样本量,r 是分桶进实验的用户比例,U 是日均活跃用户。但数学算出来的只是下限,还要加上两个现实约束:至少覆盖一个完整自然周(含周末),以及留出“新奇效应”消退的时间——用户刚看到新界面会因好奇而多点击,几天后热度退去,效果才回到真实水平。
实践中还有周内效应(工作日与周末行为差异大,要分层查看)、季节效应(大促、节假日的干扰项不可控)和网络效应(社交产品中,实验组用户的行为会影响对照组用户,导致“干净对照”失效)。周期定得过短,会把“新鲜感”当成“真效果”。
别看到“第 3 天 p<0.05”就急着收工——那可能只是顾客图新鲜。菜单测试坚持完整一周,才敢说结果不是天气给的。
- 总样本量 2n单组样本量 n 乘以两组,实验需要这么多用户完成转化。
- 每日可入流量 r·U日活 U 中按比例 r 进入实验的用户数,决定样本积累速度。
- 最终周期取数学下限、7 天、新奇效应消退时间三者的最大值。
辛普森悖论——合起来看反而被坑
你按门店分别看,新菜在每一家店的日销量都比旧菜高;但把所有门店合起来,新菜总销量反而更低。这不是数据造假,甚至不是分桶失败——这是著名的辛普森悖论。
原理藏在加权平均里:总转化率不是各层转化率的简单平均,而是按各层样本量加权的平均。如果实验组的流量恰好集中在转化率低的分层(比如小门店、冷淡季),即使每个分层内实验组都领先,一加权,整体平均值反而被拖到对照组之下。悖论的本质是“层的权重分布不均衡”。
解法有四步:设计时记录关键分层变量(城市、新老客、设备类型);分析时先按层看、再合并看;发现分层方向和总体方向矛盾,立即停下找混淆变量;必要时按层加权修正总体估计,最终报告按层呈现,避免被单一总数误导。
就像把两家好餐厅和八家差餐厅的营业额混在一起算“平均表现”,好餐厅的优势被稀释。实验设计时把分层变量记进埋点,是最后一道保险——别让一个总数毁掉所有判断。
- 各层均值把数据按门店/城市等维度切成 k 层,每层算出自己的均值 x̄ᵢ。
- 层权重每层样本量 nᵢ 占总体样本量的比例,决定该层话语权。
- 方向翻转当实验组在小店层的占比较高、而小店层均值整体偏低时,加权后总体方向可能反转。
AI 应用场景
电商 App 首页改版验证
阶段:产品方案评估 / 数据驱动决策
解决的问题:传统做法是“全量上线看大盘数据”,流量混杂、外部因素干扰,根本无法判断改版是否有效。用实验设计先定好假设与指标,再分桶灰度,结论才可信。
具体案例:某电商想验证“新首页推荐位是否提升转化”。设计阶段定下:原假设 H0 为“新版转化率不高于旧版”,主指标=支付转化率,护栏=首页加载时长 P95 与崩溃率;用 user_id 哈希 50/50 分桶,按 δ=1% 反推样本量,跑 14 天覆盖两轮周末。实验发现转化率升 2.3% 但 P95 延迟增加 300ms,护栏指标违规,最终放弃上线——避免了“看似优化、实则伤体验”的错误决策。
推荐算法新模型灰度
阶段:模型评估 / 线上验证
解决的问题:离线 AUC 高不代表线上业务好,需要真实流量验证。实验设计决定如何把用户分流到新旧模型、如何防止桶间污染。
具体案例:某推荐团队上线新排序模型,取 10% 流量做实验。用 user_id 分桶+正交分层,保证新老客比例两组一致;护栏指标=人均播放时长与负反馈率;周期 7 天+新奇效应观察额外 3 天。结果显示人均播放 +4.1%、负反馈不增,才全量发布。没有这套设计,模型 A 的曝光可能污染模型 B 的学习,结论根本不可信。
金融风控策略调整
阶段:策略上线前的风险评估
解决的问题:风控策略调整“通过率”和“坏账率”此消彼长,单看一个指标会得出危险结论。护栏指标在这里是生死线。
具体案例:某金融 App 想放宽授信策略以提升通过率。实验设计定主指标=放款转化率,护栏=逾期 30 天比率与客诉率;按城市分层分桶,避免一线城市高收入用户集中到实验组造成辛普森悖论。跑 30 天覆盖完整账单周期后,发现通过率升 8% 但逾期率升 1.5 倍,护栏报警,策略回滚。
Python 演示
import mathimport random # 标准正态分布的临界值表, key 为单侧概率Z_TABLE = {0.025: 1.96, 0.05: 1.645, 0.10: 1.282, 0.20: 0.842} def sample_size(alpha, beta, sigma, delta): # 根据显著性水平 alpha, 功效 1-beta, 指标标准差 sigma, 最小效应 delta 计算每组样本量 z_alpha = Z_TABLE[alpha / 2] z_beta = Z_TABLE[beta] return int(math.ceil(2 * (z_alpha + z_beta) ** 2 * sigma * sigma / (delta * delta))) def simulate_ab(rate_a, rate_b, n, seed=7): # 模拟 A/B 实验: 两组各 n 个用户, 按伯努利分布转化 random.seed(seed) conv_a = sum(1 for _ in range(n) if random.random() < rate_a) conv_b = sum(1 for _ in range(n) if random.random() < rate_b) p_a = conv_a / n p_b = conv_b / n se = math.sqrt(p_a * (1 - p_a) / n + p_b * (1 - p_b) / n) z = (p_b - p_a) / se return p_a, p_b, z def main(): rate_a = 0.10 # 对照组真实转化率 lift = 0.02 # 想检测出的最小提升: 2 个百分点 sigma = math.sqrt(rate_a * (1 - rate_a)) # 转化率的方差由率本身决定 n = sample_size(0.05, 0.20, sigma, lift) print("设计目标: 检测出转化率从 10% 提升到 12%") print("每组最少样本量:", n) p_a, p_b, z = simulate_ab(rate_a, rate_a + lift, n) print("实验结束: A=%.3f, B=%.3f, z=%.2f" % (p_a, p_b, z)) if z > 1.96: print("结论: 拒绝原假设, 新版显著更好") else: print("结论: 证据不足, 不能拒绝原假设") if __name__ == "__main__": main()
sigma = math.sqrt(rate_a * (1 - rate_a))转化率是"0/1"伯努利变量,它的波动由率本身决定,历史数据不够时用它近似n = sample_size(0.05, 0.20, sigma, lift)把显著性 0.05、功效 80%、方差、最小效应四个设计参数翻译成样本量se = math.sqrt(p_a * (1 - p_a) / n + p_b * (1 - p_b) / n)计算两组转化率差异的标准误,即“噪声”有多大z = (p_b - p_a) / se信号除以噪声得到 z 统计量,对应正文中的指标比较公式if z > 1.96:双尾 α=0.05 的临界值,超过它才有 95% 把握拒绝原假设
常见误区
误区我不确定样本量够不够,那就一直跑,什么时候 p 值小于 0.05 什么时候停,肯定最保险。
正解用餐厅比喻:顾客换了一拨又一拨,季节也变了,你测的已经不只是“新配方”。实验设计要先算样本量、定死周期;中途反复看 p 值、显著即停,会让假阳性率从 5% 膨胀到远高于 5%(多重比较问题)。“跑到显著为止”等于先射箭再画靶。
为何常见:人天生想看到“成功”,且不了解“反复检验会放大假阳性”的统计原理。
误区p 值小于 0.001,说明新版效果巨大,可以立刻全量上线。
正解p<0.001 只说明“观察到差异不太可能是随机波动”,不代表差异在业务上有价值。样本量极大时,哪怕 0.01% 的提升也会显著。下单前先问:这个提升值得承担改版风险吗?要看效应量和业务成本,而不是只看 p 值。
为何常见:显著性这个名字带“显著”二字,让人误以为是“效果显著”,其实是“统计上不像巧合”。
误区出现辛普森悖论肯定是埋点错了或者随机分流失败了,只能去查代码。
正解恰恰相反,数据完全正常也可能出现——只要两组在不同分层上的占比不同。好比 A 餐厅在三个区都比 B 好,但 B 的分店集中在富人区,总营业额反而更高。正确做法:设计阶段就记录分层变量,分析时先分层后合并,发现方向矛盾要预警。
为何常见:人的直觉习惯看“总体数字”,不容易察觉内部权重结构的变化。
误区我把能想到的指标全列为主指标,反正都要看,这样不会漏。
正解主指标太多会让“显著”变成偶然:跑 20 个指标,即使都没有真实效果,也有约 $1 - 0.95^{20} \approx 64\%$ 的概率至少出现一个假阳性。应选 1-2 个核心主指标 + 少量护栏指标,分析结果才干净。
为何常见:业务方想一次看全所有数据,不理解“多重比较会放大假阳性”的代价。
面试题
Q1. 关于原假设 H0 的设定,下面哪项是正确的?
- A.设定新旧无差异或更差← 正确答案
- B.设定新版显著优于旧版
- C.设定样本量达到足够大
- D.设定指标方差足够小
答案:A。原假设是“待推翻”的默认立场,类似“疑罪从无”,应设定为新旧无差异或新版更差。把想证明的结论放进 H0 会颠倒检验逻辑,样本量和方差则是设计参数,不是假设内容。
Q2. 护栏指标在 A/B 实验中的作用是?
- A.防止核心体验等底线恶化← 正确答案
- B.防止实验受随机波动干扰
- C.提高样本量计算精确度
- D.替代主指标完成假设检验
答案:A。护栏指标好比“后厨事故率”,负责兜底,防止新版在优化主指标的同时伤害收入、投诉、延迟等底线。它不替代主指标,也不影响显著性计算或样本量公式。
Q3. 样本量计算中,最小效应 δ 越小,所需样本量会?
- A.越小因为更易检出差异
- B.不变因为与样本量无关
- C.越大因为要分辨细微差异← 正确答案
- D.先增后减取决于显著水平
答案:C。δ 是你想分辨的最小提升。δ 越小,相当于要在更细的刻度上分辨差异,噪声相对更大,因此需要更多样本。类比:要称出 1 克的差别,比称出 1 两的差别需要更精密的秤和更多复测。
Q4. 关于辛普森悖论,说法正确的是?
- A.样本量不足造成的随机波动
- B.分层与合并方向相反的现象← 正确答案
- C.只在数据造假时才会出现
- D.显著性水平设置过高导致的
答案:B。辛普森悖论指每个分层内 A 组都优于 B 组,但合并后总体 B 反而领先。根源是分层样本占比不均衡,与数据造假、样本量、显著性水平都无关。解法是先分层看、再合并看。
Q5. 实验周期设计应主要覆盖?
- A.只覆盖周末高峰就能代表整体
- B.覆盖首次出现显著的那几天
- C.完整业务周期含周末工作日← 正确答案
- D.只覆盖工作日就能代表整体
答案:C。用户行为在工作日与周末差异巨大,周期至少要覆盖一个完整自然周,并预留新奇效应消退时间。“首次显著就停”等于反复偷看 p 值,会膨胀假阳性率,是典型错误做法。
Q6. 实验中反复查看 p 值并在显著时停止,会导致?
- A.统计功效得到显著提升
- B.假阳性率被大幅膨胀← 正确答案
- C.辛普森悖论随之消失
- D.样本量自动完成归一化
答案:B。每看一次数据并决定是否停止,就相当于做一次检验。多次检验下,假阳性率会从 5% 膨胀到远高于 5%。这就像反复抛硬币直到出现一次正面就宣布“硬币偏向正面”,是自欺欺人。
Q7. 流量分桶的好做法包括?
- A.按 user_id 哈希取模随机分组← 正确答案
- B.同一用户实验期间固定组别← 正确答案
- C.多实验并行时做好桶间隔离← 正确答案
- D.按 IP 动态实时切换实验组别
答案:ABC。哈希取模让同一用户固定进同一组,不串组;桶间隔离防止多个实验互相污染。IP 会变化且可能多人共用,动态切换会让用户在不同版本间跳来跳去,破坏实验的干净对照。
Q8. 哪些做法能降低辛普森悖论的风险?
- A.设计时记录城市新老客等分层变量← 正确答案
- B.分析时先按层查看再合并查看← 正确答案
- C.只关注总体聚合转化率指标
- D.发现分层与总体矛盾立即预警← 正确答案
答案:ABD。记录分层变量、先分层后合并、矛盾时预警,是防悖论三件套。只关注总体聚合指标恰恰是悖论得逞的条件——它掩盖了层内差异和权重不均。分层分析相当于把账按门店算清楚再谈总利润。
Q9. 显著性水平 α=0.05 意味着?
- A.实验结果有很高概率正确
- B.实验有 95% 把握发现差异
- C.误拒原假设的概率被限制在 5%← 正确答案
- D.功效达到 95% 的设计要求
答案:C。α=0.05 指“原假设为真时,误拒绝它的概率不超过 5%”,是控制冤枉好人的红线。它不等于实验正确率,也不等于检验功效(那是 1-β 的事)。混淆 α 和功效(1-β)是面试常见陷阱。
Q10. 正式开跑实验前的必要步骤包括?
- A.明确原假设与备择假设← 正确答案
- B.选定主指标和护栏指标← 正确答案
- C.计算样本量并规划实验周期← 正确答案
- D.全量上线新版再观察大盘
答案:ABC。实验设计的五要素——假设、指标、样本量、分桶、周期——都应在开跑前定好。全量上线再观察大盘是“没有对照”的伪实验,无法排除外部干扰,属于设计缺失,不是必要步骤。