AB测试实战(二)

简介: AB测试是一种数据驱动的产品优化方法,用于比较不同版本的网页、应用界面或营销策略的效果。

AB测试实战(一)+https://developer.aliyun.com/article/1544766?spm=a2c6h.13148508.setting.14.22454f0eHFZZj3


3、AB测试代码实战

3.1 项目背景


UI设计师设计了最新的产品页面想通过页面更新提高转化率


  • 目前的转化率全年平均在13%左右


  • 目标转化率达到 15%。


  • 在新的页面上线之前,我们要通过一小部分用户上测试页面的效果, 所以需要进行A/B测试

3.2 设计实验


  • 提出假设


首先,我们要确保在项目开始时就制定了一个假设


鉴于我们不知道新设计的性能是否会比我们当前的设计更好或更差(或相同?),我们将选择双尾测试:


H 0 原假设 老的设计比较好, 新版设计没有用


H 1 备选假设 新的设计比较好


  • 选择变量


对照组: 看到旧的设计

实验组: 看到新的设计


虽然我们已经知道了旧的设计的转化率(13%左右), 但是我们依然要需要设计两组, 原因是为了避免其他因素带来的误差, 比如季节因素, 促销因素。这两组人在其它条件都相同的只是页面设计不同的情况下进行实验, 这样能保证两组间的差异是由于设计导致的


我们的设计的目标KPI是转化率, 所以,我们会添加一个字段来记录用户的购买情况


购买了产品的用户 值为1

未购买产品的用户值为0


  • 确定实验人数


AB测试只会选择一小部分用户来参与实验, 用小部分的实验结果来估计整体的结果,每组的人数越多,我们得到的结果就越精准,但同时我们付出的成本就越大,通过功效分析我们可以计算出满足实验条件的最小人群


检验功效 (1 — β) :一般设置为0.8


α :在设计实验的时候我们设置为0.05


效果大小:旧的页面转化率为13%,新页面我们希望转化率能提升2%,所以我们可以用13%和15%来计算预期效果大小


确定实验人数的计算过程可以通过Python代码实现


import numpy as np
import pandas as pd
import scipy.stats as stats
import statsmodels.stats.api as sms
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from math import ceil

%matplotlib inline


effect_size = sms.proportion_effectsize(0.13, 0.15)   

required_n = sms.NormalIndPower().solve_power(
    effect_size,
    power=0.8, 
    alpha=0.05, 
    ratio=1  
    )                                                  
#对结果向上取整
required_n = ceil(required_n)                         

print(required_n)


4720


  • 计算结果说明每组至少需要4720人
  • 在实践中将功率参数设置为 0.8 意味着如果我们的设计之间存在转化率的实际差异,假设差异是我们估计的差异(13% 对 15%),我们有大约 80% 的机会检测到它 与我们计算的样本量在我们的测试中具有统计显着性。


3.3 收集准备数据


  • 在企业场景下,我们需要与工程团队配合,收集满足要求的数据, 这里我们使用准备好的数据集, 对数据进行处理
  • 加载数据到DataFrame
  • 检查和清理数据
  • 从DataFrame中采样数据每组4720行


df = pd.read_csv('data/ab_data.csv')
df.head()



user_id
timestamp group landing_page converted
0 851104 2017-01-21 22:11:48.556739 control old_page 0
1 804228 2017-01-12 08:01:45.159739 control old_page 0
2 661590 2017-01-11 16:55:06.154213 treatment new_page 0
3 853541 2017-01-08 18:28:03.143765 treatment new_page 0
4 864975 2017-01-21 01:52:26.210827 control old_page 1


  • 查看数据基本情况


df.info()


<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
 #   Column        Non-Null Count   Dtype 
---  ------        --------------   ----- 
 0   user_id       294478 non-null  int64 
 1   timestamp     294478 non-null  object
 2   group         294478 non-null  object
 3   landing_page  294478 non-null  object
 4   converted     294478 non-null  int64 
dtypes: int64(2), object(3)
memory usage: 11.2+ MB


