TT Lab
开始
学习 学习路径 课程

开发者创业 — 先验证再动手

按规则判定四个实验

在 TT Lab 中继续学习

目标

编写用标准库计算 SRM、z 检验、置信区间、样本量和 Holm 校正的函数,并按规定的规则判定四个实验的结果。

为什么重要

小团队的 A/B 测试样本少,每天都要看,没有结果就拆开来看。三者都是把偶然变成发现的习惯。必须先定规则,再按规则计算,实验才能守护产品决策。

材料

定义

步骤

  1. 在 /root/founder/ab/ab.py 中创建 srm(n_a, n_b) → {"chi2": x, "p": y},并在 /root/founder/ab/srm.json 中,为 exp1、exp2 各写入 {"a": n, "b": n, "chi2": x, "p": y, "srm": true/false}。
  2. 在 ab.py 中创建 ztest(ca, na, cb, nb) → {"diff", "z", "p", "ci_low", "ci_high"}(ca、cb 是转化数,na、nb 是用户数)。
  3. 在 /root/founder/ab/result.json 中写入 exp1 的 a_users,a_conv,b_users,b_conv,diff,p,ci_low,ci_high,decision。
  4. 在 ab.py 中创建 sample_size(p_base, mde),并在 /root/founder/ab/power.json 中写入 baseline(exp1 A 的转化率,小数点后第四位)、mde(0.01)、n_per_arm(= sample_size(baseline, 0.01))、exp1_min_arm(exp1 两边用户数中较小的一个)、powered(exp1_min_arm ≥ n_per_arm)。
  5. 在 /root/founder/ab/peeking.json 中写入 exp3 的 daily_p(从第 1 天起用累计合计计算出的 21 个 p)、first_significant_day(累计 p < 0.05 的第一天,没有则为 null)、final_p、final_decision(按最后一天累计值做出的判定)。
  6. 在 ab.py 中创建 holm(pvalues)(名称→p 的字典 → 被拒绝的名称的排序后的列表),并在 /root/founder/ab/multi.json 中写入 exp4 的 p(v1 至 v5 各自相对于 control)、naive(p < 0.05 的名称,排序)、holm。
  7. 在 /root/founder/ab/segments.json 中,为 exp1 的 10 个细分群体,分别写入 p、naive(p < 0.05,排序)、holm。
  8. 在 /root/founder/ab/decision.json 中写入 exp1(判定)、exp2_trustworthy(没有 SRM 则为 true)、exp3_decision(最后一天的判定)、exp4_ship(Holm 拒绝的清单)、segment_claims(Holm 拒绝的细分群体清单)。

参考

先确认样本比例

在 /root/founder/ab/ab.py 中创建 srm(n_a, n_b),并在 /root/founder/ab/srm.json 中写入 exp1、exp2 的 a、b、chi2、p、srm。

期望值是 (n_a+n_b)/2。自由度为 1 的卡方尾部概率,可以用 math.erfc(math.sqrt(chi2/2)) 求得。SRM 的标准是 p < 0.001。

两个比率的 z 检验与 95% 置信区间

在 ab.py 中创建 ztest(ca, na, cb, nb)。diff、z、p(双侧)、ci_low、ci_high 保留到小数点后第六位。

检验统计量用合并比率的标准误,置信区间用各自比率的标准误(非合并)。Φ 是 statistics.NormalDist().cdf,临界值是 inv_cdf(0.975)。

判定 exp1

在 /root/founder/ab/result.json 中写入 exp1 的 a_users、a_conv、b_users、b_conv、diff、p、ci_low、ci_high、decision。

判定规则:p < 0.05 且下限 > 0 则为 ship_b,p < 0.05 且上限 < 0 则为 keep_a,其余为 inconclusive。

这个实验是否大到足以捕捉 1 个百分点

在 ab.py 中创建 sample_size(p_base, mde),并在 /root/founder/ab/power.json 中写入 baseline、mde、n_per_arm、exp1_min_arm、powered。

p2 = p1 + mde,p̄ = (p1+p2)/2,z 值是 inv_cdf(0.975) 和 inv_cdf(0.8)。把括号内的整体除以 mde 后平方,再向上取整。

如果每天都看 A/A 实验

在 /root/founder/ab/peeking.json 中写入 exp3 的 daily_p(累计 21 个)、first_significant_day、final_p、final_decision。

exp3_daily.csv 是当天的增量。从第 1 天起逐日累加,用截至当天的累计合计来调用 ztest。日期从 1 开始计数。

五个变体——Holm 校正

在 ab.py 中创建 holm(pvalues),并在 /root/founder/ab/multi.json 中写入 exp4 的 p(v1 至 v5)、naive、holm。

把每个变体与 control 做 ztest(control 在 a 一侧)。Holm 在按升序排列的第 k 个(从 0 开始)上判断 p·(m−k) ≤ 0.05,第一次失败就停止。

拆成十个细分群体来看

在 /root/founder/ab/segments.json 中写入 exp1 的 10 个细分群体的 p、naive、holm。

按细分群体分别统计 A 和 B,调用同样的 ztest,并对 10 个 p 应用同样的 holm。

每个实验的上线决策

在 /root/founder/ab/decision.json 中写入 exp1、exp2_trustworthy、exp3_decision、exp4_ship、segment_claims。

从前面步骤的文件中汇集。存在 SRM 的实验,就是不可信的实验。偷看反例的结论,不是第一个显著的日期,而是最后一天的判定。