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

AB测试示意图

为什么需要新方法?

传统样本量计算公式(比如T检验)有两大痛点:

  1. 正态假设太强:实际业务数据经常是偏态分布(比如电商购买金额)
  2. 忽略方差差异:对照组和实验组的方差不同时误差很大

更糟的是,如果用错公式可能白跑两周实验,最后发现样本根本不够检测出真实效果。

Evan's Method强在哪?

这个方法结合了蒙特卡洛模拟和统计功效分析,优势很直接:

  • 不依赖严格的正态分布假设
  • 自动考虑方差异质性
  • 小样本场景更稳定

对比表格看差异更直观:

| 方法 | 需要正态假设 | 处理方差差异 | 小样本表现 | |----------------|-------------|------------|----------| | 传统T检验公式 | 是 | 否 | 差 | | Evan's Method | 否 | 是 | 优 |

手把手实现

核心思路分三步走:

  1. 模拟数据生成:根据历史数据特征生成仿真数据集
  2. 统计检验循环:对每批模拟数据执行假设检验
  3. 功效计算:统计检测出真实效应的概率

上代码最直接(关键处都加了注释):

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

模拟过程示意图

调优经验

实际使用时要注意:

  1. 模拟次数选择
  2. 开发阶段用500-1000次快速验证
  3. 最终报告建议3000次以上
  4. 分布式加速
  5. 用joblib并行化蒙特卡洛循环
  6. 超大规模数据考虑Spark实现
  7. 内存优化
  8. 增量计算统计量,避免存储全量模拟数据

避坑指南

踩过三个坑特别值得注意:

  1. 方差差异陷阱
  2. 错误:直接用经典t检验
  3. 正确:始终设置equal_var=False

  4. 效应量误解

  5. 错误:把相对提升幅度当绝对值输入
  6. 正确:明确用baseline_mean * mde

  7. 流量分配不均

  8. 错误:样本量计算后仍按1:1分流
  9. 正确:根据方差调整分组比例

延伸思考

这个方法虽然好用,但还有些开放问题:

  • 多变量场景(比如同时测试价格和UI)怎么扩展?
  • 当历史数据存在季节性时如何调整模拟策略?

欢迎在评论区分享你的实战经验~

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