【干货】AB实验助力用户体验升级(含直播回放)

原创 黄昱 淘系技术  2021-04-15


【干货】AB实验助力用户体验升级(含直播回放)


本文根据4月14日淘系技术前端团队出品的「阿里淘系用户体验优化前端实战系列直播」——《AB实验助力用户体验升级》整理而成。


【干货】AB实验助力用户体验升级(含直播回放)

点击查看直播回放



为什么AB实验能够提升用户体验


【干货】AB实验助力用户体验升级(含直播回放)我们先从一个例子说起,上图中是一个购物频道的首页,产品经理在思考页面上可能会影响到用户体验的因素,他想到这样一个问题,页面重复样式的营销模块过多,导致底部的精选分类模块无法在首屏透出,从而影响了用户体验。试想,如果用户在首屏就能看到精选分类模块,可能会帮助到他们更快的定位想要类目的商品。基于这个思考,产品经理和设计师一起设计了实验组方案,即,将原来多个重复的营销模块合并为一个,这样底部的精选分类模块就可以在首屏展示了。我们设计了一个AB实验来论证新方案的有效性,将频道用户均匀的分为两组,各50%,分别对应两个首页。实验上线后,我们对两组的用户行为数据进行对比分析,实验组的各个指标的确都优于原首页。我们在整个实验周期内,对核心指标(如,点击率)进行观测,发现实验组的优势是稳定存在的。基于这个结论,产品经理选择固化实验组。【干货】AB实验助力用户体验升级(含直播回放)基于前面案例,我们了解了AB实验的基本流程,从产品经理产生猜想,到设计实验,再到实验上线后,我们对数据进行采集分析,并最终做出决策。一个实验的生命周期,实质上就是一个人从思考问题到论证问题的过程。回到本节最初的问题,为什么AB实验可以提升用户体验,我认为有以下三点:

  • AB实验是一种我们与用户的沟通方式;它让我们业务同学,技术同学都能够站在用户的角度去思考问题,通过实验我们了解到用户的真实需求,前端UI的迭代是用户需求驱动的,而不再是“凭经验拍板”;
  • AB实验将用户体验具象化;用户体验是一个抽象的名词,从前面的例子我们也看到,在实验中我们将用户体验转化为客观可量化的数据指标,并根据数据结果更准确的衡量用户体验的提升或者下降;
  • AB实验的科学性,可以极大程度的保证数据的准确性,即我们从数据中提炼出的用户需求是可靠的。实验的科学性体现在分流模型,及底层的决策模型等等,我们在下一章节进行详细的介绍。


前端AB实验技术原理

【干货】AB实验助力用户体验升级(含直播回放)一条完整的AB实验链路到底需要什么?创建实验,工程接入,分流,实验数据回流...恩,是的,我还可以列一大堆,但是它们没有组织不成体系,就毫无意义,更谈不上架构设计。所以,我们来把这些分散的元素尝试归类。

一条完整的AB实验链路其实可以拆分成三部分,第一部分是实验配置,顾名思义它包含了所有与实验配置相关的操作,配置创建,分组,配置的推送或下发,第二部分,在前端工程运行时我们读取实验配置,并进行分流,并将分流结果进行埋点上报。第三部分是实验数据,它包含实验数据的计算,存储及展示(实验报表)。接下来我们就基于这三部分展开来聊一聊其底层设计原理。


  实验配置模型

【干货】AB实验助力用户体验升级(含直播回放)它核心解决的问题是,如何将实验配置按照合理维度进行组合并下发?我们线上运行着数千个实验,如果简单的把每一份实验配置进行单独存储并下发,很快实验配置会多到无法管理,且在多实验并行的页面上也会非常影响性能。如果把所有配置都放到同一个文件里,那显然更不可行。所以找到这样一个合适的维度来对实验配置进行组合非常关键。我们引入了前端应用的概念。前端应用我们可以理解为一个前端工程,一个小程序可以是一个应用,或手淘内某个频道(比如淘金币)也可以是一个应用。我们将实验配置以应用为维度进行组合,然后推送到CDN。前端运行时则通过JSSDK读取配置,完成分流并渲染相应的业务组件。

