探讨AB实验中的分层实验原理与实施方法

软件模
• 阅读 258

1、背景

AB 实验是 “特性管理” 的主要应用场景之一。随着业务功能、实验数量的增加,特别是对实验流量的管理需求,需要建立统一的组织和规划。在本文中,我们将简要介绍通用实验流量的管理办法,并介绍如何在 FeatureProbe 中实现这种流量管理。

1.1 实验的冲突

大家对实验的冲突和实验的层域规划设计的认识,大多来自于早期 Google 关于 AB 实验的论文《Overlapping Experiment Infrastructure:More, Better, Faster Experimentation》。这里简单回顾一下在什么情况下实验会出现冲突。在同一时间段内,如果只执行一个实验,这意味着同一个用户不会同时参与两个不同的实验,而只会分配到一个实验的A组或B组。然而,通常情况下,即使产品不像 Google 搜索系统那样复杂,也可能需要同时上线多个新功能,这就要求我们同时进行多个 AB 实验。如果我们将所有实验按照时间顺序一个一个进行,验证所有功能所需的时间将会变得非常漫长。

从效率的角度考虑,我们需要能够同时进行多个实验,以节省时间。但从准确性的角度来看,我们不希望同时进行多个实验会导致与一次只进行一个实验时不同的结果。换句话说,我们需要确保实验之间不会互相干扰,使得同时进行多个实验的结果与一次只进行一个实验的结果一致。

2、实验层方案

2.1、原理

实验层的方法通过流量分配来实现多个实验的隔离。简而言之,它将所有用户分成相互隔离的组,然后将每个组的用户引导到不同的实验中(再进一步将组内用户分为实验的A组和B组)。这意味着同一用户只属于一个特定的组,即每个用户只能参与一个实验,从而确保各个实验之间互不影响。
 

  • 优点:实验之间用户完全隔离,适用于任何需要绝对隔离的实验场景(即不允许同一个用户同时进入两个实验)。
  • 缺点:流量硬性分割,在总用户量很小的情况下每个实验分到的用户数量可能很小,导致无法获得统计显著所需要的样本量。

2.2、在 FeatureProbe 中配置实验层与实验

FeatureProbe 的功能设计注重通用性和最小化,因此它当前不直接提供实验层的页面配置和管理。不过,我们可以通过使用前置开关(Prerequisite flag)功能来实现实验层的设置与管理。
假设一个场景:我们现在需要一个流量层,其中一部分流量需要被隔离用于两个相互不影响的实验,而剩余的流量需要被保留以备未来可能需要上线的实验。以下是如何进行配置的介绍:

探讨AB实验中的分层实验原理与实施方法

首先,我们需要创建一个名为 "Experiment\_layer" 的前置开关,以作为实验层的配置。在这里,我们选择使用百分比流量来对用户进行分组,当然也可以选择不同的用户特征来进行分组,比如按城市来分组等。在这个配置中,我们将 10% 的流量分配给实验甲,另外 10% 的流量分配给实验乙,而剩下的 80% 的流量将被预留以供将来使用。我们会使用三个不同的 variation 来代表这三个分组,分别是 "甲"、"乙"和"预留"

探讨AB实验中的分层实验原理与实施方法

现在我们来配置实验甲,新建一个实验开关,例如取名 “Exp1“。配置前置开关为 "Experiment\_layer" 的返回为实验甲,之后将 “Exp1“ 的 2 个 variation 配成 “A组” 和 "B组",将 default 的 variation 设置为“A组”,将 disable 的 variation 设置为“未进入实验”。

探讨AB实验中的分层实验原理与实施方法

这时,我们可以编写我们的业务代码如下:

FPUser fpUser = new FPUser(userId);
    string var = fpClient.stringValue("exp1", user, "未进入实验");
    if (var == "A") {
        
        // 这个人进入了实验的A组,这里写A组的处理逻辑
        
    }else if(var == "B"){
        
        // 这个人进入了实验的B组,这里写B组的处理逻辑
        
    }else{
        
        // 这个人没有进入exp1实验,他可能在实验层里别的组,写默认的处理逻辑
    }

2.3、直接使用实验层做实验

以上的场景假设每个实验都有自己的 A组 和 B组(control组 和 treatment组),在更简化的形势下,层内实验可以复用同一个 control组,如下图所示:

探讨AB实验中的分层实验原理与实施方法

这种情况下,就可以直接使用 "Experiment\_layer" 控制流量,而不用嵌套前置开关。相应的代码示例如下:

 FPUser fpUser = new FPUser(userId);
   
    string var = fpClient.stringValue("experiment_layer", user, "未进入实验");
    if (var == "Control") {
        
    // 这个人进入了Control组,使用之前的处理逻辑
    
    } else if (var == "blue" {
        
    // 这个人进入了blue实验,这里写blue的处理逻辑
    
    } else if (var == "green") {
        
    // 这个人进入了green实验,这里写green的处理逻辑
    
    } else {
        
    // 写错误处理逻辑
    
    }

3、实验正交方案

3.1、原理

除了使用实验层来进行硬隔离流量的方法之外,通常情况下,我们发现大多数实验所要测试的变化点并不是绝对互斥的。这意味着我们可以采用重新随机分配流量的方式,来共享资源,同时又能够将两个不同实验的效果区分开。 

举例来说,一个页面"UI实验"和一个"排序策略实验",我们就可以认为这两个实验是非互斥的,同一个用户可以同时进入这两个实验,只需要将进入两个实验的用户打散,避免所有进入"UI实验A组"的人,进入的"排序策略都是 A 组",而是让进入""UI实验A组"的人,重新打散,均匀进入"排序策略实验"的 A 组和 B 组,这样"UI实验"的效果在"排序策略实验"里就会因为被打散而平衡掉,使得"排序策略实验"的效果只包含排序算法产生的影响而不包含"UI实验"产生的影响。

3.2、在 FeatureProbe 中使用正交实验

FeatureProbe 中所有开关的按流量分割算法参数都是不同的,也就是说所有开关的流量分割分组都是天然互相正交的,无需做特别设置。
 
例如建立实验 "Exp1" 和 "Exp2",分别都是 50%,50% 返回两个 variation。那么拿同一组用户 id 去请求两个实验结果,进入 "Exp1" 的 A 组用户,一定是打散进入 "Exp2" 的两个 variation 组。

探讨AB实验中的分层实验原理与实施方法

4、混合方案

在 Google 的原论文中,还介绍了更复杂的组和实验层,以及正交实验的实验流量规划方法,如下图所示:

探讨AB实验中的分层实验原理与实施方法

FeatureProbe 中,我们可以通过级联使用前置开关来实现类似的实验层配置,具体示例不一一列举。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
4年前
VBox 启动虚拟机失败
在Vbox(5.0.8版本)启动Ubuntu的虚拟机时,遇到错误信息:NtCreateFile(\\Device\\VBoxDrvStub)failed:0xc000000034STATUS\_OBJECT\_NAME\_NOT\_FOUND(0retries) (rc101)Makesurethekern
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这