为什么在数据驱动的路上,AB 实验值得信赖?
在线AB实验成为当今互联网公司中必不可少的数据驱动的工具,很多公司把自己的应用来做一次AB实验作为数据驱动的试金石。
文 | 松宝 来自 字节跳动数据平台团队增长平台
在线AB实验成为当今互联网公司中必不可少的数据驱动的工具,很多公司把自己的应用来做一次AB实验作为数据驱动的试金石。
数据 => 洞察 => 优化,循环往复寻找最优解,寻找增长的方法。
AB中有句经典的名言:大胆假设,小心求证。
本系列连载会从数据驱动、AB实验基本架构、指标选取与数据分析等角度切入,第一篇着重介绍AB实验与数据驱动的条件和AB实验的基本架构。
AB实验与数据驱动
AB实验阶段对应数据驱动的不同阶段,从最基本的设计执行分析阶段到绝大多数改动需要AB验证,从简单到复杂,从少量实验到大规模实验,正好反应的数据驱动从「爬,走,跑,飞」的四个阶段,关系是层层递进的。
1、设计执行分析阶段
设计执行分析阶段主要是:数据检测设置和数据科学能力搭建。在AB实验上进行多次的实验,从实验的设计,指标的定义,实验的开启,实验结果的分析,并且找到成功的一些实验案例有助于我们进入到下一阶段。
2、标准化指标阶段
标准化指标阶段主要是:运行少量实验到定义标准指标再到开启更多实验。AB实验开始运行更加复杂的case来持续验证数据的可行性,并且通过运行AA实验来验证平台潜在的问题,同时能够进行样本比率偏差检测。
3、大面积实验AB实验阶段
从上一个阶段的标准化指标,已经可以运行大量实验,并且各种指标也逐渐相对成熟,每次实验进行多个指标的权衡,然后在一个应用上利用AB实验对绝大多数的新功能和改动做实验。
4、绝大多数改动需要AB验证阶段
几乎所有的改动都需要经过AB实验的验证,可以在没有数据科学家的辅助下,可以对大多数的实验进行独立的分析和运作。同时通过对过去实验的分析,AB实验的有效性和最佳实践也能得到不断的更新。
数据驱动的条件
1、实验标准化
数据决策肯定是一套标准化的东西来规范,实验标准化也是AB数据驱动的必备条件。
那什么是AB实验的标准化呢?
AB实验需要注意辛普森悖论,幸存者偏差,选择偏差等,注意事项都是来源于对撞因子,简单来说就是「是指同时被两个以上的变数影响的变数」,具体可以在Google深入了解一下。
2、实验结果可信性
有数字容易,让人信赖的数字需要下功夫。开启实验容易,实验报告有数字很容易,这些数字的可信度,这些数字让人信赖更重要,需要花费更长的时间。
大量实验中可能只有很小一部分实验,例如微软大约30%的结果是正向积极的,最终可以发布到整个应用上。
举个例子:如果我抛起三枚硬币,落地分别是正正反,那么我可以说抛硬币正面朝上的概率是三分之二吗?
概率和频率并不是一个东西,同理,少数几次AB实验的结果也不能证明版本A和版本B的优劣。
我们需要统计学上的严格论证和计算,来判断一个实验结果是否显著,是否可信。
3、如何衡量好的想法
对于任何一个想法我们很难去衡量它的好坏,大胆假设小心求证。短期目标可能会与更关键的长期目标发生冲突。
举个例子:一家超市突然提高价格,可能会在短期带来更高利润。但长远看,如果更多的顾客改从竞争对手那里购买商品,那么这家店的收入就会减少。
新奇效应如何避免?
对于用户有感知的A/B Test,如UI改版、新的运营方案、新功能上线等,实验组做的任何改变都可能引起用户的注意,好奇心驱使他们先体验一番,从而导致A/B Test中实验组效果一开始优于对照组,p-value极小,实验效果非常显著。但是一段时间过去后,用户对于新的改版不再敏感,实验组效果回落,显著性可能会下降,最后趋于稳定。足够的样本量能保证一个合理的实验周期,可以使用我们的流量计算器中计算流量和实验周期,从而避免这种新奇效应的影响。
AB实验基本架构
01 - 流量分割
流量分割的方式:分流和分层。
每个独立实验为一层,层与层之间流量是正交的(简单来讲,就是一份流量穿越每层实验时,都会再次随机打散,且随机效果离散)。实验在同一层拆分流量,不论如何拆分,不同组的流量是不重叠的。
分流
分流是指我们直接将整体用户切割为几块,用户只能在一个实验中。但是这种情况很不现实,因为如果我要同时上线多个实验,流量不够切怎么办?那为了达到最小样本量,我们就得延长实验周期,要是做一个实验,要几个月。
简单来说:分流是指对流量进行整体切割,实验之间互斥。
- 目的:为了获取纯净的分区,不会互相影响。
- 缺点:浪费流量,导致流量不够。
分层
就是将同一批用户,不停的随机后,处于不同的桶。也就是说,一个用户会处于多个实验中,只要实验之间不相互影响,我们就能够无限次的切割用户。这样在保证了每个实验都能用全流量切割的同时,也保证了实验数据是置信的。
简单来说:对整体流量分流分层。
- 目的:同一个用户在不同的实验组,相互不会影响。
- 缺点:不同层之间的hash值尽量不要重合。
02 - 如何看待随机单元?
什么是随机单元呢?
简单来说,随机单元就是AB实验需要达到随机的最小单元。一个web网站中,最小单元可能是页面级别,可能是会话级别,或者是用户级别。
举个例子:我们选择页面级别的随机单元,AB实验针对某一个页面,用户每一次打开页面的时候决定把该用户导向某一个实验组。
最简单的情况就是:随机单元和分析单元是一致的。我们大多数情况也是将随机单元和分析单元采用用户级别。两种单元不一致可能使得实验分析变得更加复杂。
03 - 随机算法
首先什么是随机数?
不确定的数。大多数随机算法使用的是伪数字生成器。
那什么是伪数字生成器?一个生产数字序列的算法,特征近似随机数序列的特性。伪随机数生成器通常接受一个随机种子( seed) 用来初始化生成器的初始状态。
按照密码学来将「随机」分为三种级别:
- 伪随机 (PRNG)
- 密码学安全的伪随机 (CSPRNG)
- 真随机 (TRNG)
机PRNG生成的序列并不是真随机。
它完全是由一个初始值决定,初始值称为随机种子(seed)。接近于真随机序列可以通过硬件随机数生成器生成。但是伪随机数生成器因为其生成速度和可再现的优势,实践中也很重要。
寻找一个合适的随机算法是非常重要的。
一个实验的每一个variant(实验组或对照组)都具有关于users的一个随机抽样。随机算法必须有一些特征。特征如下:
特征(1):用户必须等可能看到一个实验的每个variant,对于任意的variant必须是无偏的。
特征(2):同一个实验中,对于单个user重复分配必须是一致的,对于该用户每次后续访问中,该user必须被分配到相同的variant上。
特征(3):当多个实验同时并行运行的时候,实验之间必须没有关联关系。也就是在一个实验中,一个user被分配到一个variant,对于被分配给其他任意实验的一个variant,在概率上没有影响。
特征(4):算法必须支持单调递增的,也就是说,如果没有对那些已经被分配给实验组的用户分配进行变更,用户看到一个实验组的百分比可能会缓慢增加的。
使用caching的伪随机
伪随机数的随机性可以用它的统计特性来衡量,主要特征是每个数出现的可能性和它出现时与数序中其他数的关系。
伪随机数的优点是它的计算比较简单,而且只使用少数的数值很难推断出它的计算算法。
使用caching缓存,可以使用标准伪数字生成器作为随机算法,一个好的伪数字生成器会满足特征(1)和特征(3)。
对于特征(2),需要引入状态,用户的分配必须被缓存,或者缓存完成可以是数据库存储,便于下次再次访问应用。
Hash和分区
不同于伪随机方法,hash和分区是无状态的,每一个user都会被分配一个唯一的user_unique_id,使用ssid和webid(或者其他)来维持。user_unique_id会和实验的id进行映射绑定,接着user_unique_id和实验id使用hash函数来获得一个整数,整数的范围是均匀分布的。
hash函数的选取需要注意️,如果hash函数有漏斗(那些相邻key的实例会映射到相同的hash code),会造成均匀分布的冲突,如果hash函数有特性(某一个key变动会产生一个hash code 上可预测的变动),会造成实验之间会发生相关。
「加密hash函数MD5」生成的数据在实验间没有相关性。其实还可以关注「大质数素数hash算法」等更加精密优良的算法。
04 - 实验灰度发布
实验发布是一个容易忽略但又非常重要的步骤,从比较小的流量慢慢发布到相对比较大的流量,直到最后全站发布。这个过程是需要自动化和风险控制相结合。
我们经常的做法就是:
实验发布之后,还可以预留一些流量来衡量实验的长期效果。
还可以重复发布某一个实验,看实验的结果是否可以保持。
指标选取
选取什么指标来进行检测,从而更好的帮助我们进行数据驱动决策。
对于一个应用或者产品来说,可能会有很多指标的选择,哪些指标需要被重点关注,哪些仅仅是关注,哪些是可以不关注。为什么要定义这个指标,这个指标的定义是为了说明什么情况,如果这个指标发生变化,将需要怎么去解释它。
(一)指标特性
1、 按照实验的角度来划分
核心指标:需要优化的目标指标,决定这个实验的最终发展方向。这种指标在一个实验是非常少的,在运行之后是不做改变的。
非核心指标指标:与核心指标有因果关系的+基础数据的指标,基础数据的指标是应用运行的底线。
2、指标敏感性和鲁棒性
指标敏感性:指标对所关心的事物是否足够敏感
指标鲁棒性:指标对不关心的事物是否足够不敏感
可以通过预先小规模试验来验证,或者AA试验来排除伪关系。
3、指标分类
(1)计数或者求和(比如:访问页面的用户数)
(2)指标分布的平均数,中位数,百分位
(3)概率与比率
(4)比例
(二)自顶向下设计指标
(1)高层次的指标(比如:活跃用户数,点击转化率CTR等等)
(2)指标细节(比如:如何定义用户活跃)
(3)使用一组指标,并将它们整合成一个单一指标(比如:总体评价指标OEC)
总体评价指标OEC:如果是使用一套指标,可以把他们聚合成一个指标,比如构造一个目标函数,或者是简单的加权指标。比如OEC = A * 0.6 + B * 04 + C * 2
举个例子:点击率的定义
定义一:登陆后总点击次数 / 登陆后的去重后的访问总数
定义二:被点击的页面数 / 总页面数
定义三:总的页面点击次数 / 总页面数
数据分析
有了AB实验,并且有实验指标选取之后,实验结果的分析就成为一件非常重要而且有挑战的事情。
产生一组数据很容易,但是从数据中分析得到实验的洞察(Insight)并不简单。
(一)实验结果显著
上面有说到实验结果的可信度,接下来详细来介绍。
说到实验结果是否显著,我们需要知道统计学中2类统计错误,我们简单说明一下,这里我们不展开说。
- (0)两类统计学错误
在统计学的世界里,我们往往只说概率,不说确定,在现实世界中往往只能基于样本进行推断。在AB实验中,我们 不知道真实情况是什么,因此做假设检验的时候就会犯错误,这种错误可以划分为两类:
这是第一类错误:实际没有区别,但实验结果表示有区别,我们得到显著结果因此否定原假设,认为实验组更优,发生的概率用 表示。
这是第二类错误:实际有区别,但是实际结果表示没有区别,我们得到不显著的结果因此无法拒绝原假设,认为实验组和对照组没有区别,发生的概率用 表示。
理想状态下当然是希望可以同时控制这两类错误,但是这是不可能的,两个概率值之间是负向关系,其中一个值的减少必然伴随着另一个值的增大,为什么呢?后续有机会再分享。
是否显著,是否可信,我们可以通过以下几种因素来判断:
(1)p值。
展示该指标在实验中犯第一类错误的概率,该概率小于显著性水平 α ,统计学中称为显著,1-α 为置信度或置信水平。
简单来说:p值判断不同版本的实验结果之间不存在显著差异的概率。
p-value越小越可信,有显著差异的指标,P-value=0.01的比P-value=0.05的可信度更高。
p值基本上还有另一个相对应的叫作t值,这个p值其实就是在t分布下≥t值的概率密度值(P(x≥t))。
通常情况下:
p值 > α(显著水平α,α 值一般5%) ,说明A版本和B版本没有太大差别,不存在显著性差异。
p值 < α(显著水平,α 值一般5%),说明A版本和B版本有很大的差别,存在显著性差异。
我们根据判断 p 值和第一类错误概率 α 比较,已经做了决策。是不是觉得大功告成,不,我们可以继续考虑power统计功效来衡量实验的可信。也就是我们要同时考虑第二类错误概率,这时候引入power统计功效。
(2)power统计功效(1 - )。
实验能正确做出存在差异判断的概率。
可以理解为有多少的把握认为版本之间有差别。
该值越大则表示概率越大、功效越充分。
一般来说,我们一般并设置的最低的统计功效值为80%以上。认为这样的可信度是可以接受的。
举个例子:实验A显示,power(统计功效)为92%,那么就可以理解为有92%的把握认为版本A和版本B之间是有差别的。
但是power根本算不出来,power作为需要满足的前提条件,作为先验的输入值。
实验开启前,通过流量计算器中计算流量和实验运行时长。
实验开启后,通过power=80%,然后计算MDE。
(3)MDE检验灵敏度,能有效检验出指标置信度的diff幅度。
通过比较指标MDE与指标的目标提升率来判断不显著的结论是否solid,可以避免实验在灵敏度不足的情况下被过早作出非显著结论而结束,错失有潜力的feature。
MDE 越小,说明当前的实验灵敏度越高,并且可以认为:实验组相比于对照组,只有高于 MDE 的提升才能大概率检测出效果显著。小于 MDE 的提升,大概率不会被检测出显著。
当前条件:指当前样本量,指标值和指标分布情况,并假设样本方差与总体指标方差足够接近。
有效检测:指检出概率大于等于80%(也就是犯第二类错误概率 <=20%)
主要影响因素:样本量大小
举个例子:假设你对该指标的预期目标提升率为1%。
如果此时MDE=0.5%,MDE < 预期提升值,说明指标变化真的不显著,请结合业务ROI和其他维度里例如用户体验、长期战略价值等来综合判断是否值得上线;
如果那此时MDE=2%,MDE > 预期提升值,说明当前能检验出显著性的最小差异值是2%,由于灵敏度不足未能检测出。这种情况下建议增大样本量,例如扩大流量、再观察一段时间积累更多进组用户,指标还有置信的可能。
(4)置信区间。
置信区间就是用来对一个概率样本的总体参数的进行区间估计的样本均值范围。一般来说,我们使用 95% 的置信水平来进行区间估计。
置信区间可以辅助确定版本间是否有存在显著差异的可能性:
如果置信区间上下限的值同为正或负,认为存在有显著差异的可能性;
如果同时正负值,那么则认为不存在有显著差异的可能性。
详细视图中有个值叫相对差,该值就是指标变化的点估计值,而置信区间给出的是指标预期变化的区间估计值,区间估计值有更大的可能性覆盖到指标相对变化的真实值。(假设做100次实验,有95次算出的置信区间包含了真实值)。
可以这样简单但不严谨地解读置信区间:假设策略全量上线,你有95%的把握会看到真实的指标收益在置信区间这个范围内。
(5)决策流程
(二)多次测试
简单的说:传统的假设检验的设置是对需要检测的「假设」进行唯一测试,然后计算p值。我们有5%的概率观测到某一个并没有实际变化的“指标”显得有统计意义上的显著变化。
现实中,对于同一个实验,我们通过AB实验反复观察结果,或者反复针对同一个想法进行迭代。
出现更严重的问题就是:我们针对同一个实验,常常同时观测几十个或者上百个指标,导致出现多次实验的问题,大大增加了观测并不该有显著变化的指标有了统计意义变化的概率。
(三)方差的计算
t检测中我们需要对数据的方法进行计算。有时候我们的“方差”计算是有问题的,之前有说到的「随机单元」和「分析单元」不一致的情况下,计算比率型的指标,比如点击率。
我们来看一个场景:经常我们的「随机单元」是用户级别的,然而我们希望计算的是一些页面级别的点击率,然后看对照组和实验组之间的差别的,这个时候就存在「随机单元」和「分析单元」不一致的问题,传统的计算点击率的「方差」公式可能存在问题。
(四)样本比率偏差
在理想的状态下,对照组和实验组的流量是一半一半的,也就是50%的进入到对照组,50%的进入到实验组。但是现实是残酷的,比如会出现50.27%的用户进入到对照组,另外49.73%的用户进入到实验组。
这种情况正常吗?我们还信任这样的实验结果吗?
这样情况的排查和分析。简单的说,我们需要把这样的分流结果当作假设检验,看这样的结果是否异常。
(五)AA实验
AA实验往往作为检测平台稳定性和实验设置是否正确的重要手段。
也就是说,对AB系统本身进行测试,以确保系统在95% 的时间内正确识别出没有统计学意义上的显著差异。
(六)对照组和实验组之间干涉
传统的实验我们假设对照组和实验组是完全隔绝的,然后实际中,完全的隔离是不可能的。
举个例子:社招网络中,朋友与朋友的关系,我们按照传统的随机划分流量的方法,可能一个用户在对照组,他的朋友在实验组,这样这个用户可能接触到对照组的一些信息,从而违背了假设检验的一系列基本假设。
(七)指标的长期效果
有一些“指标”的效果在A/B实验之后,可能会出现一些“恶化”,也就是说,效果可能没有之前那么明显了,甚至会出现效果完全消失。
如果遇到短期效果与长期效果可能出现不一致的情况,建议延长测试时间,观察长期效果。
但是长期存在一些问题:
(1)ssid跳变的情况,进行实验时候,通过随机分配的ssid,进行确定用户身份,但是用户可以在浏览器中修改localstorage中的ssid,保持一个稳定的样本几乎不可能,实验进行的越久,问题越严重。
(2)幸存者偏差的情况,过度关注幸存者,忽略没有幸存的而造成错误结论。
(3)选择偏差的情况,由于ssid跳变,只有登陆的用户组成,不具备代表性。
参考
https://stats.stackexchange.com/a/354377/320904
火山引擎A/B测试
A/B测试,摆脱猜测,用科学的实验衡量决策收益,打造更好的产品,让业务的每一步都通往增长。点击了解
欢迎关注字节跳动数据平台同名公众号
为什么在数据驱动的路上,AB 实验值得信赖?的更多相关文章
- 滴滴数据驱动利器:AB实验之分组提效
桔妹导读:在各大互联网公司都提倡数据驱动的今天,AB实验是我们进行决策分析的一个重要利器.一次实验过程会包含多个环节,今天主要给大家分享滴滴实验平台在分组环节推出的一种提升分组均匀性的新方法.本文首先 ...
- AB实验的高端玩法系列2 - 更敏感的AB实验, CUPED!
背景 AB实验可谓是互联网公司进行产品迭代增加用户粘性的大杀器.但人们对AB实验的应用往往只停留在开实验算P值,然后let it go...let it go ... 让我们把AB实验的结果简单的拆解 ...
- AB实验的高端玩法系列3 - AB组不随机?观测试验?Propensity Score
背景 都说随机是AB实验的核心,为什么随机这么重要呢?有人说因为随机所以AB组整体不存在差异,这样才能准确估计实验效果(ATE) \[ ATE = E(Y_t(1) - Y_c(0)) \] 那究竟随 ...
- Paper慢慢读 - AB实验人群定向 Learning Triggers for Heterogeneous Treatment Effects
这篇论文是在 Recursive Partitioning for Heterogeneous Casual Effects 的基础上加入了两个新元素: Trigger:对不同群体的treatment ...
- Paper慢慢读 - AB实验人群定向 Recursive Partitioning for Heterogeneous Casual Effects
这篇是treatment effect估计相关的论文系列第一篇所以会啰嗦一点多给出点背景. 论文 Athey, S., and Imbens, G. 2016. Recursive partition ...
- Paper慢慢读 - AB实验人群定向 Double Machine Learning
Hetergeneous Treatment Effect旨在量化实验对不同人群的差异影响,进而通过人群定向/数值策略的方式进行差异化实验,或者对实验进行调整.Double Machine Learn ...
- AB实验的高端玩法系列4- 实验渗透低?用户未被触达?CACE/LATE
CACE全称Compiler Average Casual Effect或者Local Average Treatment Effect.在观测数据中的应用需要和Instrument Variable ...
- AB实验人群定向HTE模型5 - Meta Learner
Meta Learner和之前介绍的Casual Tree直接估计模型不同,属于间接估计模型的一种.它并不直接对treatment effect进行建模,而是通过对response effect(ta ...
- 【转】AB实验设计思路及实验落地
这篇文章会讨论: 在什么情况下需要做 AB 实验 从产品/交互角度,如何设计一个实验 前端工程师如何打点 如何统计数据,并保证数据准确可信 如何分析实验数据,有哪些数据需要重点关注 附:如何搭建前端实 ...
随机推荐
- 【刷题-LeetCode】207. Course Schedule
Course Schedule There are a total of numCourses courses you have to take, labeled from 0 to numCours ...
- 【记录一个问题】神坑,自定义一个golang的error类型,居然运行崩溃了
2020-05-20 18:20补充: 感谢yif同学提供指导,出现错误并且打印大量信息的原因是函数递归调用导致栈溢出. 而导致递归调用的关键代码是%v 类型实现了error的interface %v ...
- thinkpad s5 电源功率不足提示
相关答案 作者:路灯瓜 链接:https://www.zhihu.com/question/47551448/answer/122578101 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权 ...
- 第01讲:Flink 的应用场景和架构模型
你好,欢迎来到第 01 课时,本课时我们主要介绍 Flink 的应用场景和架构模型. 实时计算最好的时代 在过去的十年里,面向数据时代的实时计算技术接踵而至.从我们最初认识的 Storm,再到 Spa ...
- java 坐标练习
定义一个三维空间的点,有三个坐标 实现以下目标: 1.可以生成特定坐标的点对象 2.提供可以设置三个坐标的方法 3.提供可以计算该点到特定点距离的平方的方法 class Point { double ...
- lambda表达式的学习
Lambda表达式 为什么使用lambda表达式 Lambda表达式可以简化我们的代码,使我们只需要关注主要的代码就可以. //测试用的实体类 public class Employee { priv ...
- Django class meta
class Main(models.Model): img = models.CharField(max_length=200) # 图片 name = models.CharField(max_le ...
- React之常用技术栈
· react-redux:https://www.cnblogs.com/jingxuan-li/p/12439181.html · react-router-dom:https://www.c ...
- Lesson6——Pandas Pandas描述性统计
1 简介 描述统计学(descriptive statistics)是一门统计学领域的学科,主要研究如何取得反映客观现象的数据,并以图表形式对所搜集的数据进行处理和显示,最终对数据的规律.特征做出综合 ...
- JAVA中获取不同系统的换行符和获取系统路径路径分割符
简介 JAVA具有多平台特征,一次开发,多平台运行,主要依据JVM,但是不同的操作系统中换行符和分割符不同,故需要根据不同的操作系统去获取不同的符号. JAVA代码 @Test public void ...