应用里面包含了场景,一个独立的流量入口我们称之为场景,比如某应用的首页就是一个场景,导购页也是一个场景,每个场景(页面)下都运行着一个或多个实验。实验是在场景里完成分流的,换句话说,场景是我们底层的分流模型。


  分流模型

【干货】AB实验助力用户体验升级(含直播回放)实验在场景内并不是无序放置的,场景里有很多层(layer),大家可以将层简单的理解为一个数学区间,比如[0,100),这个区间代表着该场景下100%流量,在场景里,每个实验都是放置在相同或者不同的层里的。比如上图中,实验一有AB两组,各占50%的流量,且实验一占据了一整个层,这意味着,A组占据了该层(区间)的前50%,即[0,49],B组占据了后50%,也就是[50,100)。


  • 稳定分流

当一个用户进入该场景,我们会首先读取他的唯一id,这可以是他的web设备id,也可以是userid,总之它可以唯一且稳定的标识一个用户。然后我们会将这个唯一id作为入参,运行一个Hash算法,该算法的结果一定是落在层这个数学区间上的某一个位置的,以实验一为例,如果Hash算法的结果处于该层的前50%,那么该用户命中了实验一的A组,反之则是B组。由于唯一id是稳定的,这位用户不管多少次访问当前场景,他落在某个特定层(区间)上的位置也是稳定的,因此他也会稳定的被分流到实验一的A组。

稳定分流保证了线上用户体验的连续性,从而大大提升了用户行为数据的可靠性。


  • 实验的正交、互斥及推全

统一场景下常常运行着多个实验,如何来处理不同实现之间的相互关系,来满足复杂场景下的业务需求。还是以上图为例,该场景下同时运行了三个AB实验:

  • 实验一,红包权益弹层有AB两种样式,观测指标是两个弹层的点击率;
  • 实验二,页面头部商品模块有AB两种样式,观测指标是模块点击率;
  • 实验三,运营投放的营销banner有AB两种设计,透不同利益点,观测指标是banner点击率;


现在的问题是,实验二和实验三都是页面上的模块,我们希望这两个实验同时运行,但不希望它们互相影响,即进入实验二和实验三的流量必须互斥。如何做到呢?如上图所示,实验一独占一层,它与下一层的实验二和实验三是正交关系,即进入实验1的流量,同时也会进入实验二或实验三。我们把实验二和实验三放在同一层,因为我们希望进入实验二的流量不要与进入实验三的流量重叠,即他们各自占据了层(区间)上的一部分流量。通过这样的方式我们实验了,在一个场景里,层与层之间的实验流量正交,层内的实验流量互斥。

在上面的模型图中我们还看到一个特殊的层,发布层(Launch Layer),这个层用来放被推全的实验分组。比如说,经过线上验证实验一的A组效果明显优于B组,用户在平台侧将A组推至全量,这时候场景内部结构会发生变化,即实验一的A组会从原来的layer被放到这个特殊的发布层里,此时该场景内所有触发实验一的流量将不会再执行分流算法,而是直接返回组A所对应的前端组件。


  实验数据模型


【干货】AB实验助力用户体验升级(含直播回放)每一个实验所关注的数据是不同的,如何为不同的实验产出其对应的数据报表?我们引入了业务域,它是数据指标的集合,同一业务域下的实验可以创建并关联这个业务域下的所有指标,形成实验与指标的映射关系。在计算实验数据时,我们会首先读取该映射关系,确定要计算的指标有哪些,然后再进行计算,这样也极大程度的节省了计算资源。


  前端AB实验架构设计

【干货】AB实验助力用户体验升级(含直播回放)有了前面的知识基础,我们来看看完整的前端AB实验架构设计。首先绿色的部分,对于第一次入驻AB平台的业务,我们需要进行相关工作空间的注册,应用,业务,及场景,对应前面提到的三个模型。

