A/B测试中停止采样应由统计功效和最小可检测效应(MDE)决定,而非经验或时间;需满足样本量达标、置信区间足够窄或显著正向且样本充足三条件之一,同时规避早停、小样本误判等陷阱。

在 A/B 测试中,“何时停止采样”不是靠经验或时间点决定的,而是由统计功效和预设最小可检测效应(MDE)共同确定的。使用 break 配合条件标记来终止采样,本质是实现一个“样本量达标即停”的实时判定逻辑,常见于离线模拟、灰度放量监控或轻量级实验看板中。关键不在于语法本身,而在于判断依据是否科学、条件是否可复现。
明确停止采样的统计依据
不能简单写成“累计用户数 > 5000 就 break”。真实场景中,停止条件必须绑定统计结论:
- 目标指标(如转化率)的置信区间宽度已收缩到可接受范围(例如 ±2%)
- 当前样本量已达到预设的“建议最小样本量”(由基线率、MDE、α=0.05、β=0.2 计算得出)
- 双样本检验的 p 值持续低于 0.05 且置信区间不跨零,同时样本量 ≥ 建议量(避免早停导致假阳性)
用 break 实现“达标即停”的典型结构
以 Python 模拟数据流为例,核心是每次新增一批观测后立即评估,满足任一预设条件就跳出循环:
from scipy import stats
import numpy as np
<h1>假设已知:基线转化率、MDE、建议样本量</h1><p>baseline_cr = 0.12
mde = 0.03
min_required_n = 8500 # 通过功效计算工具提前得出</p><p>a_conversions, a_users = 0, 0
b_conversions, b_users = 0, 0</p><p>for batch in data_stream: # 每批可能是100~1000条用户行为</p><h1>更新两组计数</h1><pre class="brush:php;toolbar:false;">a_users += batch['a']['users']
a_conversions += batch['a']['conversions']
b_users += batch['b']['users']
b_conversions += batch['b']['conversions']
# 条件1:样本量达标
if a_users >= min_required_n and b_users >= min_required_n:
print("✅ 样本量达标,停止采样")
break
# 条件2:置信区间足够窄(以转化率差为例)
cr_a = a_conversions / max(a_users, 1)
cr_b = b_conversions / max(b_users, 1)
se_diff = np.sqrt(cr_a*(1-cr_a)/a_users + cr_b*(1-cr_b)/b_users)
ci_width = 1.96 * se_diff # 95% CI 宽度
if ci_width cr_a and (cr_b - cr_a) > mde:
_, p_val = stats.chi2_contingency([[a_conversions, a_users-a_conversions],
[b_conversions, b_users-b_conversions]])
if p_val = min_required_n * 0.8:
print("✅ 显著正向且接近足量,提前终止")
break
实际部署时必须规避的陷阱
break 很容易写,但误用会导致结论失效:
- 不能在单次 batch 后就判断显著性——小样本波动大,易触发假阳性早停
- 不能只看 p 值下降就 break,必须同步检查样本量是否接近建议值(否则统计功效不足)
- 分桶逻辑必须稳定:同一 user_id 在整个过程中必须始终归属同一组,否则 break 后的数据不可比
- 线上服务中,
break不等于“关闭实验”,而是“暂停新流量进入”,已分配用户需继续完成行为路径
更稳妥的替代方案
生产环境中,不推荐用循环+break 主动控制采样终点。更健壮的做法是:
- 预设固定实验周期(如7天),确保覆盖用户行为周期(如下单、复访)
- 每日自动校验样本量与置信区间,在报表中标注“已达建议量”供人工决策
- 将“是否终止”交由实验平台统一调度,而非业务代码中的
break










