一、信息流场景面临的挑战与重排模型的独特优势
对于重排很多同学可能感到陌生,下图是工业界中推荐系统一个常见的 pipeline。当用户来到手淘时,会从亿级的候选池中先召回万级的宝贝,然后把万级的宝贝交给粗排模型打分之后再从中精选出千级的宝贝给精排模型,然后精排模型会交付几十上百的宝贝到重排模型进一步打分。
从打分量和效率角度来讲,前序的模块打分量非常大,对其效率要求也非常高。依次往后打分量减少,效率也会慢慢降低,这里的效率指的是单个宝贝打分所需要消耗的计算量。正是因为消耗了更多计算量,后续模型的打分精准度也会变高。
重排是由阿里巴巴庄涛在 18 年首次正式提出的概念,从字面意义来说就是重新再排一遍。除了打分量和精准度之外,跟前序模型相比,重排模型的一个显著的区别是会显示建模宝贝之间的相互影响,称为 context information。
比如把上图的宝贝在手淘上展示给用户时,由于中间的宝贝跟周边的宝贝在颜色、大小上有着显著差别,用户就会以更高的概率去点击这个宝贝,这就是非常经典的context information 的应用。
下图是目前复杂信息流场景所面对的挑战,以及重排的独特优势。
右边两张截图是手机淘宝,在推荐按钮位置稍微往下滑,就可以看到【猜你喜欢】的业务,它的产品形态是一个双列流。所谓流就是用户可以不停地下滑,随着流的下滑可以接收到更多信息,这种产品形态称为信息流。之所以称它复杂,是因为它里边有直播、商品、图文、视频,还会间或的有一些用研相关的内容。在推荐旁边有一个关注按钮,这个流里边展示的是用户在手淘关注的店铺或者达人相关的内容,是一个大卡的单列流,如果是商品通常是以商品列表的形式展出。
后续分享的实验结果均来自“关注”流,这两个场景不像其它一些简单目标的推荐场景,比如说同店的六宫格宝贝推荐,以促进成交为唯一目标。在这样复杂的信息流场景中,面临着非常多的挑战。
- 第一点是要打散,要求满屏的内容,店铺不能扎堆,类目品类不能扎堆,不能满屏都是连衣裙,展现样式也不能扎堆,不能满屏都是直播。
- 第二点是会有流量控制,举例来说,为了撬动商家的供给,或者保持商家生产内容的积极性,通常都会有冷启助推计划,比如商家主动发布了新内容,在三天之内会确保有 100 个曝光,这部分内容就叫做冷启内容,通常会确保里边有一定冷启内容的占比。
- 第三点是多种形态的混合,如直播、商品、图文以及视频,这种混合流的困难一方面体现在每一种供给背后的表征是对不齐的,或者说直播跟商品拿到的特征对不齐,当特征维度不一样的时候,如何做一个混合流是一个难点。不同内容的曝光带给用户的价值也是不一样的,如何做统一的价值衡量又是另外一个难点。
- 第四点挑战是多路供给融合,供给的概念是指这一部分有不同的生产链路,或者独立的召回打分链路,跟内容形态不一定强耦合。比如说都是直播,可能是达人直播,也可能是店铺直播,背后有不同的生产链路。
- 第五点挑战是多目标,同店商品的推荐只会有一个目标就是成交,而关注信息流里我们每天紧盯着的指标就有几十个,展开可能上百个,大体可以分为用户的体验指标、效率类指标、商家生态指标以及子业务的目标。比如直播和商品背后可能是两个业务团队,他们的业务目标之间有重合的部分,也有不同的部分,需要通过推荐分发做到共赢。
Context 信息的感知与控制能力是应对这些挑战的杀手锏。以第一个挑战打散为例,当想在某个位置放入某个商品时,重排模型会去看周边的内容都是来自哪些店铺,这叫做 context 的感知。在放商品的时候可以避开这些商家,以确保店铺是不扎堆的,这个称为重排模型对 context 的控制能力。
传统方案通常是用 pipeline 的方案串联一系列内容与功能相对单一的模块。比如每一路供给精选出了最好的宝贝后,先融合完再做一个店铺打散。如果冷启占比不够会随机性地插入一些冷启的内容,还会有置顶的环节,根据业务需要把某些内容放在整个推荐结果的最顶部。仅是三个模块就可能牵扯出很多爱恨情仇,前后耦合,很容易相互踩脚。比如打散后店铺是不扎堆的,但插入的冷启内容可能跟周围的店铺是重复的,就打破了前序的结果。如果插入的时候还要看是否满足店铺打散这个需求,又可能导致冷启内容插不进去了。冷启和置顶之间也是类似情况。
还有一个问题是这种模式下每个模块功能相对单一,但在系统层面却缺少联合优化的可能,导致整个系统最后推荐的结果是次优的。有同学说会不会是模块之间的顺序不对?也有可能,但我的理解是不存在一个真正好的序能够消除各个模块相互之间的踩脚,今天要分享的就是如何使用重排模型彻底推翻这种 pipeline 推荐范式。
基于复杂目标的重排方案,在每一路供给精选出候选集后,把候选集全扔进重排模型就会直接生成最终的推荐序列。主要优势体现在两点:
- 一是基于重排模型强大的 context 感知与控制能力,可以兼顾到前文提到的全部挑战;
- 二是它本身是一个深度神经模型,可以在大数据的驱动下给出 end to end 的联合最优解。
二、重排模型的建模范式总结
重排模型大致可以分成三种建模范式,简称为 V1,V2 和 V3。
V1 版的特点是尝试捕获输入 item 之间的相互影响,即部分捕捉 context 信息,有部分 context 感知能力,单点打分,贪婪排序。
比如有 5 个候选宝贝,来自绿色店铺和黄色店铺两家。重排模型 V1 版可能是通过 RNN 或者 Transformer 的结构去捕获建模它们之间的相互影响和相互关系,给每个 item 单独打一个排序分,按照这个分数从大到小的顺序排列,再截取 top 宝贝透出作为最终的结果。
这版模型存在一个问题就是对于这些宝贝是否来自一家店铺没有控制能力。如果想确保来自不同店铺,就要加入店铺打散的逻辑,反过来看这个重排模型就不是输出最后的结果了。所以 V1 版重排模型缺少对 context 的控制能力。
V2 的特点是在 V1 版的基础上加上了序列选取 item 的模式。具体来说,会通过 encoder 去拿整个 context 的 embedding,之后会逐个选取 item。举例来说,在这个 case 中,已经选取好前 n 个 item,希望选取第 n + 1 item。该模型会先计算出一个 state 变量表示当前这个位置应该怎么选宝贝,然后会拿 state 跟各个候选 item 算 attention,attention 的值跟 item 选取概率高度相似,大体上会根据 attention 值的大小来选择一个宝贝放在当前这个位置。每选出一个宝贝后 state 都会马上更新,所有的 attention 值会重新计算。这种建模范式下,就实现了对 context 的控制能力。
当选择第 n +1 个宝贝的时候,因为前序 n 个宝贝已经选定了,他们来自哪个店铺也确定了。选 n +1 的时候,通过看前面的宝贝避免有重复的店铺出现就可以了,所以对 context 有比较强的控制能力。
但 V2 版重排模型的瓶颈在于需要手动给出每一步的最优选择作为 label,因为该重排模型是基于监督学习的范式来训练的。给定候选集宝贝、用户当前的实时状态和前序 n 个宝贝的选择,需要告诉模型这一步的最优选择是什么才可以让模型训练。
但问题是给出这么多前序设置怎么知道这一步应该选什么呢?监督训练在推荐系统中用得很多,特别是精排模型。拿到用户特征和商品特征,输入一个 CTR 点击精排模型去进行点击率预估。线上这个宝贝透给用户,能真实知道用户有没有点击,很容易回收一个点击或者不点击的 label,训练时最小化预测值和实际值的距离就可以做好模型训练。
但要把监督训练套用到重排模型就不成立了。比如说有用户特征,有 m 个商品和它们的特征,喂入一个重排模型预估了一个最优序列,比如 12345,需要给出最优序列当作 label,比如这个 case 里边最优的序列应该是 34125,通过最小化这两个变量之间的距离来做模型训练。
但问题是在复杂情景中,比如有多种内容供给、多种目标、多种业务需求情况下,如何知道最优序列是什么呢?如果已知最优序列,为什么还需要训练一个模型呢?在相关研究中,大家会提出一些寻找最优序列的探索方式。比如把购买的宝贝放在第一个,点击的宝贝次之,其他的随便排,这里其实是人为构造出一个最优序列。但在这种训练模式下,构造出来的序列好坏直接决定了重排模型的上限。基于上述原因,提出了重排 V3 的建模范式,其特点是在 V2 的基础上加了 reward 驱动训练。
首先有一个 actor,给出一个用户和候选商品序列时,它负责生成一个序列。另一个重要模块叫做 evaluator,当一个序列给到它时,它会对这个序列做出评估,reward 分反馈给 actor,actor 就会根据 reward 的大小来调节生成序列的策略。
基本的思路是如果模型看到了一个大 reward 分的序列,当以后再遇到相似的情况下,模型就会以更大的概率生成当前这个序列。
reward 有两个非常突出的优势:
- 一是它无需 label。生成一个序列后,evaluator 只要能对当前这个序列做评估就可以了,至于最优序列和其 reward 是什么无需要知道。
- 二是它无需可导。在信息检索领域,通常用 NDCG 来评估推荐的结果,但训练时绝大部分工作不会直接优化 NDCG 指标,一个重要原因就是 NDCG 不可导没有办法计算梯度,没法做深度模型训练。但 reward 不需要可导,从而可以在 reward 里边非常灵活地加入各种各样的计算。比如店铺打散,结果序列中店铺的个数就是一个很好的 reward,虽然它显然不可导。
三、有机融入多目标的重排模型
在这个建模范式下的重排模型都可以很优雅地融入各种业务目标。
基于 V3 版的设计如上图。输入是一个 user,m 个 candidate item,分别是 C1 到 Cm,一个 reward function Rw。Rw 是把 w 当做参数,进行线性求和,求和的项是 w 乘以 utility function U。U 可以是点击、冷启内容的占比等各种各样的业务目标,w 是业务目标的融合权重。
希望 output 能满足 argmax Rw 条件,给出 user 以及目前的候选集,在候选集里边的宝贝拼出来的任意序列中,挑选 Rw 最大的标星序列,记为 Lw*。模型的任务就是在这个序列存在的前提下找到 Lw*,如果有多个那么返回任意一个都可以。
完成这个任务的最基本的思想就是训练一个 actor,当给定一个 item candidate 集合的时候,actor 跑一遍正向运算,然后会给出一个最优序列。充分训练之后,就会认为它生成的这个序列趋近于 Lw*。
序列生成器 actor 本身是一个 encoder 加 decoder 结构。给出 input items 和user,会首先选用一个 DeepSet encoder,拿到整个 context 的 embedding,然后逐个选取宝贝,选取宝贝的是一个 PointerNet decoder,整个结构大致上来说跟 v2 版模型是一致的。每选取一个宝贝 state 就会立刻更新,attention 值也会全部更新。正因如此,重排模型的计算量比较大。
序列生成器的 encoder 选用的是 DeepSet,也就是用 deep network 去建模一个set,set 中的元素之间是不存在序的。重排模型只要知道 user 和 candidate item 的相关信息就够了,不需要有一个初始序。因为在复杂情况下,如果生成了一个很糟糕的初始序,很有可能伤害重排模型的表现,所以最后放弃了给模型一个初始序,就而是把 user 和 candidate items 直接交给重排模型。
具体的做法是,输入 user 特征和 item 特征。首先会做一个 item 的 feature augmentation,这里新加的特征可能是这个 item 的 price 在所有 item candidates 之间的排序;也有可能是它的店铺在 item candidates 中重复了几次,类似于这样的特征。
之后通过一个 embedding lookup,把一些 ID 类的特征转换成 item embedding 来参与数值计算。把 user 的embedding 和每个 candidate 的 embedding 进行拼接跑几层 MLP。这些 MLP 是几层 DNN,每一个单独跑,再把每一个 item embedding sum 起来,再过几层 MLP。
序列生成器中的 decoder 是一个 PointerNet 的 decoder。拿到了 context 的embedding 后,开始逐步选取宝贝。首先把 embedding 当做 RNN 的初始 hidden state 喂入 RNN,一开始会喂入一个特别的 TOKEN start,然后 RNN 计算的 output 当作 stage。拿到key 之后,会跟每一个 item 计算 attention,这边用的是 local context enhanced attention。
拿到每个item attention 后,会做 masking 操作,主要有两个原因:一是如果一个宝贝的前序已经被选择了,就不能被重复选择,所以这样的宝贝的 attention 值会被 mask 成 0;二是如果业务要求把这个宝贝放在这一位,会把除了这个宝贝之外的其它宝贝的 attention 值全部置0,在接下来的 sample 过程中就一定会选择这个宝贝。
在训练的时候一定要有 sample 的过程,因为 sample 过程引入了随机性,让 actor 会去尝试不同的序列生成策略,最终能够找到一个好的策略。图中所示的 case 选择第一个 item ,会把它喂入 RNN,迅速更新 state 或者 context 信息,然后再去选择下一个宝贝。
黄色部分是 local context enhanced attention,除了 item embedding 和 state,还有一个针对 state 和 item 的 local context。左边的 Vector 是手搓出的一系列特征,如第一个特征是目前为止冷启内容的占比是多少,第二个是当前这个 item 在前序有没有重复,帮助重排模型做好店铺打散。整体来说,这一系列加工的特征可以帮助模型快速捕捉业务意图。
这里的建模思想是有些变量之间的关系,只能依靠数据模型以及训练去捕捉拟合,但这样的关系应该限制在那些复杂且无法表达的变量关系。如果有一些清晰明确的规则,应该尽量清晰表达,而不是靠模型摸索。一是没有必要,二是这样做是低效的,所以添加了一个 local context enhance 的参数模块。
序列评估器 evaluator 对模型离线训练时生成的序列进行评估。比如这一整页会不会有用户点击,点击概率的预估只能依靠模型。拿到 user 和 item 之后,会跟 actor 里边一样做特征预处理,拿到每个 item 的 embedding,concat 起来作为整个序列的表征。然后用 5 个 channel 分别去从不同角度提取这个 list 当中的特征,包括常见的 multihead attention、RNN 等。之后会把这些 channel 捕捉的特征结果 concat 起来,再过 MLP 输出最后的 prediction,比如用户会不会点击这一页上的任意一个商品或者点击数是多少。其他的 channel 就不详细展开了。
evaluator 模型用的是标准 loss。比如想训练这一页推荐结果用户会不会有点击这样一个点击率预估模型,会用一个 0,1 的 label,用标准的交叉熵 loss 去训练 evaluator。充分训练 evaluator,然后锁死,再开始训练 actor。
这边用到强化学习的一些算法。目前用的是 REINFORE based Algorithm,这个 REINFORE 是非常经典的一个 RL 算法,在它的基础上加了一些小而常用的 trick。
训练 Generator 的 loss 有两部分内容,一部分是 reward 相关的,一部分是模型生成这个 list 的 probability。给定一个 user 和 candidates,generator 会生成一个序列,这个序列喂进 evaluator ,或者是 reward function,可以拿到一个 reward 的评估。然后减去 baseline 也就是减去线上真实曝光的那个 list,因为离线训练的数据是通过 log 获取的,所以线上真实知道当时的曝光序列是什么,这个序列也进入 reward function 拿到一个 reward 值,对它们进行一个减的操作,希望生成高于线上或者优于线上序列的结果。
第二部分是乘一个 probability 项,给定 user 和 candidates,计算 generator 生成这个序列的 probability 。训练的核心思想就是 reward 得分高的序列应该有更大的概率被生成。
比如有 4 个 candidate items,生成一个长度为 4 的序列。第一步计算每个 item 的 attention 值,在这一步的时候,选择了第一个 item。第二步会更新 context,计算剩下三个 item 的 attention 值大小,比如这一步选择了 0.8 的这一个。接下来走到第三步的时候,就只剩两个 candidate 了,这一步选择了 0.4,注意这里是有采样的一个动作的,所以不一定选到 0.6 的这一个。到第四步的时候,就只有一个 item 可选了,则该 item 的 tension 是 1。
在这个case 里边,generate 模型生成这个序列的概率是 0.5*0.8*0.4*1,就把这个概率值放在这个位置,模型只要去不停地 minimize 这个loss,就可以让高 reward 的序列有高的生成概率。
我们的论文中对线上的一些业务目标做了总结,分成了四大类,每一类都介绍了如何将它有机地融入重排模型,比如说 reward 或者 utility 应该怎样设计。感兴趣的同学可以去看 paper,里面都有比较详细的论述。这样就设计好了一个重排模型,可以有机的融入多种优化目标。
接下来探讨如何灵活调节多目标之间的权重。
四、基于超网络的实时可控重排模型
实时可控多目标之间的权重的设计动机是:首先有一个 assumption,reward function 是线性加权求和的形式,把这一部分 term 称为 utility function。一个 utility function 就是从一个维度去评估序列,比如用户点击率、多样性、新鲜度和新颖性等。无论这边是需要模型预估的utility,还是可以手写出公式的 utility,当训练 actor 的时候,都认为 utility 是一个固定的 function,所以整个 reward function 里面可以变的参数就只有 w,而这个 w 又表示了对各个目标之间的一个倾向。
在传统的 preference weights 里这是一个静态的模式,w 在模型训练一开始就要指定。如果出于一些原因必须要调节 w,则必须重新训练整个模型,就会非常费时费资源。有一系列工作在尝试帮助如何寻找到最优 w,也有些工作会在训练的过程中不停地去调节w,以达到最好的效果,我们的工作则跳出了这个框架,整体的思路不是去寻找某一个最优的 w,而是任意给一个 w,都能生成最好的序列,这种形式称为动态指定 preference weights。
当用户来到手淘时需要给他做推荐,在这个瞬间可以指定一套 w,模型就根据这套 w 生成最优序列。这样的好处:一是可以实现快捷的超参调节,以冷启占比为例,怎么知道其 w 应该写多大,实操中往往是上线不断地尝试,但如果需要重新训练模型即使是增量数据的训练,也可能需要几个小时甚至几天,而如果有了这种快捷的超参调节能力,只要调一调w,看一看线上的实时监控是不是 OK ,如果不 OK 再调一调,可能几十分钟,或者最多半天就可以完成了。
另外这种方式能更快速响应流量变化,做到更精准的流量控制。特别是在大促的时候,前五分钟跟后五分钟的流量都是不一样的,我们要对流量的变化快速做出响应,即使是线上流式训练的模型其实都做不到这种 0 delay 的实时响应速度。
第三点也是我们认为对业务影响最大的一点,就是可能根本不存在一个最优的 w。对于不同的流量,最优的 w 就应该是不一样的。比如对于新用户,最重要的是让用户了解、喜欢这个场景,就会分发跟用户相关性更高的一些内容。但对于成熟用户,那可能希望更多给他带来惊喜性与发现性,惊喜性与发现性的 w 就会调得更大。
综上,业务上其实更合理的应该是运用分人群、分策略的 w 配置,或许还可以做分流量来源的策略,可以不停地分,做到千流量千策略,传统模式下,每一次切分,就要训练更多的模型,但在我们新提出的动态方案下,只需要一个模型。
目前这项工作发表在最新的 KDD2023 上,论文名是《Controllable Multi-Objective Re-ranking with Policy Hypernetworks》,整个技术方案的要点就是 Hypernet 和 conditional training。
下边的框里是任意一个重排模型,上面的框是新加入的 Hypernet 的部分。线上 serving 部分,当一个用户和他的 candidate item 来到场景时,可以实时指定一个认为正确的 w,交给 Hypernetwork,它会生成一组参数交给重排模型。蓝色加黄色,是重排模型的参数,分为两部分,一部分是 θw,是对 w 敏感的参数,比如重排模型 DNN 最后几层的 w 和 b,也就是最后几层的权重和 bias,是对 w 敏感的。而模型大多数的参数,认为是对 w 不敏感的。比如每个 item 的 embedding 表征对 w 应该是不敏感的。当线上 Hypernet 生成 θw 时,重排模型就可以用完整的 θ 去生成一个序列,因为这部分 θw 是跟着 w 走的,所以也认为生成的序列就是最接近 Lw* 的那个结果。这个是 Serving 时,网络正向计算的过程。
当一个训练的 sample 进来时,这里的一个 trick 会随机采样一个 w,采样的范围就是事先指定的一个 distribution,这里需要一些先验知识来指定 w 的采样分布,为每一个 sample 或者每一个训练 batch 指定一个 w。走正向运算,当重排模型生成一个序列时,需要将它交付给 Evaluator 做评估。Evaluator 也会根据采样出来的这个 w 对序列做出评估,这个 reward 可以转化成一个 gradient,这个 gradient 就会流到 Hypernet 来 update 它的参数,同时也可以流到重排模型里面去 update 那些对 w 不敏感的参数。
Conditional training,借鉴了 Conditional GAN 中的一个技术,用到了重排模型的设计当中。
上图展示了线上的结果。左边的实验是训练好的一个实时可调控的重排模型,线上也随机采样 w 做投放。比如第一张图中,横轴是点击的 utility 的权重,而纵轴是线上真实回收出来的样本的点击平均值。例如图(a)中,横轴上是 0.5,这个点是把线上投放时候点击的权重是 0.5 的那些 case 收集起来,统计他们线上真实的点击率是多少,逐一画出这些点来,就得到了蓝色的折线。橙色的直线是一次拟合。可以看到,当点击的 utility 权重增大的时候,整体的点击率或者说点击数量也有着明显上升的趋势,说明重排模型确实能够依据给定的 w 生成不一样的序列。
基于相同的思路,图(b)展示的是冷启内容的占比,图(c)是店铺的多样性,图(d)是组间排序的 utility,表示来自不同 group 的内容,大致要按照 group 的优先级排序。这四幅图说明重排模型确实调得动。右边是 online AB test 的结果,baseline 方案就是一开始提到的 pipeline 模式,实验方案是实时可控的重排模型,用线上超参调节,调到一个比较好的位置。可以看到在用户点击、用户看到的商家数量、冷启占比、组间的排序、停留时长以及用户看的内容的数量等方面都有着不同程度的提升。
五、结语
相关工作是由阿里巴巴以及人民大学合作完成的。我们来自大淘宝技术私域用户算法团队,负责手机淘宝商家私域产品,包括店铺详情关注的相关算法。通过对海量数据的分析与学习,帮助亿万用户在商家私域高效地买和逛,辅助千万商家运营好用户。同时我们也是一支注重创新、乐于分享的团队,不少成果已经整理发表在了 AAAI、SIGIR、WWW、KDD 等国际顶会上,这里有海量的数据、充足的计算资源以及丰富的应用场景等着你来挑战。想进一步了解可以发送邮件到这个地址或者微信扫二维码。
六、问答环节
Q1:线上每个用户个性化的权重是怎么得到的?
A1:虽然从技术上来讲可以支持每个用户,甚至是每个用户每次访问的权重都可以是不一样的。但是线上会把这个粒度打到人群,就像我刚才说的新人和老用户是不太一样的,是做到人群层级的。至于每个人群是怎么设置,这个主要取决于一些偏业务的要求,比如说需要多少的创新性和相关性,这个是业务上定的。而一些比如说冷启的占比是通过算法确定的。
Q2:线上 serving 不同,不同流量权重不同,那离线训练的时候权重也不同吗?
A2:线上 serving 权重不同,离线训练时的权重也不同。一个重排模型在线上能为一个权重生成好的序列,一定是因为它在离线训练的时候就已经见过这套权重或者相似的权重了。所以在离线训练的时候,对于每一个 training 的 sample 或者每一个 training 的 batch,都是采样一个 w 做训练的,因为不知道线上真实会遇到什么样的 w,进行采样。
Q3:w 选取是什么分布?
A3:这个确实是被问到比较多的一个问题。首先会有一些业务的输入,就是专家的先验知识,如果这个不 ok 再进行手调,比如说冷启的这个权重基本上就是手调的。但在论文中,为了验证这个算法是一个更加 general,不需要过多先验知识的方案,把 w 的分布设置为从 0 到 1 的一个均匀分布,然后线上也是在这个范围之内做调节的。
Q4:重排用这么复杂的模型为什么不在精排做?
A4:因为做不了,各个模块从左到右计算变得越来越复杂,重排的计算复杂度一般是 m 乘以n,m 是输入的 item 数量, n 是需要返回的 item 数量,就是序列的长度,它的计算度是 m 乘以 n。通常来说,重排模型的输入可能是 50,返回的序列可能是 10。但是精排模型的打分量级是千级,是 1000。如果说像重排这样建模,它的复杂度就会变成 1000 乘以100,这个在线上是扛不住的。
Q5:打散规则和冷启策略如何得到保证,然后有概率出现相同的店铺吗?
A5:这是个好问题,其实业务需求里边有些是硬规则,有些是软规则。比如说有的时候某个 item 必须放在第一位,就是置顶的需求是强需求,一定要百分百保证实现的,用户可能在其他的地方点了一个宝贝,一般会把这个宝贝称为一个 trigger,这个 trigger 宝贝一定要做到所见即所得,它一定得是放在序列第一个的,所以是一个强规则,百分百得保证。但这个事情通过在 reward 里边加 utility 是无法实现的,而通过使用 masking 可以实现,如果需要将某个 item 置顶,那会把其他所有的 item 的 attention 值置成 0,这样选择的结果一定是第一个 item,这是能百分百保证的。
但是其他的像是店铺打散、冷启这些是软规则,只要大概率实现就 OK 了。如果用户当前真的非常喜欢耐克,他就是想去买球鞋,那我给它连续出两个耐克的 case 是可以接受的,没有什么大问题。打散规则也是一个软规则,绝大概率说是可以打散的。其实线上方案里重排模型后边还有一系列的硬性用户体验规则限制,如果不满足这些用户体验规则,重排模型输出的结果就会被放弃。如果碰巧生成了一个对这个规则来说特别糟糕的序列,比如说连续四个店铺都粘在一起,那这个结果会被后续的体验规则卡住,然后这个结果也会被弃置,会用备选的 baseline 方案。
用户对于冷启策略感知并不强烈,所以冷启没有后续的强制规则。通过调节权重,看冷启任务完成度的指标调控。当然冷启本身就有闭环调控,当前状态冷启的占比是有一个实时反馈链路的。冷启的信号是有一个 PID 闭环控制信号,即使权重一样,闭环调控的 PID 信号也有强有弱,如果冷启发得不够多,PID 控制信号就会变得更强。重排的 w 以及闭环调控的 PID 信号,两个一起来保证冷启完成度。
Q6:重排整体耗时,P99 指标大概多少?线上特征数量级以及线上处理耗时大概多少?
A6:大致是 20 多一点,应该不到 25 毫秒。基于精排模型打分,重排模型不需要使用太多特征就可以实现不错的表现,所以目前特征使用得不多,这是耗时低的一个重要原因。
Q7:淘宝 feed 里不仅仅有商品,还有直播,这套框架如何考虑到题材一致性的?
A7:这个其实是整套设计最精髓的地方之一。我的答案就是我不考虑。因为很难总结出来视频下边应该放一个宝贝,还是视频下边应该放一个直播?因为真得不知道,所以应该去避免主动确认这个问题。把这些个视频、直播、宝贝全部都给重排模型,然后重排模型就去看,可能今天这样拼,明天这样拼,但是他会不停地 get 到用户的反馈。比如今天这样拼用户点得更多,那就尝试继续这样拼,如果大家不买账,那以后就避免这样拼,这个事情是靠 Generator,靠 RL 算法自己去探索出来的。
Q8:不同物料的特征怎么统一?例如直播物料和商品物料的特征差异会比较大,怎么做比较统一的特征?
A8:我认为这也是重排模型来做混排的一个优势,不需要统一物料特征。作为一个特征来讲,如果这个特征真实包含了丰富的信息量,且是稳定的,就是好特征。比如说视频内容返回了特征 ABC,然后宝贝内容返回的特征叫做 d、e、f,可以用统一表征,比如说特征最后变成每一个 feed 都用 ABCDE 去表征,只不过会有一半是 0,只要把这个拼起来的特征直接喂给重排模型即可。至于两组特征怎么去做统一或者对齐,交给重排模型,交给大数据,交给训练就 OK 了,不需要担心的。
Q9:重排使用精排模型的分数,后续精排模型迭代的问题怎么解决?
A9:精排模型非常重,可能一个精排模型不经过压缩就大几百 g 了,这种规模的模型很难做一些类似于采样、loss 设计等操作。所以精排模型的定位就是把核心的预估做准,预估的点击率的分布应该跟真实的点击率非常靠近。精排稍稍调整一些模型结构,预估的 CTR 值的分布应该是不会大变的。在这种情况下,前后耦合的问题没有那么强。
当前序模型有比较重大的改变,比如说从点击率的预估变成了点击数的预估,后续的重排模型是没法直接应用的。而精排模型可以额外预估点击数,但点击率还是要传到下游模型。有时精排如果做采样策略的一些调整,预估的点击率有可能发生明显的改变,比如原来不做负采样,现在随机抛弃一半的负样本,这种情况下会让点击率明显比原来增加一倍。为了解决这个问题业界经常用的一个办法是做校准,通过一系列的操作,把预估的点击率锚定到真实点击率含义上的那个物理值去,保证这个预估值到达重排模型的时候是稳定的。
Q10:重排要生成的序列长度大于最后的曝光序列,那目前序列中评估器序列长度是最后的透出序列长度吗?输入的是精排排序长度是多少?没有透出的商品在生成器 reward 是什么?
A10:C 端用户的体感是一个无限下翻的信息流,但实际从技术侧来看推荐是分页走的。比如说 10 个内容会先推一页,用户差不多把 10 个内容看完,再推荐下一页。所以至少目前的方案里边,评估器输入的序列长度就是 10,这个是跟着每一页的长度走的。
重排模型的 page size 是 10,重排序列生成的序列长度也是 10。目前训练中评估用评估器训练长度是最后透出序列的长度。重排模型输入的序列长度一般是几十,最多就上百这个量级。
没有在线上真实透出的商品,也会埋下来再放在那个 candidate set 里边,交给重排模型,重排模型是有可能选出原来没有透出的内容的。也正是因为会透出原来线上没有真实透出的宝贝,一旦出现了这种场面,除了用 Evaluator 之外,没有其他的手段去判断这个序列用户会不会点击,或者有几次点击,这个是没有办法的。极端情况下可能透出 10 个宝贝,线上没有一个展现,那这个序列用户到底会不会点击,log 下来的数据是不会有这个信息的,只能用 Evaluator 做评估。
Q11:请问论文中有没有 RL 训练不稳定问题?
A11:RL 就是不稳定,数据不变,模型不变,随机种子不一样,可能这一次行,下一次不行,这也是 RL 难训练的一个体现。如何能让模型训练得更稳定,是一个值得研究的问题,目前用一个简单粗暴的办法,这次垮掉了,那再试一次,多次尝试后通常可以获得较好的效果。它只要效果相差不大,上线之前会有检测,如果垮掉了,那再试一次。模型目前是用精排的特征,所以整个模型不大,几个钟头就训练完了。
Q12:线上推理时 Generator 一次产生多少个序列,然后进行打分的。
A12:其实现在 generate 线上和训练的时候,是两种工作状态,线下训练是采样,推到线上后它会切换成贪婪形式,就是说线上一定会在这一步选择 attention 值最大的 item,所以它只需要输出一条序列。
后续在其他同学的工作下,上线了多序列重排模型,线上也可以开启采样,Evaluator 也推上线了,Generator 通过采样生成多条序列,然后 Evaluator 再从中选优,透出最优的一条序列。现在线上全量推的是这个方案,不单是 generate 的输出结果,也尝试用其他手搓的序列,一起丢给 evaluator,从中选最优。
Q13:重排模型的离线指标看什么?
A13:实操当中离线模型的指标看的是获取到的 evaluator 的 reward,还有一个指标是 better percentage。Better percentage 是同样的情况下生成的重排序列,从 reward 上来讲优于线上真实投放序列的概率。基本上认为这个数值应该至少得高于 50%。
Q14:入选重排候选内容池 50 条是如何选择的?完全按照精排分吗?还是会考虑一些其他业务需求,比如保量内容进入 50 条重排候选池。
A14:存在一些特别的 case,比如说用户关注东西实在太少了,也会给他做全网推荐的内容。当时在全网推荐遇到过一个 case,推荐返回了 200 个宝贝。靠精排模型分截取的 200 个 feed,有 197 个都是同一种类型的feed,这个事情就很尴尬了。比如说业务规则要求一页里边最多只能出一个买家秀,如果有这样的业务规则那 200 个返回的结果就大面积是废的,所以一定要在返回之前先看 CTR,然后也要做 feed 内容类型的打散和商家的打散,这些操作一定程度来说是必要的。