适用于在线服务的A/B测试方法论
适用于在线服务的A/B测试方法论
简介:
这篇文章旨在介绍适用于为在线服务进行A/B测试(A/B Test)的方法论。中文网络中目前还缺乏全面的入门级介绍。
我将首先讨论在线服务业进行A/B测试所考虑的决策问题,然后介绍两种不太常见的统计测试:序列概率比测试(Sequential Probability Ratio Test, SPRT)和基于多臂bandit(Multi-armed Bandit, MAB)算法的测试。
I.不只是P-Value
经典统计学会用如下的方法进行A/B测试:
(F1)选择一个样本N
(F2)随机平分到A/B组
(F3)计算原假设的t统计量(双样本+未知方差)所对应的p-value
(F4)如过p-value小于一个特定的显著性水平(例如0.05),那么就拒绝原假设,否则啥也做不了。
基于农业和工业生产体系产生的经典统计检验方法并不一定适用于在线服务业。这不完全是因为p-value经常被误解了,更多是因为经典假设检验不能满足在线服务业的业务要求。
1.1 为持续改进服务的AB测试是决策问题而不是推断问题
大部分时候,我们只关心是否A方案比B方案好,而不关心A方案比B方案好多少。换句话说,我们只关心实验的业务正确性(decision),而不在乎实验的统计可靠程度(inference)。
从这个角度来看,双边检验是一个糟糕的决策问题。拒绝原假设并不能告诉我们到底应该选择A方案还是B方案。单边检验是一个更好的原假设。如果拒绝了原假设,那么应该选择A方案;否则就选择B方案。
假设检验还可以有其他形式。我们可能并不关心A方案和B方案是否完全一致(贝叶斯主义者会说永远不会一致),我们可能关心A方案的B方案差距是否在一定范围内。如果是,那么我们应该做出选择,否则可以保持现有的方案。这样的原假设检验是等价检验(equivalence test):
总而言之,F3不适合在线AB测试。事实上,假设检验的鼻祖Ronald Fisher反对将原假设检验作为决策依据。
1.2 不仅关心实验结果,而且关心实验成本
在线上运行试验(特别是大规模实验)时,可能会影响用户体验,从而影响用户留存等关键业务指标。除非主管老板正好是实证主义的狂热信徒,否则他们可能会对于做实验颇有微词。如果你运气好,去了一家完全由A/B测试驱动的公司,那么实验成本的问题不仅没有消失反而更为重要了。
因此,我们希望在实验过程中,尽可能降低优势方案向用户曝光的频率。要实现这个目标有两种方法,动态结束机制和非均衡分组。动态结束机制是指一旦确认某个方案胜出,就立即停止实验;采用这种方法意味着F1不适合在线AB测试,因为我们不必死等到耗尽预订样本为止。非均衡分组是指向在当前估计下优势方案多分配用户,我们将在多臂bandit一节中更加详细地讨论这个问题;采用这种方法意味着F2不适用在线AB测试。
1.3 样本是序列生成的
经典统计学暗中假定数据是同时生成的,而不是依次生成的(大概要归功于假设检验的始祖Ronald Fisher是个农业统计学家)。然而在线服务业的用户总是依次到达的。这个重要特征使得我们可以兼顾实验可靠性和实验的成本,也是下面两种检验方法的核心特征。
II.序列概率比测试
序列概率比测试(Sequential Probability Ratio Test,以下简称SPRT)可以认为是经典假设检验在序列样本环境下的变体。在相同显著性(significance)和检验力(power)下,SPRT可以比经典t检验结束的更早,需要的样本更少。而其代价就是更加复杂的统计量和更加复杂的决策程序。
对于SPRT理论性质和正规检验方法感兴趣的读者可以钻研David Seigmund(1985)的Sequential Analysis一书。在这里我们提供两个更为实际的检验方法。第一是optimizely的统计检测引擎,另一个是Evan Miller的简易SPRT。前者虽然提供一个严格的False positive边界,但是没有完全披露其核心参数,因此不能下架即用。后者是个傻瓜式的检验,但是其显著性和检验力堪忧,能够适用的业务场景也较少(几乎仅限于二元变量)。
如果你对于显著性这个概念情有独钟,那么SPRT可能是一个值得投入时间研究的方法。
III. 多臂bandit测试
如果SPRT所涉及的数学水平是精深的话,那么真正理解多臂bandit(以下简称MAB)问题所需要的数学水平已经是非人了。Scott(2010)为MAB问题的历史提供了一个深入浅出的回顾。O’Reilly有一本书介绍了MAB的经典解法和其Python代码。
幸运的是,MAB有一个名为汤普森抽样(Thompson Sampling)的贝叶斯解法。它容易理解,容易执行,扩展性强;因此非常适合用于在线AB测试。事实上,它正是Google Analytics,Yahoo!和Bing实际使用的方法。
关于汤普森抽样的技术细节请参见Google Analytics的帮助菜单和例子,Scott(2010)提供了更为正式的表述。在这儿我主要讨论一下GA算法的核心思想。
3.1 什么是多臂bandit
Bandit是美国人给bandit取得别名。下图的bandit是一个独臂one-arm bandit。你拉一下摇杆,得到一个奖励。进一步假设奖励是取值0,1的随机变量,取值为1的概率是p。
假设这个bandit有多个摇杆,从1到N编号,每个摇杆返回奖励的概率为,但是这个概率你不知道。每个回合你可以选择拉动一个摇杆。
假设各个摇杆的返奖概率不变,使用什么策略可以使得累计奖励最大化?
简而言之,这就是多臂bandit问题。回顾第一节关于在线服务优化的讨论,可以发现两者间的强关联:两者的核心目标都是做出决策;两者的核心考量都是成本收益,两者的数据生成过程都是序列化的。
3.2 探索与利用的权衡
如果用经典t检验的思路来解决多臂bandit问题,你的策略是这样的:
(1)在1到轮,确保每个摇杆拉次
(2)在结束时,计算每个摇杆的样本平均,选出样本返奖概率最高的摇杆
(3)从第轮开始,一直选择摇杆
从轮开始的策略是纯利用(Exploration):即选择实证奖励最高的选项(play the winner);而前轮所用的策略是纯探索(Exploitation):即无视经验奖励,让概率做决定。
一般而言,像这样泾渭分明的策略组合不是最优的。在实验初期,应该鼓励探索,因为我们不知道哪个选项更好。但是,当有证据表明某几个选项相对更优时,应该增加“利用”的比例。这样做有两个好处:第一,多选赢家可以提高策略的整体收入;第二,多选赢家可以比平均分配更快地降低标准误,从而提高我们对于“赢家估计”的信心。因此,利用的比例应该随着时间的增加而增加。
汤普森抽样提出了这样一种直观的贝叶斯解决方案:
在每个周期计算“摇杆i是最优摇杆”的后验概率,以此作为下一轮随机分配摇杆的依据。
汤普森抽样保证”在实验过程中“坑用户”的比例是最小的。此外,如果你懂一些贝叶斯模型,你就可以看到这种方法的灵活性和可扩展性有多强。
3.2 停止条件:潜在剩余价值
尽管汤普森抽样看似秒杀经典t检验,但是在决策过程中它有一个致命问题。所有的MAB策略本身都不是一个统计检验,因为它们没有停止条件。汤普森抽样会跑到海枯石烂,但是实际操作不允许无限长的实验。目前为止,还没有人公开发表一个简单靠谱的终止条件。和经典t检验相比,这是基于MAB测试的一个重要缺点。
Google Analytics推荐使用“潜在剩余价值”(Potential Value Remaining,PVR)来判断实验结束的时间。当选择摇杆后,我们想知道(基于返奖概率的后验概率分布)如果选择其他摇杆的潜在收益有多大。如果这个收益很小,那么我们就有足够的理由的选择最优解;如果这个收益还很大,那么还需要收集更多的数据来消除对于返奖概率的不确定性。事实上,PVR并不是一个值,而是一个分布。因此,潜在收益“大小”需要用两个数(,)衡量,分界线,分界概率:
潜在最优收益比目前最优收益大%的概率小于
比如,Google Analytics默认的设置是(0.01,0.05),即潜在最优收益比目前最优收益大1%的概率不到5%。
需要警告读者的是,即使A/B方案没有任何区别,PVR停止政策也会导致相当一部分的实验在有限时间内终止;并且随着时间的延长,这样第一类错误的概率会不断增加。这与经典t检验下固定pvalue,样本越大,显著性越小的特征正好相反。如果你非常关心第一类错误概率,那么MAB测试不是一个好选择!
IV. 什么时候应该关心显著性?
在假设检验中,我们一般讨论第一类错误(Type I Error)和第二类错误(Type II Error)。假设原假设为H0:你没有怀孕,被择假设为H1:你怀孕了。那么,两类错误描述的情况如下图所示。
Scott在好几处都提到一个观点,那就是线上实验根本不用考虑第一类错误,因为其代价极小;反而是第二类错误犯了才致命。事实上,Scott反对的并不是第一类错误,而是双边假设检验。
考虑形如下第一类错误和第二类错误的业务含义。如果犯了第一类错误,A方案和B方案完全等效,我们错误认为其中一个方案更好。这有什么实际代价么?如果代码转换和用户体验变化的成本可以忽略不计(对于小改变而言的确如此),那么第一类错误的代价的确是0。与此恰恰相反,假设我们犯了第二类错误,并且假设新方案是更优的选择,我们就错过了一个永久改进的机会:这是一个代价不菲的错误。
当产品线稳定后,持续改进只能从细节入手时,Scott的批评是非常有用的。因为PM们能想到的改进都已经做了,意外惊喜靠人的想象力来发掘已经不太现实了;相反,用算法生成大量组合,进行持续测试和优化,说不定可以积跬步而致千里。因此对于诸如Google或者Facebook这样的公司来说,用实验主导开发是更合理的选择。
如果产品线不稳定,实验数据被用来做改版的调研,此时我们在做推断,而不是决策。因为人很容易被随机性所欺骗,看到海市蜃楼般的改进道理;所以实验方法论应该设计的更为保守。如果因为第一类错误而导致失败的all in,这是一个代价不菲的错误。
因此,我个人推荐使用汤普森抽样作为自动化实验体系的统计检验方法,使用经典t检验作为战略决策实验的统计检验方法。
延展阅读
为了提高可读性,本文避开了以下重要话题。这些问题有助于我们更加深入地理解假设检验与业务的契合。有兴趣的童鞋可以从这些博客出发,进一步阅读:
(2)重复显著性检验(repeated significance test):为什么Bayesian Test是或者不是解决方案。我个人认为信贝叶斯又信p value属于人格分裂,Andrew Gelman有更加科学的解释(下面的评论值得详细阅读!)。
(3)多重对比,为什么过度的(简易)AB测试是伪科学。
关于经典t检验应该怎么做,实验经济学大神John List(2010)有一个非常实用的指导手册。经典t检验绝不是把样本五五开这么简单。
来源:http://www.fengjunchen.com/tag/abtest/
适用于在线服务的A/B测试方法论的更多相关文章
- 渗透测试方法论(qf总结)
渗透测试(penetration testing , pentest)是实施安全评估(即审计)的具体手段.方法论是在指定.实施信息安全审计方案时,需要遵循的规则.惯例和过程.人们在评估网路.应用.系统 ...
- 使用app测试Modelarts在线服务
1. 基础准备 本demo代码已上传github地址为 https://github.com/zxzxzxygithub/hwmodelartdemo clone下来之后导入android studi ...
- 【Android测试】【随笔】与 “58同城” 测试开发交流
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5384698.html 初衷 一直都有一个这样的想法: 虽然 ...
- 渗透测试的理论部分3——ISSAF的详细描述
ISSAF即信息系统安全评估框架(Information Systems Security Assessment Framework)是另外一种开放源代码的安全性测试和安全分析框架.为了解决安全评估工 ...
- 渗透测试的理论部分2——OSSTMM的详细描述
昨天休息了一天,今天我要连更两篇博客,作为补充,以下为正文 本章详细描述了OSSTMM内的RAV得分这一理论概念,对日后从事正规安全工作至关重要 OSSTMM为开源安全测试方法论,对OSSTMM不了解 ...
- Kali linux渗透测试的艺术 思维导图
Kali Linux是一个全面的渗透测试平台,其自带的高级工具可以用来识别.检测和利用目标网络中未被发现的漏洞.借助于Kali Linux,你可以根据已定义的业务目标和预定的测试计划,应用合适的测试方 ...
- Test complete测试工具介绍
Test complete 是一款性价比比较高的测试工具,能够满足大多数用户的自动化测试的需求. Test complete 是近几年流行和发展起来的一款自动化测试工具,早期版本由Automated ...
- web 压力测试工具
最近有收到任务,测试新服务器的性能. 花了很长时间做搜索,也整理了一些资料.以下是收集到一些简单易用的分析工具.推荐给大家使用. WebBenchhttp://www.ha97.com/4623.ht ...
- loadrunner测试结果三
结果摘要: 场景执行情况: 该部分给出了本次测试场景的名称.结果存放路径 及 场景的持续时间 统计信息摘要 statistic summary 该部分给出了场景执行结束后并发数.总吞吐量.平均每秒吞吐 ...
随机推荐
- 【CUDA开发】 Check failed: error == cudaSuccess (8 vs. 0) invalid device function
最近在复现R-CNN一系列的实验时,配置代码环境真是花费了不少时间.由于对MATLAB不熟悉,实验采用的都是github上rbg大神的Python版本.在配置Faster R-CNN时,编译没有问题, ...
- Docker虚拟化
1. Docker虚拟化特点 跟传统VM比较具有如下优点: 操作启动快 运行时的性能可以获取极大提升,管理操作(启动,停止,开始,重启等等) 都是以秒或毫秒为单位的. 轻量级虚拟化 你会拥有足够的“操 ...
- Java语言中null与" "的区别
null是空对象,没有地址,可以赋值给任何对象:""是空字符串,有地址但是里面的内容是空的,只能赋值给字符串对象. 如:String s;//分配了一个内存空间,没存入任何对象 ...
- Django框架4——form表单
HTML表单一直是交互性网站的支柱,使用form组件对用户通过表单提交的数据进行访问.有效性检查以及其他处理 从Request对象中获取数据 URL相关信息 属性/方法 说明 举例 request.p ...
- Docker2 docker commit方法镜像制作
一.前期准备 1.下载一个centos镜像,进入容器,安装wget docker pull centos docker run -it centos bash [root@web1 ~]# docke ...
- caffe模型的一些解释~
转自:https://blog.csdn.net/wjmishuai/article/details/50890214 刚开始摸caffe,找了个比较清楚的模型. 原始数据是28* input: &q ...
- wpf 把两个Bitmap 合并为一个
水平合并 /// <summary> /// 将两个Bitmap水平合并为一个 /// </summary> /// <param name="first&qu ...
- Flutter裁剪图片
最近在学习中需要用到裁剪图片,记录一下解决方法 思路: 使用canvas的drawImageRect()方法,对Image进行裁剪,这里的Image需要 'dart:ui' 库中的Image. 1. ...
- Java High Level REST Client 使用示例
概述 ES 在 7.0 版本开始将废弃 TransportClient,8.0 版本开始将完全移除 TransportClient,取而代之的是 High Level REST Client,官方文档 ...
- 【转载】Sqlserver使用IsNull方法对空字段进行赋值操作
在Sqlserver的SQL语句查询过程或者编写存储过程以及自定义函数过程中,有时候字段的值为空,如果为空的字段需要赋值一个默认值,可以使用Sqlserver内置系统函数IsNull来给定一个默认值, ...