创建完工作空间以后,我们开始核心的实验创建链路,这里包含了实验的基本信息的读取,分桶设置(流量分配)。接下来是创建指标并将指标与实验关联的过程。然后是实验发布,正式发布前,有一个beta发布环节,beta发布可以理解为实验上线前的一次“非正式”下发,开发者和业务方可以在beta发布后对实验分流、数据及相关业务逻辑进行充分验证后,再正式发布。当然,实验是支持多次发布的,即实验中期业务方可以回到流量分配这一步,重新调控流量比例,并重新发布实验。

然后是蓝色部分AB实验的JSSDK。先从前端工程说起,我们在工程里引入了一个业务AB实验组件,该组件是AB平台根据用户的配置动态生成的,作为(AB实验相关的)业务组件与页面(或父容器)的衔接器,其核心工作就是读取AB实验所需的参数并传入SDK,以此触发SDK的整个AB实验逻辑。

首先从全局来看,我们把JSSDK拆成了两个包:

  • 一个是核心(Core)包,封装了通用的核心逻辑如实验配置读取及缓存策略,实验周期控制及分流算法;
  • 另一个是接入具体DSL工程的衔接器包(Coupler),如图所示,它就像是一个AB实验流程的中转站,它实现了一套接口函数,即在特定DSL环境下(如React)的请求、缓存及cookie解析(分流因子),并将这些接口函数和实验参数一起透传给Core,我们这么设计的目的是实现Core与前端DSL的彻底解耦,这样极大的增加了JSSDK的可扩展性。


在拿到实验参数,及所需的接口函数以后,Core要做的工作就是先获取实验配置,此时Core不会直接去请求实验配置,而是触发版本控制策略,该策略主要是检查远程实验配置的版本号是否更新,若有更新才会去请求配置,否则会读取本地缓存的配置。这份本地缓存的配置是用户第一次触发实验时从CDN请求并缓存下来的,之后每次版本更新,才会重新请求并更新缓存。拿到实验配置后,Core会确认当前事前是否处于实验周期(AB平台侧配置)内,校验通过后才会正式触发分流算法(见下一章节),然后将分流结果返回给Coupler。

Coupler接着会根据分流结果来判断应该展示哪个对应的业务组件,同时它会将分流结果上报给平台,用户此时已经可以在实验的实时数据报表看到分流数据了,技术同学可以通过实时数据来确认实验是否正常触发。另外,埋点组件会对命中的业务组件做一层封装,这里会传入可供业务组件调用的埋点上报方法,具体的调用我们在AB平台创建实验时,就已经生成好了,前端同学是需要将这些上报实验指标的代码部署到相应的业务即可。这一部分埋点数据是T+1的,业务方可以在平台侧看到相应的实验报表,并分析实验结果。

为了快速覆盖所有的前端场景,我们在设计上慎重的考虑了JSSDK的易扩展性。这也是为什么我们在上一节的Rax 1.0方案中,将JSSDK拆成了Core和Coupler两个包,我们的思路是Core封装AB实验的核心逻辑,不依赖任何前端DSL,在Core与前端工程之间引入一个"衔接器"包,来串联起整条链路。这样如下图所示,我们可以通过这样的架构,非常低成本的扩展到React,小程序,Node FaaS等等。同时也具备良好的可维护性。

我们是如何做到将核心包(Core)与这些DSL彻底解耦的?我们定义了一套接口规范,然后在"衔接器(Coupler)"包中根据这个规范实现一系列的接口函数,当Core在执行某段逻辑调用这些函数时,根本无需关心其底层用的是哪一个DSL的API。比如对localStorage的操作,React和小程序的API是完全不一样的,所以我们在React和小程序的"衔接器"中按照接口规范各自实现了这样一套对localStorage的处理函数,并透传给Core。


  前端AB实验数据链路

