Trustworthy Online Controlled Experiments Part 1 Chap 4
实验部署
在定义好实验之后,需要把部署实验,将改动放到真实世界后,观察用户的反映。部署主要包括以下两部分:
- 一个良好的基础设施,可以解读定义好的实验,版本设置,以及其他信息。
- 按照预先的定义,将不同功能的产品,分配给不同的用户。
实验基础设施必须包括:
-
版本分配:根据用户请求的特征(例如,国籍,语言,操作系统,平台)来决定给用户分配那些版本的软件。 根据ID的 Hash 值进行伪随机分配。 在大多数情况下,ID 使用用户ID(而不是请求ID)。 版本分配必须独立,也就是说给一个用户分配某个版本并不会影响到给其他用户分配版本。这部分会在第14章具体讨论,这里假定用户都是随机分配的。
-
代码,系统参数以及值:在定义好了版本以后,如何保证用户获得符合预期的体验?如何分配代码,如何根据用户设定相应的值。
在上图中分配不同版本接口,一般被称为版本分配服务(Variant Assignment Service)。该接口可以根据正确的软件版本以及配置。不同服务版本不一定要链接到不同的服务上,可以使用不同的动态链接库来实现不同的功能(客户端或者服务器)。即使不考虑接口,统一的实现也可以预防意外的不一致性以及bug。
当建立基础设施,尤其是想上规模的时候有些细节需要仔细考量。例如,是否需要保证原子性,如果需要,如何保证?原子性意味着, 所有版本的服务都会在同一个时刻切换到下一个迭代的实验中。 在web 服务中,一个用户请求会调用上百个服务,这时原子性就很重要,因为不一致的分配会导致不一致的用户体验。 比如,搜索服务中,对搜索结果的排序会影响到很多服务,如果搜索排名服务进行了迭代,其他服务可能需要做出相应的调整。在这种情况下, 可以使用父子服务。子服务依赖与父服务,如果父服务调整,子服务则需要做出相应调整。 对于服务器基(server-based)的实验和用户基的实验(client-based)会有所不同,这部分回在第12章讨论。
另外一个需要考虑的是在何时给分配服务。根据Kohavi, Longbottom 等人在2009年的讨论, 版本分配可以发生在客户端或者服务器端。在决定时,可以考虑如下一些情况:
-
在何时有足够进行版本分配的信息? 例如,如果你只有用户请求, 这时你拥有的用户信息包括用户ID,语言,设备。对于一些其他信息,比如年龄,上次访问时间,访问频次等, 这时候是不知道的。 如果分配需要用到这些信息,那么就应该将版本分配放到更晚一些的时候。
-
在用户访问的流程中,版本分配是只发生一次,还是会发生多次?如果在平台构建早期(走,或者跑的早期), 那么最好只有一个版本分配点,这样可以使得平台比较简单,易于实现。 如果有多个分配点,那么就要保证正则性(例如覆盖性实验,比如并发实验会在本章晚些时候讨论)。 正则性指的是,早期的分配行为不会影响晚期分配的行为。
给用户分配了指定的版本以后, 接下来就要确保把不同的功能会正确的分配给用户。有三种主流方案可以选择:
- 在代码中使用分支, 例如:
variant = getVariant(userId)
If (variant == Treatment) then
buttonColor = red
Else
buttonColor = blue
- 使用参数化的系统配置,代码查询系统配置后在决定自己的执行方式:
variant = getVariant(userId)
If (variant == Treatment) then
buttonColor = variant.getParam(“buttonColor”)
Else
buttonColor = blue
或者;
variant = getVariant(userId)
…
buttonColor = variant.getParam(“buttonColor”)
- 完全使用配置文件,每个属性都有一个默认值,每个干预都会指出干预哪一项,改成什么值。
buttonColor = config.getParam(“buttonColor”)
以上三种方式,各有优缺点。 第一种方案的优点是改动距离代码最近,最贴近触发点; 缺点是这种实现会欠下“技术债”: 这种分支代码难以管理,尤其是他们越来越多的时候。第二种方案,尤其是第二种实现,同样贴近代码,在解决了“技术债”的问题的同时保证具体“触发点”足够近。 第三种方案提前了版本分配的时间点, 因此更具挑战性; 但是这种方案的优点是:随着系统变大,当整个系统有成千上万的参数时,即使实验只涉及几个参数性能也会变得非常重要。 第三种方案可以通过一些手段来优化系统性能(比如缓存)。
Google 从第一种方案逐渐过度到第三种方案,原因包括:技术债,以及需要保证不同实验代码一致性(实验分支的代码在实验结束后,要 merge 回主分支)。 Bing 也使用第三种方案。 微软使用第二种方案的第一个选项,但是他们实现了一个系统, 在这时bug ID 会当作实验参数被传递,在三个月以后回triger 一个 bug 提醒工程师删除该实验分支。
不管你使用哪一种方案,你都要测量实验平台的成本以及运行开销。 实验平台本身也会有性能方面的影响, 因此可以用在实验平台之外运行的代码的性能来测量实验平台自身带来的性能影响, 比如延时, CPU 利用率,内存以及其他影响。
记录实验信息
假设你已经记录了部分信息,比如用户动作,系统性能(见第13章)。特别是,当测试一个新功能时,必须调整记录项目以做出合适的分析。 在“爬” 的阶段时,应该关注于这些信息。领导力需要保证这些信息被经常的审查和改进。除此以外,还要记录当前用户操作使用的是哪个版本,哪个迭代。记录关于迭代的信息很重要,因为并不是所有的服务器和客户端信息都会同时改变干预行为。
在跑以及飞的阶段, 我们希望能够记录一些反事实信息,或者本该发生而未发生的一些信息。 比如,当前需要给用户返回的是B版本的搜索结果,在记录B版本的结果同时, 我们还希望记录A版本的搜索结果。 这种反事实信息可能回造成很大的开销,因此需要有关于合适才能使用此类log 的指导。 如果软件支持用户反馈,那么一定要将用户返回和版本ID关联起来。
放大实验: 挖掘更多的信息
随着公司从走迈入跑的阶段,需要提供更多的样本, 每个版本都需要被分配到足够多的样本。 当所有流量都用户实验,且用户按照 五五分的时候,实验可以获得最大的统计功率。随着实验的增加, 每个用户都需要被分配到多个实验当中, 如何做到这种分配呢:
- 单层方法
版本分配是将用户持续分配给不同版本的实验的过程。在走的阶段,实验次数通常很少,通常将所有流量除以每个实验版本, 结果就是每个版本得到的流量。情况可能是这样: 有一个实验,其中一个控件和两个“处理”, 占用了60%的流量;而另一个实验只有一个控件和一个“处理”,占了另外40%的流量(图4.3)。通常使用哈希函数将用户一致地分配到存储桶,从而完成此分配。在示例中,我们使用1,000个不相交的存储桶,并指定哪个变体获取哪个存储桶。在此示例中,具有200个存储桶的版本,将获得20%的流量。
image.png用户对存储桶的分配必须是随机的,但必须是确定性的。如果比较运行相同“处理”的任何两个存储桶,则假定它们在统计上是相似的(请参见第19章):
- 每个存储桶中的用户数量应该大致相同(请参见第3章)。如果按关键维度(例如国家/地区,平台或语言)进行细分,则比较各个存储分区的内容也大致相同。
- 关键指标(目标,护栏,质量)应具有大致相同的值(在正常可变范围内)。
监控很关键! Google,Microsoft和许多其他公司通过监视存储桶特征发现了随机代码中的错误。另一个常见的问题是残留效应(请参阅第23章): 以前的实验可能会污染当前实验的结果。常见的解决方案是在每次实验中对存储桶进行重新随机化或改组,以使其不再连续(Kohavi等,2012)。
单层(也称为数字线)方法很简单,并允许多个实验同时运行(每个用户只能进行一个实验)。当很少有实验同时进行时,在早期的成熟阶段这是一个合理的选择。但是,它的主要缺点是并发实验的数量受到限制,因为必须确保每个实验都有足够的流量以提供足够的功率。从操作上讲,在单层系统中管理实验流量依然可能具有挑战性,因为即使在此早期阶段,实验仍可能是并行的。为了管理并发,LinkedIn,Bing和Google都从手动方法开始(在LinkedIn,团队使用电子邮件协商流量;在Bing,由项目经理管理,这导致很多人围在项目经理周围乞求实验流量;在Google,首先是通过电子邮件和即时消息传递协商开始的,然后才转移到程序经理。但是,手动方法无法扩展,因此随着时间的推移,所有这三个公司都转移到了程序化分配上。
- 并发实验
为了将实验扩展到单层方法无法实现的范围,则某种并发(也称为重叠)实验系统,其中每个用户可以同时进行多个实验。实现此目的的一种方法是使用多个实验层,其中每个层的行为类似于单层方法。为确保跨层实验的正交性,在为用户分配存储桶时,需要添加层ID。
在收到用户请求后,每层将进行一次版本分配(下图展示了有2层时的情况)。这意味着生产代码和工具都必须能够处理层ID。并发实验系统的主要问题是如何确定层。
image.png一种方法,是将全因子实验层设计扩展到全因子平台设计。在全因子实验设计中,将每种可能的因子组合作为版本进行测试。如果将其扩展到平台,则用户将同时处于所有实验中:每个用户将被分配给一个版本(对照组或任何干预组)。每个实验都与唯一的层ID相关联,因此所有实验都相互正交。同一实验的迭代通常共享相同的哈希ID,以确保用户获得一致的体验。这种简单的并行实验结构能以分散的方式轻松扩展实验数量。
该设计的主要缺点是无法避免潜在的碰撞,如果两个实验会冲突,则会给用户带来糟糕的体验。例如,实验一中测试蓝色文本,实验二中测试蓝色背景。在这种情况下,对于碰巧同时遇到这两种干预方法的所有用户而言,这将是一次可怕的经历。用统计学的话,这两个实验彼此“interact”。因此,如果实验涉及不考虑两个实验之间的任何“interact”,不仅可能带来糟糕的用户体验,而且可能得到错误的实验结论。注意,并非所有的“interact”都是以对立形式出现的,有时候两种干预方式会产生“叠加”效果,产生比两个干预单独使用更好的效果。
就是说,如果分拆流量时对统计Power的降低的担忧,超过了对“interact”的担忧,那么, 全因子平台设计可能是更可取的。如果独立运行这些实验,我们可以看到在没有“interact”的情况下干预的效果, 从而判断“interact” 造成了多大的影响。当然,如果没有明显的“interact”,则可以分别分析每个实验,并且每个实验都可以享受可利用的全部流量,从而达到最大的Power。微软的实验平台拥有一个强大的系统,可以自动检测“interact”(Kohavi等,2013)。
为了防止不良的用户体验,我们可以使用嵌套平台设计(Tang等人,2010),也可以使用基于约束的平台设计(Kohavi等人,2013)。为了实现可扩展性,Google,LinkedIn,Microsoft和Facebook使用了这些设计的某些变体(Xu 2015,Bakshy,Eckles和Bernstein 2014)。
在嵌套设计中,系统参数被划分为多个层,以便组合在一起可能会产生较差的用户体验的实验必须位于同一层,并且要防止设计针对同一用户运行。例如,可能有一层用于公共UI元素(例如,页面的标题和标题中的所有信息),另一层用于主体,第三层用于后端系统,第四层用于对参数进行排名, 等等。
基于约束的设计会让实验人员指定约束,系统使用图形着色算法(graph-coloring)来确保展示给用的干预不会涉及相同的关注点。另外, 该方法的一个可能扩展用途是构建检测“interact” 的自动化系统(Kohavi等,2013) 。
实验分析
为了实现高成熟度的系统,需要自动化的分析,它不但可以节约很多时间,还可以确保产生报告的方法是确定的,一致的且科学的。我们假设在构建自动化分析系统之前,选择目标,护栏和质量指标的工作已经完成,并且所有折衷方案都编入了OEC。
自动化分析首先需要数据处理,其目的是使数据进入可用状态以便进行计算,并可视化实验结果。由于有关用户请求的检测可能会在多个系统中发生,因此数据处理通常涉及对不同的日志进行分类和合并,并对它们进行清理,会话化和丰富化。此过程有时称为数据烹饪(cooking the data )。
在处理完数据后,接下来的任务是总结并突出显示关键指标,以帮助指导决策者做出是否使用该功能的决策。这需要按不同因素(例如,国家,语言,设备/平台)对度量标准(例如,OEC,护栏度量标准,质量度量标准)进行数据计算,p值/置信区间计算以及可信度检查(例如SRM检查)。还可以包括分析以自动找到最值得注意的段(请参见第3章)。注意,尽管可以在一个步骤中计算所有这些信息,但是当实际查看实验数据时,必须进行可信赖性检查,然后再检查OEC,分段等。在查看实验数据之前,还必须彻底测试和检查所有数据处理和计算,以确保这些过程的可信赖性。
通过计算,我们最终可以创建数据可视化,以一种易于理解的方式突出显示关键指标以及有趣的指标和细分指标。这种可视化可以像一个类似Excel的电子表格一样简单。指标以相对变化的形式呈现,如果结果在统计上有意义,则可以清楚地指出,通常使用不同颜色使显着的变化脱颖而出。为了培养一种知识完整性的文化,需要确保结果可跟踪,并且访问方式通用化,并应经常对其进行审查和更新。
当组织进入“跑与飞”阶段时,可能会有很多指标,甚至有数千个!这是按等级(公司范围,特定产品,特定功能(Xu等人2015,Dmitriev和Wu 2016))或功能(OEC,目标,护栏,质量,调试;请参阅第7章)对度量进行分组的情况。随着度量标准数量的增加,多重测试变得越来越重要,并且实验人员会经常提出这些问题:为什么一个似乎无关紧要的指标,会发生显着变化?
虽然相关领域的知识可以提供帮助,但使用小于0.05的p值阈值是有效的。较低的阈值使实验者可以快速过滤出最重要的指标(Xu等,2015)。
使用可视化工具生成所有实验结果的指标视图,从而关心业务的人密切监视关键指标的全局运行状况,并查看哪些实验最有影响力。这种透明性会鼓励实验所有者与指标所有者之间进行对话,从而增加了公司中关于实验的整体知识。
可视化工具是访问已完成实验,找出做出某个决策的原因,以及导致知识发现的绝佳门户。例如,通过挖掘历史实验,可以进行元分析,以分析哪种类型的实验倾向于移动某些指标,哪些指标倾向于一起移动(超出其自然相关性)。我们将在第8章中对此进行更多讨论。当新员工加入公司时,可视化工具的视觉效果可以帮助他们迅速形成直觉,了解公司目标并了解公司产品开发过程。随着系统的发展,拥有历史结果和完善的参数,可以让公司重新运行以前失败的实验。
网友评论