A/B-test
A/B-test称为A/B测试(也称为分割测试或桶测试),是一种对比分析方法,通过对流量进行细分和随机实验,排除其他因素的干扰,并监控和跟踪实验效果,来判断实验所代表的策略的可行性和有效性。其本质上是一个实验,其中将版本或者页面的两个或多个变体随机显示给用户,统计分析确定哪个变体对于给定的转换目标(指标如CTR)效果更好,从而科学的帮助产品进行决策。

A/B-test原理
A/B-test的本质,是一个假设检验问题。在统计学角度上,用样本代表全体,始终存在着统计显著性的问题。在一定程度内的数据差别是属于正常的波动,并不能说明某个版本更优。通常a/b-test会进行显著性检验。
假设现需要从A、B两种方案中选择一种进行落地实施,那么可以将用户群分为两个部分,用户群1使用A方案,用户群2使用B方案,使用A方案的人数记为,使用B方案的人数记为。通过样本计算出A方案的用户次日留存率,B方案的用户次日留存率,用样本的次日留存率、估计总体的次日留存率、。则:总体A的分布A~,总体B的分布B~,(因为用户只有留存和不留存两种情形,因此,可以认为服从期望为P的二项分布)。
由二项分布的性质及中心极限定理可知,当A、B方案的用户群样本量足够大时, 其样本均值服从正态分布,~,~, 根据正态分布的性质可知:~。
建立假设
<->
构建统计量
由于总体方差未知,根据假设检验的相关知识可知可以构建 检验
根据原假设,我们只需检验 的情况即可得出结 论,因为 足够大的情况下, 分布可以近似于正态分布, 可以直接以正态分布的 Z 检验进行假设检验。上式即:
构造完统计量之后,即可根据假设检验的相关知识进行计算 值,与给定的显著性水平进行比较,得出结论。
A/B-test的使用误区
误区一:轮流展现不同版本
| 正确做法:不同版本方案并行(同时)上线试验,尽可能的降低所有版本的测试环境差别。 |
误区二:选择不同应用市场投放(随机选取用户测试)
| 正确做法:科学的进行流量分配,保证每个试验版本的用户特征相类似。 |
误区三:让用户自主选择版本
| 正确做法:让用户展现对不同版本的真实使用体验,企业则应实时关注各版本的数据表现,并根据数据反馈及时调整试验流量。 |
误区四:对试验结果的认知和分析过浅 这一误区又包括了两个不同的内容:其一,认为只有当试验版本结果优于原始版本时,试验才算成功。其二,单从试验的整体数据结果,就推论所有场景的表现效果。
| 正确做法:在分析试验整体数据的同时,需要从多个维度细分考量试验数据结果。 |
流量分级
每个团队的模型分级策略并不相同,这里只给出一个建议模型流量分级:
基线流量。本流量用于与其他流量进行对比,以确定新模型的效果是否高于基准线,低于基准线的模型要快速下线。另外,主力流量相对基线流量的效果提升也是衡量算法团队贡献的重要指标。
主力流量。主力流量只有一个,即稳定运行效果最好的流量。如果某个潜力流量长期好于其他潜力流量和主力流量,就可以考虑把这个潜力流量升级为主力流量。
实验流量。该流量主要用于新实验模型。该流量大小设计要注意两点:第一不能太大而伤害线上效果;第二不能太小,流量太小会导致方差太大,不利于做正确的效果判断。
潜力流量。如果实验流量在一定周期内效果比较好,可以升级到潜力流量。潜力流量主要是要解决实验流量方差大带来的问题。
做实验的过程中,需要避免新实验流量对老模型流量的冲击。流量群体对于新模型会有一定的适应期,而适应期相对于稳定期的效果一般会差一点。如果因为新实验的上线而导致整个流量群体的模型都更改了,从统计学的角度讲,模型之间的对比关系没有变化。但这可能会影响整个大盘的效果,成本很高。
AB-test步骤
AB-test分为以下几个步骤:
1:基于现状和期望,分析并提出假设
2:设定目标制定方案
3:设计与开发
4:分配流量进行测试
5:埋点采集数据
6:实验后分析数据
7:发布新版本/改进设计方案/调整流量继续测试
实例分析
数据来源:kaggle--该数据是一个手游的AB-test结果
字段名称:
userid--用户id
version:版本区别 A:gate_30 B:gate_40
sum_gamerounds:安装后14天内,玩家玩的游戏回合数。
retention_1:次日留存率
retention_7:7日留存率
分析目的:根据假设检验的统计学原理确认哪个项目表现更好
import numpy as np
import pandas as pd
import statsmodels.stats.proportion as ssp
#读取数据
data = pd.read_csv('Python\\ABtest\\cookie_cat.csv')
print(data.head())
| userid | version | sum_gamegrounds | retention_1 | retention_7 | |
|---|---|---|---|---|---|
| 0 | 116 | gate_30 | 3 | False | False |
| 1 | 337 | gate_30 | 38 | True | False |
| 2 | 377 | gate_40 | 165 | True | False |
| 3 | 483 | gate_40 | 1 | False | False |
| 4 | 488 | gate_40 | 179 | True | True |
#检查是否存在空缺值
print(data.isnull().sum())
#检查是否存在重复值
print(data.duplicated().sum())
#检查是否存在异常值
print("version:",data.version.unique())
print("retention_1:",data.retention_1.unique())
print("retention_7:",data.retention_7.unique())
| userid | 0 |
| version | 0 |
| sum_gamerounds | 0 |
| retention_1 | 0 |
| retention_7 | 0 |
| dtype:int64 | 0 |
version:['gate_30' 'gate_40'] | |
|---|---|
retention_1:[False True] | |
retention_7:[False True] |
#提取分析所需数据
retention = data.groupby('version').agg({'userid':'count','retention_1':sum,'retention_7':sum})
print(retention)
# 各方法的留存率
retention_rate = pd.DataFrame(index = ['gate_30','gate_40'],columns = ['次日留存率','七日留存率'])
for i in range(0,2):
retention_rate.iloc[i,1] = retention.iloc[i,2] / retention.iloc[i,0]
retention_rate.iloc[i,0] = retention.iloc[i,1] / retention.iloc[i,0]
print(retention_rate)
| version | userid | retention_1 | retention_7 |
|---|---|---|---|
| gate_30 | 44700 | 20034 | 8502 |
| gate_40 | 45489 | 20119 | 8279 |
| 次日留存率 | 七日留存率 | |
|---|---|---|
| gate_30 | 0.448188 | 0.190201 |
| gate_40 | 0.442283 | 0.182 |
可以看出A方案(gate_30)无论是次日留存率还是七日留存率都要优于B方案(gate_40)接下来进行显著性测试确保我们的测试不是因为偶然因素。
#次日留存率
z_score, p_value = ssp.proportions_ztest(count = retention.retention_1, nobs = retention.userid, alternative='smaller')
print("次日留存率--Z值为:", z_score)
print("次日留存率--P值为:", p_value)
#七日留存率
z_score, p_value = ssp.proportions_ztest(count = retention.retention_7, nobs = retention.userid, alternative='smaller')
print("七日留存率--Z值为:", z_score)
print("七日留存率--P值为:", p_value)
| 次日留存率——Z值为:1.7840862247974725 |
| 次日留存率——P值为:0.9627951723515404 |
| 七日留存率——Z值为:3.164358912748191 |
| 七日留存率——P值为:0.9992228750121929 |
次日留存率P值为96.3%,七日留存率为99.9%,均大于(1-α == 0.95),无法拒绝原假设。所以我们可以得出结论A方案(gate_30)的效果好于B方案(gate_40)。
补充资料:
https://pan.baidu.com/s/12AccXSZw_Sgm7NSCaJLJdw
提取码:jorr