数据一共294478行,每一条数据代表一次用户访问,共五列:


  • user_id - 访问的用户ID
  • timestamp - 访问的时间
  • group - 该用户被放到那一组 {control对照, treatment实验}
  • landing_page -该用户看到的是哪一种落地页 {old_page老页面, new_page新页面}
  • converted - 改次访问是否有转化 (binary, 0=无转化, 1=转化)


在后续的分析中,我们实际上主要用到的是 group 和converted 这两个字段


创建透视表, 查询是否对照组看到的都是老页面


df.pivot_table(index = 'group',columns='landing_page',values = 'user_id',aggfunc='count')


anding_page new_page old_page
group
control 1928 145274
treatment 145311 1965


  • 在我们进行后续处理之前, 还要查看是否有用户进行了多次操作


session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts>1].count()
multi_users


3894


  • 说明一共有3894个用户访问了不止一次, 整体数据有20多万条, 所以我们直接把这部分数据删除


users = session_counts[session_counts < 2].index
df = df[df['user_id'].isin(users)]


数据采样


  • 接下来我们从处理后的数据中,每组采样4720条数据, 我们这里使用DataFrame的sample()方法进行简单随机采样


control_sample = df[df['group'] == 'control'].sample(n=required_n, random_state=22)
treatment_sample = df[df['group'] == 'treatment'].sample(n=required_n, random_state=22)
# 这里random_state 为随机数种子, 如果也传入22, 那么后续结果会与讲义中一样
ab_test = pd.concat([control_sample, treatment_sample], axis=0)
ab_test.reset_index(drop=True, inplace=True)
ab_test



user_id
timestamp group landing_page converted
user_id
group landing_page converted
0 763854 2017-01-21 03:43:17.188315 control old_page 0 0




1 690555 2017-01-18 06:38:13.079449 control old_page 0 1




2 861520 2017-01-06 21:13:40.044766 control old_page 0 2




3 630778 2017-01-05 16:42:36.995204 control old_page 0 3




4 656634 2017-01-04 15:31:21.676130 control old_page 0 4







9435 908512 2017-01-14 22:02:29.922674 treatment new_page 0 9435




9436 873211 2017-01-05 00:57:16.167151 treatment new_page 0 9436




9437 631276 2017-01-20 18:56:58.167809 treatment new_page 0 9437




9438 662301 2017-01-03 08:10:57.768806 treatment new_page 0 9438




9439 944623 2017-01-19 10:56:01.648653 treatment new_page 1 9439





  • 查看两组数据情况


ab_test.groupby('group')['landing_page'].value_counts()
# landing_page 落地页类型  old_page老页面 new_page 新页面
# control 控制组  treatment 对照组


group landing_page

control old_page 4720

treatment new_page 4720

Name: landing_page, dtype: int64


3.4 分析实验结果


  • 首先我们来计算一下两组的转化率和标准差


conversion_rates = ab_test.groupby('group')['converted'].mean().to_frame()
conversion_rates 

conversion_rates.style.format('{:.3f}')


group conversion_rate
control 0.123
treatment 0.126


  • 从上面的统计数据来看,旧的和新的落地页表现非常相似,新设计表现略好, 12.3% 与 12.6%


  • 从对照组的数据看, 转换率为12.3% 比之前我们的整体表现要差一些, 可能与采样人群的差异有关
  • 测试组的数据比对照组要好一些, 但是这个结果是否具有统计意义?


3.5 假设检验


  • 最后一步是假设检验, 我们的样本量比较大,可以应用Z检验来计算P值, 如果P值<0.05, 说明
  • 我们可以使用statsmodels.stats.proportion 模块来计算P值和置信区间


from statsmodels.stats.proportion import proportions_ztest, proportion_confint
control_results = ab_test[ab_test['group'] == 'control']['converted']     #获取对照组是否转化的数据
treatment_results = ab_test[ab_test['group'] == 'treatment']['converted'] #获取实验组是否转化的数据
n_con = control_results.count() # 获取对照组人数
n_treat = treatment_results.count()  # 获取实验组人数
successes = [control_results.sum(), treatment_results.sum()] # 获取实验组和对照组成功转化的人数
nobs = [n_con, n_treat]

