广告位 · 页头(后台-模块管理-新建模块后替换此区域)

如何科学确定A/B测试的样本量与时长以保证统计功效

A/B测试能否给出可信结论,很大程度上取决于统计功效是否足够。很多人习惯盯着p值是否小于0.05,却忽略了功效不足带来的假阴性风险。功效(Power)表示当真实差异存在时,实验能显著检出该差异的概率。如果功效只有50%,即使改动确实有效,也有一半的概率被误判为无效,造成机会流失。要提升功效,合理确定样本量和实验时长是最直接的路径。本文会拆解样本量计算公式,演示如何用代码完成估算,并讨论从样本量推导实验时长时需要考虑的流量波动与周期因素。

如何科学确定A/B测试的样本量与时长以保证统计功效

一、统计功效、显著性水平与效应量之间的关系

统计检验中通常设定第一类错误概率α,也就是在原假设为真时错误拒绝的概率,惯例取0.05或者0.01。第二类错误概率β则是当备择假设为真时未能拒绝原假设的概率,功效等于1减β。功效不足的原因往往是样本量太小、效应量太小或方差太大。在固定α和效应量的前提下,样本量越大,估计量的标准误越小,检验统计量越容易进入拒绝域,功效随之提升。

效应量是最小可检测效应(MRE),它代表业务上认为值得投入的最低提升幅度。例如转化率从10%提升到12%,相对提升20%,这个0.02的绝对差就是需要检测的效应量。效应量越小,所需样本量越大;反之,如果只关心大幅度提升,样本量需求会显著下降。先设定业务上能接受的最低提升,再反推样本量,比先拍脑袋决定跑两周更科学。

下面的代码演示在给定样本量和效应量时如何计算功效。这里使用Cohen's d作为标准效应量,采用双样本双侧检验。

from statsmodels.stats.power import NormalIndPower
import numpy as np
alpha = 0.05
effect_size = 0.2  # Cohen's d,小效应
n = 394
power = NormalIndPower().solve_power(effect_size=effect_size, nobs1=n, alpha=alpha, ratio=1.0, alternative='two-sided')
print(f"每组样本量 {n} 时功效为 {power:.3f}")

运行后会得到功效约为0.800,说明每组394个样本在检测0.2的效应量时刚好达到80%的常用功效标准。这个示例适合连续型指标,如果是转化率类指标,需要用比例检验的效应量计算方法。

二、样本量快速估算:双样本比例检验

转化率、点击率等二元指标通常采用双样本比例检验。计算每组所需样本量的公式可以结合显著性水平对应的Z值和功效对应的Z值推导出来。核心公式为:n = (Z_{α/2}乘以根号下2乘p乘(1减p)加上Z_β乘以根号下p1乘(1减p1)加p2乘(1减p2))的平方,再除以(p1减p2)的平方。其中p1和p2分别是对照组和实验组的预期转化率,p为合并比例。

实际工程中很少有人手动套公式,通常使用统计库求解。下面的代码计算转化率从10%提升到12%时,每组需要多少样本才能达到80%的功效。

from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
p1 = 0.10
p2 = 0.12
alpha = 0.05
power = 0.80
effect_size = proportion_effectsize(p2, p1)
analysis = NormalIndPower()
n = analysis.solve_power(effect_size=effect_size, alpha=alpha, power=power, ratio=1.0, alternative='two-sided')
print(f"每组所需样本量约为 {n:.0f}")

运行结果通常会显示每组需要约3520个样本,两组加起来约7040个。如果实验组和对照组各分配10%的流量,那么总流量需求是7040除以20%,即约35200个用户进入实验页面。这个数字还要乘以实际转化漏斗的放大系数,因为并非所有进入页面的用户都会走到转化环节。

均值类指标如人均时长、客单价的计算方法与比例检验略有不同。均值检验使用Cohen's d作为效应量,通过均值差除以合并标准差得到。如果历史数据的标准差很大,所需样本量会急剧增加。此时可以考虑使用方差缩减技术,本文最后一节会展开讨论。

三、实验时长计算与流量波动

