3、随机对照试验(RCT):黄金标准,AB测试原理,随机化的作用与局限性

聊到因果推断,绕不开的一个话题就是随机对照试验,也就是我们常说的 RCT。在用户增长领域,它还有个更接地气的名字——AB 测试。

我个人习惯把 RCT 叫做「因果推断的黄金标准」。为什么是黄金?因为它从根上解决了因果推断最头疼的问题:混淆变量。你想想看,我们做数据分析时,最怕什么?最怕看到 A 和 B 相关,但搞不清到底是谁导致了谁。RCT 就是用来切断这种模糊关系的。

AB 测试的核心原理

AB 测试的原理其实特别简单。你把用户随机分成两组:一组看到新功能(实验组),一组看到旧版本(对照组)。然后比较两组的关键指标差异。

这里的关键词是「随机」。随机化保证了什么呢?它保证了在理想情况下,两组用户在除了实验变量之外的所有特征上都是「统计上等价的」。年龄、性别、历史行为、设备型号……这些乱七八糟的东西,理论上在两组之间是均匀分布的。

我在项目中遇到过这样一个场景:产品经理想测试一个新推荐算法,直接拿老用户做了个灰度发布。结果发现实验组指标涨了 10%,大家都很兴奋。但我一看数据,实验组里高活跃用户占比明显偏高。说白了,这不是算法厉害,是用户本身就不一样。这就是没有做好随机化的典型翻车案例。

核心要点: 随机化的本质是消除选择偏差,让「处理组」和「对照组」在干预前是可比的。

随机化的作用:它到底解决了什么?

随机化的作用,我总结为三点:

  1. 消除混淆变量:这是最核心的。随机化让所有已知和未知的混淆变量在两组间分布均衡。你不需要去「控制」什么,随机化替你做了。
  2. 保证因果方向:因为干预是随机分配的,所以因果方向是确定的——是干预导致了结果变化,而不是反过来。
  3. 简化统计推断:有了随机化,你直接用 t 检验或卡方检验就能比较两组差异,不需要复杂的因果模型。

嗯,这里要注意一点。随机化不是万能的,它解决的是「内部有效性」问题,也就是你能确定这个因果效应在实验环境下是成立的。但「外部有效性」——也就是这个结论能不能推广到其他人群——那是另一个话题了。

随机化的局限性:黄金标准也有软肋

做增长久了你会发现,RCT 在实际落地中处处是坑。我曾经踩过不少,今天帮你梳理一下。

局限性一:成本高,周期长
做一次完整的 AB 测试,从设计、开发、上线到收集足够样本,往往需要几周甚至几个月。对于快速迭代的增长团队来说,这个节奏有时候跟不上。
局限性二:伦理和公平性问题
你不能为了做实验,故意给一部分用户推送糟糕的体验。比如你想测试「降低优惠券金额是否影响转化率」,那对照组用户可能就白白损失了优惠。这在增长实践中是需要谨慎对待的。
局限性三:网络效应和干扰
社交类产品最头疼这个问题。如果实验组和对照组的用户是好友,他们之间会互相影响。你给 A 组用户开放了新功能,A 组用户可能分享给 B 组用户看,这就污染了对照组。我管这叫「实验污染」,处理起来很麻烦。
局限性四:无法处理长期效应
大多数 AB 测试只跑一两周。但有些干预的效果是滞后的,比如新用户引导流程的优化,可能三个月后才会体现在留存上。短期 AB 测试根本看不出来。

一个简单的 AB 测试模拟

为了让你更直观地理解,我写个简单的 Python 模拟。假设我们想测试一个新按钮颜色是否提升了点击率。

import numpy as np
from scipy import stats

# 设置随机种子,保证结果可复现
np.random.seed(42)

# 模拟 10000 个用户,随机分配到两组
n_users = 10000
group = np.random.binomial(1, 0.5, n_users)  # 0: 对照组, 1: 实验组

# 对照组真实点击率 10%,实验组真实点击率 12%
control_ctr = 0.10
treatment_ctr = 0.12

# 生成点击数据
clicks = np.where(
    group == 0,
    np.random.binomial(1, control_ctr, n_users),
    np.random.binomial(1, treatment_ctr, n_users)
)

# 计算两组点击率
control_clicks = clicks[group == 0]
treatment_clicks = clicks[group == 1]

control_rate = control_clicks.mean()
treatment_rate = treatment_clicks.mean()

print(f"对照组点击率: {control_rate:.4f}")
print(f"实验组点击率: {treatment_rate:.4f}")
print(f"提升幅度: {(treatment_rate - control_rate) / control_rate * 100:.2f}%")

# 统计检验
t_stat, p_value = stats.ttest_ind(treatment_clicks, control_clicks)
print(f"p 值: {p_value:.4f}")

运行这段代码,你会看到实验组点击率确实比对照组高,而且 p 值通常小于 0.05,说明这个差异在统计上是显著的。这就是 RCT 的威力——你不需要控制任何东西,随机化已经帮你搞定了。

知识体系结构图

下面这张图总结了 RCT 的核心逻辑,我建议你保存下来,做实验前看一眼,能帮你避开不少坑。

RCT / AB测试核心逻辑 目标用户群体 随机化分配 对照组(旧版本) 实验组(新功能) 观察指标(如点击率) 观察指标(如点击率) 统计比较 因果结论:新功能是否有效? 局限性:成本高 | 伦理问题 | 网络效应 | 无法处理长期效应

避坑指南

最后,分享几个我踩过的坑,希望能帮你省点时间。

避坑一:样本量不够就别跑
我曾经做过一个实验,跑了两周,结果不显著。后来一算,样本量至少需要 5 万用户,我只有 1 万。说白了,样本量不够,再好的随机化也救不了你。跑之前先用样本量计算器算一下。
避坑二:注意「新奇效应」
用户刚看到新功能时,可能会因为新鲜感而点击。但过两周就腻了。我建议 AB 测试至少跑够一个完整的业务周期,比如一周或两周,别只看头三天的数据。
避坑三:多重比较问题
如果你同时看 10 个指标,纯随机波动下,大概率会有一个指标「显著」。我习惯的做法是:先定好一个核心指标(Primary Metric),其他指标只做参考,不做决策依据。

好了,关于 RCT 和 AB 测试的核心内容就这些。记住一句话:随机化是你的朋友,但它不是万能的。理解它的作用和局限,你才能在增长实践中用好这个工具。


专注资料整理