第二章节:统计基础——假设检验、p值、置信区间
做 AB 验证,躲不开三个东西:假设检验、p 值、置信区间。
说白了,这就是你判断实验结果靠不靠谱的数学工具。没有它们,你改版之后看到 0.5% 的转化提升,根本不敢说这是你的功劳还是随机波动。
我刚开始带项目时,就踩过这个坑。改了一个按钮颜色,转化率涨了 0.8%,兴冲冲地汇报。结果被老板一句「你确定不是运气好?」怼了回来。嗯,从那以后我才老老实实把这套基础补上。
统计基础三件套
假设检验定方向,p 值给证据,置信区间画范围。三者缺一,AB 验证就不完整。
假设检验:你的实验到底在检验什么?
你做一个改动,然后看数据。但你怎么知道这个改动真的有效?
我们需要设计一个「对照实验」。这个实验的逻辑特别简单:先假设改动没用,然后看数据能不能推翻这个假设。
这个「假设改动没用」,就是原假设(H₀)。对应的「改动有效」,就是备择假设(H₁)。
我的习惯:在每次 AB 验证开始前,先把 H₀ 和 H₁ 写下来,贴在项目看板上。这能让你在分析结果时不容易跑偏。
举个例子。你改了一个支付按钮的位置,想看看能不能提高支付转化率。
- H₀:新按钮位置与旧按钮位置的支付转化率没有差异。
- H₁:新按钮位置比旧按钮位置的支付转化率更高(或更低,看你期望)。
你收集数据,算个统计量,然后决定是否拒绝 H₀。如果数据足够「离谱」,就拒绝 H₀,接受 H₁。
为什么叫「假设检验」?其实就是看数据给不给原假设面子。
p 值:一个数字,告诉你运气成分有多大
p 值,很多人觉得它神秘。其实很简单。
p 值说的是:如果原假设是真的,你拿到现在这个结果(或更极端结果)的概率。
嗯,要小心理解这句。不是「H₀ 为真的概率」。而是「假设 H₀ 为真,看到这种数据的概率」。
举个例子:
- p = 0.03,意思是如果改动无效,你只有 3% 的可能看到现在的差。那多半是改动真有效。
- p = 0.5,意思是如果改动无效,你有 50% 可能看到现在的差。那就不能排除这是随机波动。
我曾经踩过的坑:早期做 AB 验证时,我以为 p 值越小,效果越好。其实不是。p 值只告诉你是否存在统计显著差异,不告诉你差异有多大。一个微小到没有商业价值的变动,样本量足够大时,p 值也能变得很小。
行业中通常设阈值 α = 0.05。p 值小于 0.05,就说「统计显著」。但有两点要注意:
- 这个阈值只是惯例。有些场景(如医疗、金融)会设 0.01 更保险。
- p 值在 0.05 附近飘忽时,最好多做几次验证,或者延长实验周期。
你想想看,如果你从 10 万个样本里算出 p = 0.049,会不会真的信?我建议你再看一次置信区间。
置信区间:不只看「有没有」,还要看「有多大」
p 值告诉你「差异是否存在」。置信区间告诉你「差异有多大,并且有多不确定」。
95% 置信区间,意思是重复做 100 次实验,大概有 95 次实验的效应量会落在这个区间里。
假设你实验得出支付转化率提升了 2 个百分点,95% 置信区间是 [0.5%, 3.5%]。
- 下限 0.5%:最差情况也能涨 0.5%。
- 上限 3.5%:最好情况涨 3.5%。
- 宽度 3%:说明数据波动不小,结论还需要更多数据来锚定。
一个实用原则:如果置信区间的下限 > 0,而且下限 > 你认为有商业价值的「最小有意义效应」,那这次改动才值得全量上线。否则,就算 p 值显著,也要再想想。
| 概念 | 回答的问题 | AB 验证中的用法 |
|---|---|---|
| 假设检验 | 改动是否产生了系统性的差异? | 设定 H₀ 和 H₁,确定检验方向(单侧/双侧) |
| p 值 | 看到当前结果的证据有多强? | 拿 p 值与 α 对比,决定是否拒绝 H₀ |
| 置信区间 | 效应量的范围是多大? | 判断商业可行性,决定全量还是回滚 |
实战中容易犯的三个错
我见过的团队(包括曾经的我自己)在基础知识上翻车的地方,基本上这三类:
- 多次检验不做校正:同时看 10 个指标,每个用 0.05 做阈值。整体犯错的概率就不是 0.05 了,而是 1 - (0.95)^10 ≈ 0.40。差不多一半概率出错。我建议用 Bonferroni 矫正,或者 FDR 控制。
- p-hacking:不断加样本,直到 p 值小于 0.05。这种操作会让假阳性率急剧飙升。老老实实先确定样本量再做实验。
- 忽略置信区间宽度:p 值显著但区间太宽,说明样本量不足。这时候应该加量,而不是急着上线。
用 Python 算一遍最简流程
为了让你有个直觉,我贴一段最简代码。别怕,就是算 p 值和置信区间。
import numpy as np
from scipy import stats
# 模拟数据
control = np.random.binomial(1, 0.10, size=1000) # 对照组,转化率 10%
treatment = np.random.binomial(1, 0.12, size=1000) # 实验组,转化率 12%
# 计算两样本 t 检验
t_stat, p_value = stats.ttest_ind(treatment, control)
# 计算置信区间
n1, n2 = len(control), len(treatment)
mean1, mean2 = np.mean(control), np.mean(treatment)
se = np.sqrt(mean1*(1-mean1)/n1 + mean2*(1-mean2)/n2)
diff = mean2 - mean1
z = 1.96 # 95% 置信水平的 z 值
ci_low = diff - z * se
ci_high = diff + z * se
print(f"p 值: {p_value:.4f}")
print(f"效应差 (实验组 - 对照组): {diff:.4f}")
print(f"95% 置信区间: [{ci_low:.4f}, {ci_high:.4f}]")
跑完看看输出。如果 p 值小于 0.05,且置信区间下限大于 0,那这次改动就过了统计关。
我的建议:不要只把这段代码当黑盒。把样本量改成 50、500、5000 试试。你会看到置信区间越来越窄,p 值越来越稳定。这个直觉比公式重要得多。
到这里,假设检验、p 值、置信区间这三个基础就铺好了。你想想看,它们其实是在回答三件事:
- 差异到底是不是系统性的?
- 证据有多足?
- 如果真有差异,范围在哪里?
有了这些,你才能谈下一步——怎么设计实验、怎么算样本量、怎么结合业务做上线决策。那些东西都好说,但地基在这里。