【干货】AB实验助力用户体验升级(含直播回放)

在前端工程运行时,分流之后展示相应组件,并触发相关的埋点,如下图所示在埋点参数中,我们会带上实验参数,即实验发布id和分组id,实验发布id是什么呢?前文提到在实验运行中,我们允许业务重新调控流量比例,并发布实验,也就是说一个实验是可以多次发布的,所以实验发布id可以标识采集到的数据是当前实验的某一次发布;这也就是所谓的数据染色过程。

数据上报后,在日志系统形成实时数据流,在数据库会存储到T+1的离线表。我们前面多次聊到了创建数据指标并将其指标与实验绑定,建立实验与指标的映射关系;在平台侧,我们会读取这个映射关系,并以此为依据进行对应数据指标的计算,计算结果会以KV形式存储在非关系型数据库中,便于快速读取,最终我们在平台产出数据报表供用户分析决策。

数据积累到什么程度可以进行进一步决策呢?AB实验平台底层的统计学模型会对我们当前搜集到的数据进行进一步的计算,帮助业务同学进行风险评估。目前业界运用比较广泛的两种方式,一种是频率学派,对各个指标进行显著性检验(计算p值)。另一种是今天要给大家介绍的贝叶斯模型。【干货】AB实验助力用户体验升级(含直播回放)基于贝叶斯算法的风险决策模型,主要计算的是转化率的概率分布。公式中,θ代表的是我们关注的转化率指标,比如,点击率,成交转化率等等;X代表当前已经采集到的数据,p代表概率,那么贝叶斯公式计算的结果 p(θ|X) 代表的意义就是基于当前数据X,转化率指标θ的概率分布。

我们模拟一个简单的实验来进一步说明,假设现在有A、B两个按钮,我们关注的指标是它们的点击率,那么套用贝叶斯公式,我们要计算的,就是基于已采集到的数据X,两个按钮点击率的概率分布情况。
上图中,我们绘制了随着X的增加,两个按钮点击率的分布曲线(概率密度函数,PDF)。蓝色曲线代表按钮A,黄色代表按钮B,x轴代表点击率,x周与曲线之间的面积代表概率密度。当采集到的数据极少的时候(图1),我们队两个按钮的点击率的分布估计是很不"自信"的,它们的PDF在0到1之间都有取值,且两条曲线有大面积的重合,这样我们也很难判断它们哪个是更好的模型。
但是随着采集数据的增加,两条曲线发生了变化,它们在x周上的取值区间越来越狭窄,这意味着我们队两个按钮点击率的估计越来越准确。直到最后一张图,我们看到代表按钮A的蓝色曲线,点击率集中分布在0.6到0.7之间,而代表按钮B的黄色曲线,点击率集中分布在0.35到0.45之间,到这个程度已经很明显,A的点击率分布是优于B的。这是否意味着可以推荐用户固化A组了呢?其实还不够,我们继续看看下面的风险评估流程。【干货】AB实验助力用户体验升级(含直播回放)我们不断收集数据,并对A、B的点击率的概率分布进行建模,然后比较两个模型的优劣,并得出A是更好的模型。这时候我们会进一步计算基于A的损失函数,我们会最终得到一个值,这个值代表选择A而这个选择是错误的概率密度。我们会预先设定一个阈值,如果计算出选择A的损失是高于这个阈值的,我们会进一步采集更多的数据,并重复上面的流程,如果低于这个阈值,那么可以认为当前决策的风险是可接受的,我们这时候才会推荐用户去做进一步决策。

案例分享


  花呗分期小程序


【干货】AB实验助力用户体验升级(含直播回放)这个实验中,两个模块样式完全一致,唯一变化的是其利益点。一个是展示日均价格,另一个是展示分期价格,业务方的猜想是日均价格利益点能带来更好的体验,因为它帮助用户做了更进一步的计算,所以预期展示“日均xx元”利益点的点击率要优于“¥xxx/期”利益点。

