diff --git a/overlapping-experiment-infrastructure-more-better-faster-experimentation/README.md b/overlapping-experiment-infrastructure-more-better-faster-experimentation/README.md index ab6af7b..80a3509 100644 --- a/overlapping-experiment-infrastructure-more-better-faster-experimentation/README.md +++ b/overlapping-experiment-infrastructure-more-better-faster-experimentation/README.md @@ -61,7 +61,7 @@ 宏观上看,用户通过它们浏览器发送请求与`Google`交互。请求进入`Google`的服务系统后,会先后被多个服务处理(运行在服务器上的程序),然后产生面向用户的结果页。比如,可能有一个服务决定与查询最相关的原生搜索结果,另一个服务决定与查询最相关的广告,还有一个服务将原生搜索结果和广告结果组织到结果页,返回给用户。见图1。一方面,这种模块化可以让我们降低延时(不相互依赖的过程可以并行),显然,原生的搜索过程与广告搜索过程是相互独立的,并能更快速的试验(每个服务都可以独立地进行,并且模块化的测试可以进行更快速的发布)。另一方面,如果要求每个请求最多只进入一个实验,那么模块化就需要更精心地设计。可能存在的问题有流量饥饿(上游模块的实验可能优先处理了所有请求,导致下游模块的实验没有请求),和偏置(`bias`)(比如,上游模块的实验处理了所有英语的请求,导致下游模块的实验就只有非英语请求)。 ![图一](figure-01.jpg) -**图一:一个请求经过多个模块的例子,信息(和时间)都是从左流向右** +**图1**:一个请求经过多个模块的例子,信息(和时间)都是从左流向右 每个服务都有二进制推送和数据推送。二进制推送是指发布新的程序(`bug`修复、性能提升、新特性,等等),它一定时期进行一次(比如每周)。数据推送更频繁(比如,按需或是每几小时推送一次),并且这还涉及了推送更新的数据到相应的程序。数据推送中还包含了默认参数配置,参数是用来配置程序如何运行,比如,控制结果如何展示的服务也许有一个参数是决定顶部广告块的背景色。再比如,预测`CTR`的服务可能有参数是控制学习速度和收敛速度的。程序可能有几百个参数。新的特性可能会添加一个或多个参数:最简单的场景是,一个参数可以控制打开或关闭新特性,在更复杂的场景中,也许有多个参数决定新特性如果展示,有数值阈值决定新的特性是否被展示,等等。将程序和数据分离,意味着如果我们可以找到合适的分离方式,我们就可以同时得到快速影响线上服务的通路,和慢速影响线上服务的通路(程序是慢的通路,改变参数值是快速的通路)。 @@ -95,7 +95,7 @@ * 我们可以先将流量分为两个域,一个域只有一个单一层(非重叠域),和一个有三个层的重叠域(见图2b),在这种情况下,每个请求会分到非重叠域或是重叠域。请求只能在非重叠域或重叠域其中之一。如果请求在重叠域,那么请求最多在一个实验中(这个实验可以改变参数集合中的任意参数的值),如果请求在重叠域,那么请求最多在三个实验中,每层一个实验。并且对于每个实验,只能使用对应层的参数。 ![图二](figure-02.png) -**图二:重叠分层示意图** +**图2**:重叠分层示意图 这种嵌套看起来有些复杂,但它有几个好处。 @@ -120,7 +120,7 @@ 在通过流量分配类型选择一部分流量后,**分流条件**(`condition`)通过仅分配特定条件的流量给实验或域,以达到更高效利用流量的目的。比如,一个实验仅仅改变来自日语的查询,那么实验配置中只抽取日语的流量。我们可以基于地区,语言,浏览器等信息设置流量抽样条件。有了分流条件,一个只使用“日语”流量的实验,和一个只使用英语流量的实验,可以使用相同的`cookie`取模。另一个使用分流条件的场景是灰度测试新代码(代码是通过二进制推送发布的),比如,在一股小流量上测试新代码,以保证新代码没有`bug`,并与预测一致,然后才能放到大流量环境中(灰度环境中,通过错误日志和实验监控方式检查`bug`)。为了支持这种使用场景,我们提供了以机器或数据中心为分流条件的分配方式,它进一步限制了一个实验的流量。虽然灰度实验无法代替严格的测试,但它们是一个有用的补充,因为它既限制了潜在的错误,并且它让新的代码在真实环境中运行,从而可以遇到各种在测试环境中很难构造的真实请求。 ![图三](figure-03.png) -**图三:决定请求进入域,层,实验的逻辑** +**图3**:决定请求进入域、层、实验的逻辑 分配条件是直接在实验(或域)的配置中指定的,这允许我们在实验的创建时基于数据文件对流量分配冲突进行检测。如在流量分配类型一节中提到的一样,如果一个请求先满足了流量分类顺序中的一个_类型_,它不会再考虑下面的分配类型,即使它不满足这一种分配类型的分配条件。这很重要,最好以一个例子来说明,如果我们通过特定的`cookie`取模来得到实验的流量,我们将会得到一个无偏的分配。考虑一下一个指定`cookie`取模上有两个实验,一个分配条件为日语流量,另一个分配条件是英语流量,而这个`cookie`取模剩余的流量(即不是日语和英语的流量)将不会分配给以`cookie`分配方式的其它实验,这是为了避免分配顺序后几种分配方式的**偏置**,重要的逻辑是不再将上述剩余的流量分配给分配顺序后几种分配方式的实验了。我们通过将有偏的剩余流量分配一个偏置`id`来避免偏置。 @@ -170,7 +170,7 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 1/\sqrt{N} 的关系,图中的斜线即是 s ,坐标轴上的值出于保密的原因隐去了,但可以看出`cookie`取模的斜线比查询的斜线陡峭,比如在相同的准确度下衡量相同的覆盖率的变化,一个`cookie`取模的实验需要比随机流量实验大的规模。 ![图四](figure-04.jpg) -**图四:在分配类型下计算覆盖度 s 的斜线** +**图4**:在分配类型下计算覆盖度 s 的斜线 因为不同的指标和不同的分配有着不同的 s' ,那么我不应该让每个实验者自己去计算它, 我们提供了一个工具计算实验者指定的关注指标和指标敏感度,分配类型(比如`cookie`取模或是随机流量)和他们想要的某种流量(比如,分配条件,比如日语流量),工具就告诉实验者他需要多大规模流量才可以支持他的要求的实验。实验者可以轻松地在流量大小和敏感量之间权衡,有了这个工具,我们可以认为实验者在运行实验之前会设置合理的实验规模。 @@ -237,7 +237,7 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 -**图五:实验,拥有者,发布数量在时间上的趋势图** +**图5**:实验,拥有者,发布数量在时间上的趋势图 ## 6.2 Better