AB测试实战:如何用Evan's Method精准估算样本量
·
在AB测试中,样本量估算是个让人头大的问题。传统方法要么假设太强,要么计算复杂,经常导致流量浪费或结果不可靠。最近用Evan's Method解决了这个问题,效果不错,分享下实战经验。

为什么需要新方法?
传统样本量计算公式(比如T检验)有两大痛点:
- 正态假设太强:实际业务数据经常是偏态分布(比如电商购买金额)
- 忽略方差差异:对照组和实验组的方差不同时误差很大
更糟的是,如果用错公式可能白跑两周实验,最后发现样本根本不够检测出真实效果。
Evan's Method强在哪?
这个方法结合了蒙特卡洛模拟和统计功效分析,优势很直接:
- 不依赖严格的正态分布假设
- 自动考虑方差异质性
- 小样本场景更稳定
对比表格看差异更直观:
| 方法 | 需要正态假设 | 处理方差差异 | 小样本表现 | |----------------|-------------|------------|----------| | 传统T检验公式 | 是 | 否 | 差 | | Evan's Method | 否 | 是 | 优 |
手把手实现
核心思路分三步走:
- 模拟数据生成:根据历史数据特征生成仿真数据集
- 统计检验循环:对每批模拟数据执行假设检验
- 功效计算:统计检测出真实效应的概率
上代码最直接(关键处都加了注释):
import numpy as np
from scipy import stats
def evans_sample_size(
baseline_mean, # 对照组历史均值
baseline_std, # 对照组历史标准差
mde, # 想检测的最小效应量
alpha=0.05, # 显著性水平
power=0.8, # 统计功效
n_sim=1000, # 模拟次数
max_n=10000 # 最大样本量限制
):
"""
核心计算函数
"""
effect_size = baseline_mean * mde # 计算绝对效应量
# 模拟不同样本量下的检测能力
for n in range(100, max_n, 100):
rejections = 0
# 蒙特卡洛循环
for _ in range(n_sim):
# 生成对照组数据(允许非正态)
control = np.random.normal(
baseline_mean, baseline_std, n)
# 生成实验组数据(添加效应)
treatment = np.random.normal(
baseline_mean + effect_size, baseline_std, n)
# 执行Welch's t-test(不假设方差齐性)
_, p_value = stats.ttest_ind(control, treatment, equal_var=False)
if p_value < alpha:
rejections += 1
# 检查是否达到目标功效
if rejections / n_sim >= power:
return n
return max_n

调优经验
实际使用时要注意:
- 模拟次数选择:
- 开发阶段用500-1000次快速验证
- 最终报告建议3000次以上
- 分布式加速:
- 用joblib并行化蒙特卡洛循环
- 超大规模数据考虑Spark实现
- 内存优化:
- 增量计算统计量,避免存储全量模拟数据
避坑指南
踩过三个坑特别值得注意:
- 方差差异陷阱:
- 错误:直接用经典t检验
-
正确:始终设置equal_var=False
-
效应量误解:
- 错误:把相对提升幅度当绝对值输入
-
正确:明确用baseline_mean * mde
-
流量分配不均:
- 错误:样本量计算后仍按1:1分流
- 正确:根据方差调整分组比例
延伸思考
这个方法虽然好用,但还有些开放问题:
- 多变量场景(比如同时测试价格和UI)怎么扩展?
- 当历史数据存在季节性时如何调整模拟策略?
欢迎在评论区分享你的实战经验~
更多推荐

所有评论(0)