z_stat, pval = proportions_ztest(successes, nobs=nobs)  #计算P值
(lower_con, lower_treat), (upper_con, upper_treat) = proportion_confint(successes, nobs=nobs, alpha=0.05) #计算置信区间

print(f'z statistic: {z_stat:.2f}')
print(f'p-value: {pval:.3f}')
print(f'ci 95% for control group: [{lower_con:.3f}, {upper_con:.3f}]')
print(f'ci 95% for treatment group: [{lower_treat:.3f}, {upper_treat:.3f}]')


🥂小结


AB测试的应用场景


  • 互联网行业应用广泛:页面结构调整, 换新图标,添加新功能等等
  • 实体行业应用相对复杂一些:不同优惠券效果测试


AB测试还是ABC测试


  • AB测试:一次测试一个方案
  • ABC…… 测试: 一次测试多个方案,但需要流量足够大,否则难以满足实验要求的最少人数


AB测试需要注意如下几点


  • 流量分配


  • 确定有效的最小参与人数
  • 确定基准指标和提升目标
  • 设置显著性水平α (一般是5%)和 统计功效 1-β (一般是80%)
  • 出结果之后计算P值 如果P<5% 则可以拒绝原假设算P值 如果P<5% 则可以拒绝原假设
  • 我们可以通过AB测试工具网站帮助确定人数,也可以使用statsmodels 模块来通过代码实现


  • import statsmodels.stats.api 计算需要人数
  • statsmodels.stats.proportion 计算P值和置信区间


相关文章
|
4月前
|
测试技术 持续交付 UED
软件测试的艺术:确保质量的实战策略
在软件开发的舞台上,测试是那把确保每个功能如交响乐般和谐奏响的指挥棒。本文将深入探讨软件测试的重要性、基本类型以及如何设计高效的测试策略。我们将通过一个实际的代码示例,展示如何运用这些策略来提升软件质量和用户体验。
|
16天前
|
存储 人工智能 编译器
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
37 10
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
5天前
|
数据可视化 JavaScript 前端开发
从Postman到Apipost:我的动态参数测试实战踩坑记
作为一名全栈开发工程师,在开发用户中心模块时,我遇到了复杂参数API测试的挑战。最初使用Postman时,发现其在生成动态参数(如邮箱、手机号和日期)时存在诸多问题,导致测试效率低下甚至出错。例如,随机生成的邮箱格式无效等 后来,CTO推荐了Apipost,它提供了更智能的参数生成方式:支持真实邮箱、符合规范的手机号以及合法日期范围,极大提升了测试效率和准确性。通过对比,Apipost在处理复杂动态参数方面明显优于Postman,减少了维护成本并提高了团队协作效率。现在,我们已全面切换到Apipost,并利用其「参数组合测试」功能发现了多个边界条件bug。
|
5天前
|
机器学习/深度学习 设计模式 测试技术
Python 高级编程与实战:构建自动化测试框架
本文深入探讨了Python中的自动化测试框架,包括unittest、pytest和nose2,并通过实战项目帮助读者掌握这些技术。文中详细介绍了各框架的基本用法和示例代码,助力开发者快速验证代码正确性,减少手动测试工作量。学习资源推荐包括Python官方文档及Real Python等网站。
|
12天前
|
存储 数据可视化 测试技术
一个测试工程师的实战笔记:我是如何在Postman和Apipost之间做出选择的?
优秀的API测试工具应该具备: 分层设计:既有可视化操作,也开放代码层深度定制 场景感知:自动识别加密需求推荐处理方案 协议包容:不强迫开发者为了不同协议切换工具 数据主权:允许自主选择数据存储位置
44 7
|
4月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
101 3
|
5月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
1120 1
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
4月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
113 1
|
4月前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
152 2
|
4月前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
95 2

热门文章

最新文章