而实验上线后,我们发现结果与我们的预期完全相反。从累计数据以及每日趋势数据得出,在曝光一致的前提下,¥xxx/期利益点比日均xx元利益点点击率稳定高出了20%,可见用户想要的跟我们的认知其实有着很大的出入,这引起了我们想要进一步探索频道利益点的想法,于是设计了下面的组合实验。【干货】AB实验助力用户体验升级(含直播回放)如上图所示,我们将首页的各个模块,通过不同利益点组合,并强化某一利益点的方式呈现,希望寻找不同组合方式下的最优方案。我们将页面拆分成两个实验,实验一,将首屏的一拖三模块均分为三组,将日均,分期及期数三个利益点组合,并强化其中一个利益点;实验二,将底部商品feeds流模块分为四组,分组策略与实验一相似。结合前文提到的温流模型,这两个实验属于正交关系,也就是说我们将首页流量排列组合成12(3x4)组,我们期望根据实验数据,最终得到最优的组合。

【干货】AB实验助力用户体验升级(含直播回放)

【干货】AB实验助力用户体验升级(含直播回放)两个实验在线时间两周,从数据报表看出,实验一的第三组的表现要优于其它组,其中全引导宝贝订单UV及直接引导宝贝订单UV与另外两组的差别仅为1%,可以认为是持平,但其中全引导宝贝及订单数均有10%左右的增量。当然我们也观测了每项指标的在两周内的变化趋势,此处以直接引导宝贝UV为例,第三组强化期数在实验周期内的确稳定优于其它组。同样的方式我们分析实验二的数据,通过观测多项指标在实验周期内的均值,及其变化趋势,第四组相对表现更好。通过实验数据,业务最终决定固化实验一的第3组,和实验二的第4组,这是我们从两个实验正交,排列组合形成的12个分组中,得到的最优解决方案。

【干货】AB实验助力用户体验升级(含直播回放)

  虚拟充值


【干货】AB实验助力用户体验升级(含直播回放)虚拟充值业务,10元20元的小面额有一定概率缺货,给用户带来不好的体验。我们认为,如果能优化这一点,会让更多的用户使用该频道的充值服务,从而提升频道的GMV,和充值UV。于是我们设计了实验组1,也就是把常缺货的小面额折叠起来,将其它供货稳定的面额提前,实验上先后,相较于对照组,实验组1的GMV的确有提升,但支付UV下降了。我们分析这是由于频道有一部分用户是倾向于充值小面额的,但实验组1将小面额折叠起来,导致这部分用户放弃了充值。这显然不是一个理想的方案,于是我们设计了实验组2,将所有面额展示给用户。实验组2的确带来了GMV和支付UV的提升,这是一个满足我们预期的方案,但产品经理认为,这种方式的一个问题是,充值模块占用首屏过多的空间。【干货】AB实验助力用户体验升级(含直播回放)进一步思考,实验组1方案之所以不可行,是因为我们认为它牺牲了一部分喜欢充值小面额的用户的使用体验。那如果我们圈选出一部分本来就喜欢充值高面额的人,在这个特定的人群下进行实验,效果会是如何呢?实验结果是,在这个特定人群下,实验组1实现了GMV和支付UV的提升。于是在这个特定人群下,我们固化了实验组1。

【干货】AB实验助力用户体验升级(含直播回放)

总结


本次分享为大家深入介绍了AB实验的底层原理,以及前端AB实验的架构设计。我们也提供了丰富的案例,为大家介绍了如何运用AB实验技术提升用户体验,希望大家有所收获。AB实验在前端的应用我们还在持续探索,如何进一步降低UI实验的成本,进一步提升实验性能,是我们接下来希望能回答的问题。如果你也感兴趣,欢迎加我的微信MrMarc随时与我交流。谢谢大家。

上一篇:【干货】淘金币用户体验升级(含直播回放)


下一篇:【端智能】MNN CPU性能优化年度小结