先概括一下:本文主要阐述了A/Btest中组间差异的比率检验(单比率检验,双比率检验),统计功效,以及何通过显著性水平还有统计功效反实验所需选样本量。使用python对着三个功能进行实现,并封装成类,方便直接调用。如果A/B test中包含多组人群,可以两两进行比较,也可以直接利用方差分析判断不同组间是否存在差异(方差分析建立在样本独立,正态分布和方差齐性假设上,但实际上随机抽样时,样本独立,方差分析中F检验对正态分布不敏感,且方差不差太多(2倍以上)方差分析的结果基本都可以认为是有效的)。

一、A/B test

在产品发布,运营等场景我们都会遇到A/B test。A/B test通常为同一个目标,设计两种方案,将两种方案随机投放市场中。

A/B test让组成成分相同(相似)用户去随机体验两种方案之一,根据观测结果,判断哪个方案效果更好,结果可以通过CTR或者下单率来衡量。最终我们选择CTR或者下单率更优的版本作为线上应用的版本。

现实场景中我们避不开几个问题:

  1. A/B test两组人群的转化效果是否存在差异——假设检验
  2. 我们正确判断出A/B test两组人群有差异的把握有多大——统计功效
  3. 在一定显著性水平和和统计功效下,我们需要选定多少样本量进行试验——反选样本量

上面3个问题对顺利进行A/B test至关重要,在网上找到了一个很好的课件,还有一些具体的例子,非常容易理解。下面结合课件对这三个问题进行阐述。

关于三者的求解,本文利用python从底层进行了实现。其实网上有很多统计软件。但是共感觉有点杂乱,于是照着原理从底层编写,按照自己的方式编写后感觉清爽了很多。

一、单比率检验

对于A/B test中两组人群的对比中,我们需要对比的是ctr,转化率等指标。而ctr,用户转化率等指标,都是01分布,即二项分布。因此可以使用比率检验的方法进行假设检验。如果A/B test中包含多组人群,可以两两进行比较,也可以直接利用方差分析组间差异的判断。

1.1.单比率检验
现在有这样一种情景,我们新发布了一个版本或新上了一个活动,并选了一批人进行试验,我们想要知道发布了这个版本或新上活动后新的样本是否和原来有明显差异。我们可以使用单比率检验。(与平常假设检验无差别。构造统计量,看统计量是否在拒绝域内。正常是T统计量,这里由于是二项分布,n*p>5时可以认为是正态分布,即Z统计量)


接下来是单比率检验的一个简单例子:
1.2.单比率检验的统计功效
在上面我们阐述了在显著性水平α\alphaα下一组样本的统计指标是否与原来存在差异的方法。在概率统计中,我们知道,假设检验中有两类错误,第一类错误是“弃真”,即当零假设正确时,我们拒绝的概率,记为α\alphaα;第二类错误是“纳伪”,即零假设错误时,我们却没有拒绝的概率记为β\betaβ

由定义可知上面的α\alphaα和β\betaβ都是关于零假设的条件概率,实际上我们所说的显著性水平对应的就是第一类错误概率α\alphaα。

现在假设我们再比较一组样本与另一组是否存在差异时,我们拒绝了零假设,即认为两组有差异,我们需要进一步知道我们正确拒绝了零假设的概率powerpowerpower,我们把这个概率叫做统计功效

实际上统计功效powerpowerpower就是1-零假设错误时,我们却没有拒绝的概率(第二类错误概率)。即power=1−βpower=1-\betapower=1−β

1.3. 反选样本量
在实验室,我们总会预先设定一个显著性水平α\alphaα和统计功效β\betaβ。根据上面统计功效的公式,实际上我们可以反推出我们需要的样本量:

二、双比率检验

在A/B test是,我们同上的做法是在同一层试验中,选用两个或多个版本(活动)进行同时实现,此时我们需要比较两组样本的差异性。于是我们就需要用到双比率检验

2.1.双比率检验

下面是双比率检验一个简单的例子:

2.2.双比例检验的统计功效

与前面所说的统计功效一样,这里我们比较两组样本时的统计功效:



2.3. 双比例检验反选样本数
注意:下面例子的反求样本数量的计算出现错误,读者可以自行计算。我这里重新求出来下面两个例子的结果是1782和15022。



