案例1
A/B 测试可以用于测试网页的修改效果,测试需进行一场实验,实验中对照组为网页旧版本,实验组为网页新版本,实验还需选出一个指标 来衡量每组用户的参与度,然后根据实验结果来判断哪个版本效果更好。从以下假设来看,A/B 测试很像假设检验:
- 零假设: 新版本不比旧版本好,甚至比旧版本差
- 对立假设:新版本比旧版本好
如果我们无法推翻零假设,那得到的实验结果就会暗示我们得保留旧版本;如果我们推翻了零假设,那得到的实验结果就会暗示我们可实现网页改动。通过这些测试,我们可以观察什么样的改动能最大化指标,测试适用的改动类型十分广泛,上到增加元素的大改动,下到颜色小变动都可使用这些测试。
但 A/B 测试也有不足之处。虽然测试能帮你比较两种选择,但无法告诉你你还没想到的选择,在对老用户进行测试时,抗拒改变心理、新奇效应等因素都可能使测试结果出现偏差。
案例2
为 Audacity 分析 A/B 测试的结果,以下是该公司网站典型新用户的客户漏斗【1】模型:
浏览主页 > 探索课程 > 浏览课程概述页面 > 注册课程 > 完成课程
越深入漏斗模型,Audacity 就流失了越多的用户,能进入最后阶段的用户寥寥无几。为了提高学员参与度,提高每个阶段之间的转化率,Audacity 试着做出一些改动,并对改动进行了 A/B 测试。
针对 Audacity 想做的两个改动,我们将分析相关测试结果,并根据结果建议是否该实现那两个改动。
建立假设
Audacity 想做的第一个改动是在主页上,他们希望靠这个更吸引人的新设计来增加探索课程的用户,也就是说,增加会进入下一漏斗阶段的用户。
我们要使用的指标是主页探索课程按钮的点击率。点击率 (CTR)通常是点击数与浏览数的比例。因为 Audacity 有用 cookies,所以我们可以确认单独用户,确保不重复统计同一个用户的点击率。为了进行该实验,我们对点击率作出如下定义:
CTR: # 单独用户点击数 / # 单独用户浏览数
确定了指标,我们可以把零假设和对立假设定义如下。
: ≤
: >
对立假设即我们想证明正确的假设,本案例的对立假设就是新主页比旧主页有更高的点击率。零假设则是我们在分析数据前假设为真的假设,即新主页点击率小于或等于旧主页的点击率。正如你之前所见,我们可对假设进行如下处理:
: - ≤ 0
: - > 0
以python进行演示
- 导入库和数据
import pandas as pd
df = pd.read_csv('homepage_actions.csv')
df.head()
- 计算感兴趣的数据
# total number of actions
total_num_act = df['action'].shape[0]
total_num_act
# number of unique users
num_users = df['id'].unique().shape[0]
num_users
# size of control group and experiment group
num_e_users = df[df['group']=='experiment']['id'].unique().shape[0]
num_e_users
num_c_users = df[df['group']=='control']['id'].unique().shape[0]
num_c_users
# duration of this experiment
df_timestamp = pd.to_datetime(df['timestamp'])
df_timestamp.max() - df_timestamp.min()
# action types in this experiment
df['action'].unique()
主要步骤:
- 导入数据和库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline
np.random.seed(42)
df = pd.read_csv('course_page_actions.csv')
df.head()
- 计算了对照组和实验组的指标观察差异,即点击率;
# Get dataframe with all records from control group
control_df = df.query('group == "control"')
# Compute click through rate for control group
control_ctr = control_df.query('action == "enroll"').id.nunique() / control_df.query('action == "view"').id.nunique()
# Display click through rate
control_ctr
# Get dataframe with all records from experiment group
experiment_df = df.query('group == "experiment"')
# Compute click through rate for experiment group
experiment_ctr = experiment_df.query('action == "enroll"').id.nunique() / experiment_df.query('action == "view"').id.nunique()
# Display click through rate
experiment_ctr
# Compute the observed difference in click through rates
obs_diff = experiment_ctr - control_ctr
# Display observed difference
obs_diff
# Create a sampling distribution of the difference in proportions
# with bootstrapping
diffs = []
size = df.shape[0]
for _ in range(10000):
b_samp = df.sample(size, replace=True)
control_df = b_samp.query('group == "control"')
experiment_df = b_samp.query('group == "experiment"')
control_ctr = control_df.query('action == "enroll"').id.nunique() / control_df.query('action == "view"').id.nunique()
experiment_ctr = experiment_df.query('action == "enroll"').id.nunique() / experiment_df.query('action == "view"').id.nunique()
diffs.append(experiment_ctr - control_ctr)
diffs[0]
- 为比例差异 (即点击率差异)建立了抽样分布 模型;
# Convert to numpy array
diffs = np.array(diffs)
# Plot sampling distribution
plt.hist(diffs);
- 用这个抽样分布模型来为零假设分布建立模型,也即创建了一个随机正态分布模型,模型以 0 为中心,大小和宽度与抽样分布的一样。
# Simulate distribution under the null hypothesis
null_vals = np.random.normal(0,diffs.std(),diffs.size)
# Plot the null distribution
plt.hist(null_vals);
- 通过找出零假设分布中大于观察差异的那部分比值,从而计算出了 p 值;
# Plot observed statistic with the null distibution
plt.hist(null_vals);
plt.axvline(x=obs_diff, color='red')
# Compute p-value
(null_vals > obs_diff).mean()
- 我们用 p 值来确定观察差异是否有 统计显著性。
分析多个指标
实例
假设有四个指标及其p值:
- 册率: 0.0159
- 平均浏览时长: 0
- 平均教室逗留时长: 0.0384
- 完成率: 0.0363
如果原显著值为 0.05,那经由 Bonferroni 校正后的新显著值是0.0125。
只有平均浏览时长仍有统计显著性。
关于这些因素,稍后你会得到进一步的了解。
A/B 测试难点
正如你在上述情景看到的,设计 A/B 测试、基于测试结果得出结论都需要考虑诸多因素。下方总结了一些常见考虑因素:
- 老用户第一次体验改动会有新奇效应和改变抗拒心理。老用户可能会因为纯粹不喜欢改变而偏爱旧版本,哪怕从长远来看新版本更好。
- 新奇效应:老用户可能会觉得变化很新鲜,受变化吸引而偏爱新版本,哪怕从长远看来新版本并无益处。
- 要得到可靠的显著结果,需要有足够的流量和转化率。
实验:Audacity 有一门课程很难,注册率也很低,所以为该课程写了新描述,并进行了测试。Audacity 希望新描述能更激动人心,鼓励更多学生前来注册。在进行了为期五周的 A/B 测试后,Audacity 发现新描述组的注册率上升了,于是决定更改描述。
现实: 他们不知道的是,虽然新描述组的注册率看起来变高了,但这次 A/B 测试的结果并不可靠,因为随机性太高了,在本次试验中,数千名访客中只有 40 人进行了注册,因此就算课程只增加一名新学员,结果也会受到相当大的影响,甚至可能影响结论。
- 要做出最佳决策,需选用最佳指标(如营收 vs 点击率)。
- 应进行足够的实验时长,以便解释天/周/季度事件引起的行为变化。
- 转化率需具备现实指导意义(推出新元素的开支 vs 转化率提高带来的效益)。
- 对照组和实验组的测试对象要有一致性(两组样本数失衡会造成等现象的发生)。