得到每组所需样本量后,实验时长等于所需总样本量除以日均可用流量。但这个除法结果只能作为粗略参考,因为线上流量存在明显的周内波动。工作日的访问量和转化率通常高于周末,简单按日均值计算可能低估实际需要的天数。更稳妥的做法是使用过去4到8周的历史数据,按星期几的流量系数模拟累计过程。

下面的代码演示如何根据每日基础流量和周内系数,估算达到目标样本量所需的天数。假设每天有2000个基础流量,20%用于实验,周一到周日的流量系数分别为0.9、1.0、1.1、1.15、1.05、0.8、0.7。

import numpy as np
target_samples_per_group = 3520
daily_traffic_base = 2000
weekly_factors = [0.9, 1.0, 1.1, 1.15, 1.05, 0.8, 0.7]  # 周一到周日
days = 0
accumulated = 0
while accumulated < target_samples_per_group * 2:  # 两组
    factor = weekly_factors[days % 7]
    daily_available = daily_traffic_base * factor * 0.2  # 20%流量用于实验
    accumulated += daily_available
    days += 1
print(f"预计需要 {days} 天达到目标样本量")

这个计算只考虑了流量,实际还需要加入缓冲时间。用户行为存在滞后,比如访问后第二天才下单的占比不可忽略,转化窗口可能需要3到7天才能完整观测。实验开始初期也建议丢弃前几天的数据,避免老用户行为基线偏移造成污染。因此,在估算出的天数上额外加3到5天缓冲是常见做法。

此外,要避开大促、版本发布等特殊时期。这些时期的流量结构和用户动机发生改变,实验结果无法代表常规状态。最好选择流量平稳、没有重大运营活动的时间窗口,并在实验过程中监控关键指标是否出现异常波动。

四、资源受限下的功效提升策略

当流量或时间不足以支撑理想样本量时,不能简单降低样本量或缩短时长,这会牺牲统计功效。更合理的方向是降低指标方差,因为样本量需求与方差成正比。CUPED是一种广泛使用的方差缩减方法,它利用实验前指标作为协变量,对实验期指标做回归调整,移除历史行为差异带来的噪声。例如,用用户上月的购买金额调整本月的购买金额,调整后方差往往能减少20%到50%。

下面给出一个CUPED调整的完整示例,模拟1000个用户的实验数据,包含实验前消费和实验期消费。

import numpy as np
import pandas as pd
np.random.seed(42)
n = 1000
pre_spend = np.random.normal(100, 30, n)
treatment = np.random.binomial(1, 0.5, n)
delta = 5
post_spend = pre_spend * 0.8 + delta * treatment + np.random.normal(0, 20, n)
df = pd.DataFrame({'pre_spend': pre_spend, 'treatment': treatment, 'post_spend': post_spend})
theta = np.cov(df['post_spend'], df['pre_spend'])[0, 1] / np.var(df['pre_spend'])
df['cuped_metric'] = df['post_spend'] - theta * (df['pre_spend'] - df['pre_spend'].mean())
control = df[df['treatment'] == 0]['cuped_metric']
treated = df[df['treatment'] == 1]['cuped_metric']
print(f"调整后方差:对照 {control.var():.2f},实验 {treated.var():.2f}")

运行后可以对比调整前后的方差,调整后方差通常会低于原始实验期指标方差。方差降低后,在相同样本量下功效更高,反过来说,达到相同功效所需的样本量更少。分层随机也能起到类似效果,先将用户按关键特征分层,再在每层内随机分配,可以减少层间差异对结果的影响。

另一个需要注意的问题是多重检验。如果在实验过程中反复查看指标并做显著性判断,会大幅增加假阳性概率。建议预先注册主要指标和分析计划,或者使用序贯检验方法控制总体错误率。对于确实无法达到足够样本量的实验,可以降低决策权重,把结果作为后续迭代的参考,而不是直接全量上线。

合理确定样本量与时长是A/B测试可靠性的基础。先设定最小可检测效应和统计功效,再计算样本量,结合真实流量模拟出实验周期,最后通过方差缩减和分层随机等方法提升效率。这样得出的实验结论才经得起复现与推敲。

广告位 · 文章底部(后台-模块管理替换此区域)