实际上根据样本的分布、是否相互独立,方差是否已知等条件,反求样本量的方法如下:

(上图来自https://www.datasciencecentral.com/profiles/blogs/determining-sample-size-in-one-picture)

三、比率检验、统计功效以及反选样本量的python实现

本文利用python从底层进行了实现,并针对课件上的例子进行了求解。

其实网上有很多统计软件。但是共感觉有点杂乱,于是照着公式从底层编写,按照自己的方式编写后感觉清爽了很多,可以直接对接其他程序联合使用。

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 31 13:53:28 2019@author: nbszg
"""
import math as m
import numpy as np
import scipy.stats as stclass AB_test_ratio_test(object):def single_Z_test(self, p_theta, p_real, sample_n, alpha=0.05, method='two sides'):'''输入参数,输出样本指标是否与原来(总体)相同p_theta:新样本组(实验组)的转化率,点击率等p_real:原来的的转化率,点击率等sample_n:新样本组(实验组)的样本容量alpha:显著性水平method:检测区间,有'two sides'、'one sides larger'、'one sides smaller'三种,代表双侧,右侧和左侧检验return 是否可以拒绝原假设和统计量Z值'''# 构造Z统计量Z = (p_theta - p_real) / m.sqrt(p_real * (1 - p_real) / sample_n)# 我们总是希望拒绝H0!!!# H0:p_theta=p_real, H1:p_theta!=p_realif method == 'two sides':if abs(Z) > st.norm.ppf(1 - alpha / 2):return "Z is: {} , refuse H0, there's difference between p_theta and p_real".format(Z)else:return "Z is: {} ,can't refuse H0".format(Z)# H0:p_theta<=p_real, H1:p_theta>p_realelif method == 'one sides larger':if Z > st.norm.ppf(1 - alpha):return "Z is: {} , refuse H0, p_theta is larger than p_real".format(Z)else:return "Z is: {} , can't refuse H0".format(Z)# H0:p_theta>=p_real, H1:p_theta<p_realelif method == 'one sides smaller':if Z < st.norm.ppf(alpha):return "Z is: {} , refuse H0, p_theta is smaller than p_real".format(Z)else:return "Z is: {} , can't refuse H0".format(Z)else:raise ValueError("there's no method named: {0}".format(method))def single_power_cul(self, p_theta, p_real, sample_n, alpha=0.05, method='two sides'):'''输入参数,输出统计功效p_theta:新样本组(实验组)的转化率,点击率等p_real:原来的的转化率,点击率等sample_n:新样本组(实验组)的样本容量alpha:显著性水平method:检测区间,有'two sides'、'one sides larger'、'one sides smaller'三种,代表双侧,右侧和左侧检验return 检验的统计功效power'''# 求总体sigmasigma_p = m.sqrt(p_real * (1 - p_real) / sample_n)# 求B组s_p = m.sqrt(p_theta * (1 - p_theta) / sample_n)#power of p_theta!=p_realif method == 'two sides':fai_right = 1 - st.norm.cdf((p_real - p_theta + st.norm.ppf(1 - alpha / 2) * sigma_p) / s_p)fai_left = st.norm.cdf((p_real - p_theta - st.norm.ppf(1 - alpha / 2) * sigma_p) / s_p)power = fai_right + fai_left#power of p_theta>p_realelif method == 'one sides larger':fai_right = 1 - st.norm.cdf((p_real - p_theta + st.norm.ppf(1 - alpha) * sigma_p) / s_p)power = fai_right#power of p_theta<p_realelif method == 'one sides smaller':fai_left = st.norm.cdf((p_real - p_theta - st.norm.ppf(1 - alpha) * sigma_p) / s_p)power = fai_leftelse:raise ValueError("there's no method named: {0}".format(method))return powerdef single_sample_n(self, p_theta, p_real, alpha=0.05, beta=0.9, method='two sides'):'''输入参数,输出统计功效p_theta:新样本组(实验组)的转化率,点击率等p_real:原来的的转化率,点击率等alpha:显著性水平beta:想要到达的功效powerreturn 达到检验功效所需要的最小样本量'''# 先求分母denominator = pow(2 * m.asin(m.sqrt(p_real)) - 2 * m.asin(m.sqrt(p_theta)), 2)# H0:p_theta=p_real, H1:p_theta!=p_realif method == 'two sides':numerator = pow(st.norm.ppf(1 - alpha / 2) + st.norm.ppf(beta), 2)sample_n = numerator / denominatorelif method == 'one sides larger' or method == 'one sides smaller':numerator = pow(st.norm.ppf(1 - alpha) + st.norm.ppf(beta), 2)sample_n = numerator / denominatorelse:raise ValueError("there's no method named: {0}".format(method))return sample_ndef two_Z_test(self, p_theta, p_gamma, sample_theta, sample_gamma, alpha=0.05, method='two sides', d=0):'''输入参数,输出两个总体的转化率,点击率是否可以认为不同p_theta:样本组1(对照组A)的转化率,点击率等p_gamma:样本组2(实验组B)的转化率,点击率等sample_theta:样本组1(对照组A)样本容量sample_gamma:样本组2(实验组B)样本容量alpha:显著性水平method:检测区间,有'two sides'、'one sides larger'、'one sides smaller'三种,代表双侧,右侧和左侧检验d:样本组1(对照组A)和样本组2(实验组B)的设定差异return 样本组1(对照组A)和样本组2(实验组B)的转化率,点击率是否存在差异和统计量Z'''# 构造Z统计量Z = (p_theta-p_gamma-d) / m.sqrt((p_theta*(1-p_theta)/sample_theta) + (p_gamma*(1-p_gamma)/sample_gamma))# 我们总是希望拒绝H0!!!# H0:p_theta=p_gamma, H1:p_theta!=p_gammaif method == 'two sides':if abs(Z) > st.norm.ppf(1 - alpha / 2):return "Z is: {} , refuse H0, there's difference between p_theta and p_gamma".format(Z)else:return "Z is: {} , can't refuse H0".format(Z)# H0:p_theta<=p_real, H1:p_theta>p_gammaelif method == 'one sides larger':if Z > st.norm.ppf(1-alpha):return "Z is: {} , refuse H0, p_theta is larger than p_gamma".format(Z)else:return "Z is: {} , can't refuse H0".format(Z)# H0:p_theta>=p_real, H1:p_theta<p_gammaelif method == 'one sides smaller':if Z < st.norm.ppf(alpha):return "Z is: {} , refuse H0, p_theta is smaller than p_gamma".format(Z)else:return "Z is: {} , can't refuse H0".format(Z)else:raise ValueError("there's no method named: {0}".format(method))def two_power_cul(self, p_theta, p_gamma, sample_theta, sample_gamma, alpha=0.05, method='two sides', d=0):'''输入参数,输出两个总体的差异检验的统计功效p_theta:样本组1(对照组A)的转化率,点击率等p_gamma:样本组2(实验组B)的转化率,点击率等sample_theta:样本组1(对照组A)样本容量sample_gamma:样本组2(实验组B)样本容量alpha:显著性水平method:检测区间,有'two sides'、'one sides larger'、'one sides smaller'三种,代表双侧,右侧和左侧检验d:样本组1(对照组A)和样本组2(实验组B)的设定差异return 样本组1(对照组A)和样本组2(实验组B)的差异检验的统计功效power'''sigma_denominator = m.sqrt((p_theta*(1-p_theta)/sample_theta) + (p_gamma*(1-p_gamma)/sample_gamma))p_avg = (p_theta+p_gamma)/2sigma_numerator = m.sqrt(2*p_avg*(1-p_avg)/((sample_theta+sample_gamma)/2))#power of p_theta!=p_gamma + dif method == 'two sides':fai_right = 1 - st.norm.cdf((p_gamma + d - p_theta + st.norm.ppf(1-alpha/2) * sigma_numerator) / sigma_denominator)fai_left = st.norm.cdf((p_gamma + d - p_theta - st.norm.ppf(1-alpha/2) * sigma_numerator) / sigma_denominator)power = fai_right + fai_left#power of p_theta>p_gamma + delif method == 'one sides larger':fai_right = 1 - st.norm.cdf((p_gamma + d - p_theta + st.norm.ppf(1-alpha) * sigma_numerator) / sigma_denominator)power = fai_right#power of p_theta<p_gamma + delif method == 'one sides smaller':fai_left = st.norm.cdf((p_gamma + d - p_theta - st.norm.ppf(1-alpha) * sigma_numerator) / sigma_denominator)power = fai_leftelse:raise ValueError("there's no method named: {0}".format(method))return powerdef two_sample_n(self, p_theta, p_gamma, alpha=0.05, beta=0.9, method='two sides'):'''输入参数,输出两个总体的差异检验的统计功效p_theta:样本组1(对照组A)的转化率,点击率等p_gamma:样本组2(实验组B)的转化率,点击率等alpha:显著性水平beta:想要到达的功效powermethod:检测区间,有'two sides'、'one sides larger'、'one sides smaller'三种,代表双侧,右侧和左侧检验d:样本组1(对照组A)和样本组2(实验组B)的设定差异return 每个样本组的所需的最小样本数'''# 先求分母denominator = pow(2 * m.asin(m.sqrt(p_gamma)) - 2 * m.asin(m.sqrt(p_theta)), 2)# H0:p_theta=p_real, H1:p_theta!=p_realif method == 'two sides':numerator = 2 * pow(st.norm.ppf(1 - alpha/2) + st.norm.ppf(beta), 2)sample_n = numerator / denominatorelif method == 'one sides larger' or method == 'one sides smaller':numerator = 2 * pow(st.norm.ppf(1 - alpha) + st.norm.ppf(beta), 2)sample_n = numerator / denominatorelse:raise ValueError("there's no method named: {0}".format(method))return sample_nif __name__=='__main__':ratio_test = AB_test_ratio_test()print('example1 Z test is:', ratio_test.single_Z_test(0.018, 0.02,sample_n=500,  method='two sides'),'\n')print('example1 power is:', ratio_test.single_power_cul(0.018, 0.02,sample_n=500,  method='two sides'),'\n')print('example2 need sample is:', ratio_test.single_sample_n(0.018, 0.02,  method='two sides'),'\n')print('example3 Z test is:', ratio_test.two_Z_test(0.18, 0.2,sample_theta=1600,sample_gamma=2000,  method='two sides'),'\n')print('example4 Z test is:', ratio_test.two_Z_test(0.18, 0.2,sample_theta=1600,sample_gamma=2000,  method='two sides'),'\n')print('example5 Z test is:', ratio_test.two_Z_test(0.025, 0.007,sample_theta=3000,sample_gamma=3000,  method='one sides larger', d=0.005),'\n')print('example5 power is:', ratio_test.two_power_cul(0.025, 0.007,sample_theta=3000,sample_gamma=3000,  method='one sides larger'),'\n')print('example6 power is:', ratio_test.two_power_cul(0.025, 0.007,sample_theta=3000,sample_gamma=3000,  method='one sides larger', d=0.005),'\n')print('example7 need sample is:', ratio_test.two_sample_n(0.025, 0.012, method='one sides larger'),'\n')print('example8 need sample is:', ratio_test.two_sample_n(0.025, 0.02, method='one sides larger'),'\n')

程序运行结果如下:

对比课件中的结果,除去计算精度误差,结果可以认为与课件中是相等的。

参考文献:
假设检验与样本数量分析④——单比率检验、双比率检验

A/Btest:组间的差异性检验,统计功效以及反选样本量,附python底层实现代码相关推荐

  1. 两组回归系数差异检验_【stata系列】——组间系数差异检验

    01  组间系数差异检验是什么? 组间系数差异检验可以用于横截面中产权性质分析.高低分组分析等,在DID模型里也可用于检验post=0(或post=1)时组间系数差异,需要说明的是,DID模型里如果只 ...

  2. Stata:自己动手做组间系数差异检验-bootstrap-bdiff

    全文阅读:Stata:自己动手做组间系数差异检验-bootstrap-bdiff| 连享会主页 目录 1. 引言 2. bootstrap 命令 3. 第一种思路 3.1 导入数据和变量设定 3.2 ...

  3. 统计学(三):置信区间; Z 检验(样本平均数的假设检验), 均值分布, 附Python实现(大牌护肤品碧欧泉背后的秘密)

    引言   本篇博文开始前,请熟知如下链接中的概念:当然,如果直接开始,遇到遗忘的统计学名词再返回查找也没问题. 统计学(二):假设检验导论 (深入浅出超详解,附Python 代码):置信区间与 Z 检 ...

  4. 两个PDF比较标出差异_[连玉君专栏]如何检验分组回归后的组间系数差异?

    连玉君 (中山大学岭南学院金融系) Stata连享会   主页 || 视频 || 推文 连享会-知乎推文列表 Note: 助教招聘信息请进入「课程主页」查看. 因果推断-内生性 专题 ⌚ 2020.1 ...

  5. Stata:多个变量组间均值\中位数差异检验

    2019暑期Stata现场班,7.17-26日,北京,连玉君+刘瑞明 主讲     作者:韩少真(西北大学) || 刘婉青(西北大学) Stata 连享会: 知乎 | 简书 | 码云 | CSDN   ...

  6. Stata | 分组回归系数差异性检验

    这篇博客介绍的是在两个样本组的模型设定是一样的情形下,进行分组回归后,比较相同变量中二者在系数大小上是否显著差异.如果系数差异显著,则说明二者在经济意义上显著差异. 因为我们常常使用的数据是面板数据, ...

  7. R可视化:箱线图加蜜蜂图展示组间数据分布

    介绍 数据组间分布可视化可通过boxplot再叠加蜜蜂图beeswarm,可以更为直观展示数据分布在组间的差异性. 本文旨在通过使用R代码实现上述可视化. 加载R包 可通过install.packag ...

  8. 【统计学习】一篇文章理解什么是组间差异检验

    理解什么是组间差异检验 参数检验与非参数检验 抽样分布 展示差异的常用图表 箱线图(boxplot) 散点图(Scatter plot) 热图(heatmap) 树状图 如何寻找差异? 基于类别标签的 ...

  9. R统计计算--差异性检验

    假设检验 差异性检验: t检验.秩和检验(如wilcox检验).Kolmogorov-Smirnov检验 组间差异检验:方差分析.Fisher检验.卡方检验 相关性分析:相关性检验(pearson.s ...

  10. graphpad如何检测方差齐_SPSS和GraphPad如何比较组内和组间差异「杏花开生物医药统计」...

    在生物医药统计分析中,经常会遇到这样一类问题.样本分了实验组和对照组,而又同时进行了一种干预手段,在干预前和干预后进行了分别测量数据.这时候既要考虑实验组和对照组之间的比较,又要考虑干预前和干预后的对 ...

最新文章

  1. 安永创新中心落子北京,聚焦5G技术赋能企业数字化转型
  2. Linux修改主机名的两种方法
  3. 汇编语言中,DS与BX有何区别?怎么搭配使用?(BX是通用寄存器)
  4. 判断远程图片是否存在的JavaScript代码
  5. C++提取PDF页成BMP图片
  6. 原型模式——创建型模式
  7. 【CSU - 1004】Xi and Bo(并查集,裸题)
  8. 远程登录的几种方式对比
  9. 2021内容行业研究报告
  10. python属性和方法的区别_Python中几种属性访问的区别与用法详解
  11. Some Knowledge
  12. 牛人三个月内花不到 5000 美元拿到 CS 学位
  13. 唐纳德 高德纳给年轻人的建议 Donald Knuth - My advice to young people
  14. HDFView 把 JPG 图片转换成 HDF5 格式文件
  15. 极域课堂管理系统软件如何取消控制_极域新品发布会圆满落幕,你想看的都在这里...
  16. 4字节 经纬度_【笔记】进制转换和经度纬度
  17. VLC加载插件失败原因及解决
  18. 学员管理系统(面向对象版)
  19. 已解决:Navicat 1046 - UDAL - No database selected
  20. IOS中impactor报81错误解决方法

热门文章

  1. 命令行方式实现QQ自动登录
  2. MySQL ORDER BY 1 DESC的用法
  3. 夏令时到底是个什么东西?
  4. 《加密与解密》笔记五(二)
  5. VLAN访问控制列表
  6. PySpark机器学习 ML
  7. xxl-job快速入门
  8. python安装出错0x80072ee7_python3.6.4安装错误0x80072efd
  9. 【渝粤题库】陕西师范大学201931 唐诗研究 作业
  10. 使用LODOP设计打印模板