作者:薛更盛*,张国校*,李坦坦,吴樑,孔蓓蓓
新用户和冷用户喜好预测问题一直是推荐系统领域的一个难题,广泛存在于计算广告,App推荐,电子商务和信息流推荐场景。目前绝大多数的解决方案都是基于用户外部画像数据进行喜好预测,因此预测准确率严重受制于画像数据准确率,并且用户画像数据搜集成本高,涉及敏感的隐私问题;另外,据笔者所知,即便具有十分精准的用户画像数据,新冷用户仍然很难做到个性化推荐,点击率和相应的top-N指标仍然显著低于常规热用户。那么关于用户冷启动的场景,有没有其他更好的解决办法呢?最近,一篇腾讯QQ看点团队SIGIR2020长文Parameter-Efficient Transfer from Sequential Behaviors for User Modeling and Recommendation 提出了一种迁移学习架构PeterRec专门解决新用户和冷用户推荐。PeterRec基本思想是通过自监督学习一个通用的用户表征,然后将该用户表征应用到下游任务中,例如冷启动用户场景(PeterRec同时可以解决用户画像预测)。从论文中的实验结果来看,这种采用自监督预训练网络学习用户点击行为的方法可以高效地推测出用户的偏好等信息。
近年来,迁移学习对CV和NLP领域产生了重大的影响,但尚未被广泛应用于推荐系统领域,并且据我们调查,推荐系统领域目前相应的迁移学习科研工作都没有明确的展示出pretrain网络对于下游任务具有positive transfer效果。而在腾讯,我们具有非常丰富的业务场景,部分业务,例如腾讯视频,QQ浏览器具有数亿的DAU用户,并且很多用户具有数百上千的点击行为,这些海量的用户点击行为为其他推荐业务场景(例如腾讯新闻,QQ看点,微视,腾讯广告, 应用宝,微信看一看)新冷用户提供了丰富的可迁移的知识,在本文中,由PCG腾讯新闻画像平台团队和看点推荐团队协力合作,对PeterRec模型进行工程化改造,落地到PCG事业群下面的多个推荐业务中。选择PeterRec模型除了其较好的个性化推荐能力外,很重要一点,PeterRec可以实现一个pretrain网络服务数十/百个推荐业务场景能力。下面我们选择两个视频推荐业务(分别作为source业务端和target业务端),将从模型架构,数据处理,模型实现,后续工作这四个方面来介绍。
首先PeterRec根据预训练的自监督方式可以分为单向自回归方式(autoregressive和双向遮掩式,这一点类似于近期的NLP工作,例如GPT。根据微调阶段模型补丁嫁接插入方式又可以分为串行插入(serial)和并行插入(parallel)。这里只介绍autoregressive、serial版本的PeterRec模型。
图 1 模型结构
Pretrain阶段:
Pretrain采用单向自回归的训练方式,根据用户观看的前k个视频预测其可能会看的下一个视频。输入是用户在source业务端看过的视频id序列[x1, x2, x3,······, xn-1],然后通过embedding lookup的方式获取每一个视频的隐向量输入到预训练网络中;输出是对应的下一个视频id,即[x2, x3,······, xn-1, xn]。可以看到,PeterRec 模型不需要借助于任何图像和文本特征,仅需要用户点击视频的ID即可,视频的向量表示完全由模型训练得到,省去了特征工程的步骤, 这种pretrain方式已经被应用于CV和NLP领域,并且取得了非常认可的效果,然而并没有在推荐系统领域得到推广。
Finetune阶段:
Finetune阶段是根据用户在source业务端观看记录,预测其可能会在target业务端感兴趣的视频。输入是[x1, x2, x3,······, xn-1, xn, [CLS] ], 其中[x1, x2, x3,······, xn-1, xn]用户在source业务端看过的视频ID序列,[CLS]是一个特殊的记号,表示在这个位置输出分类结果;输出Label是target业务端的视频ID,即预测用户在target业务端可能会看的top-N个视频ID。
Pretrain阶段:
在模型Pretrain阶段,将其看成一个超大多分类问题。输入的视频ID序列经embedding_lookup操作后,提供给后面的空洞卷积网络。整个空洞卷积网络由若干个residual block(如下图(a)所示)堆叠构成。在每个block中,包含两个空洞卷积层(DC layer),每层的空洞因子以 2^n 增加。最后通过一个softmax层,预测出下一个视频。
相较于其他时序模型如RNN、Transformer等,PeterRec模型基于空洞卷积神经网络构建大规模的预训练模型,同时通过叠加空洞卷积层达到可视域指数级的增加,这种网络结构使得它在对超长的用户点击序列进行建模时更加高效。而相比之下,RNN模型在对超长序列建模时,通常会遇到梯度消失和梯度爆炸的问题;而像Transformer这类self-attention based的模型,时间复杂度和显存需求会随着序列长度以二次方的级别增加。
图 2 residual block和模型补丁
Finetune阶段:
为了实现对预训练网络参数的最大化共享,Finetune阶段仅对预训练模型做了两处的改动:
第一、在residual block中以串行的方式插入模型补丁(如上图(b)所示),每个模型补丁(如上图(f)所示)由一个瓶颈结构的残差块构成,且参数量仅有原始空洞卷积的不到十分之一。
第二、直接移除预训练 softmax 层,然后添加新任务的分类层。
微调通常要重新训练整个网络,并更新模型所有的参数,因此从参数量的角度来看,微调是非常低效的。相比这种微调所有参数的方式,PeterRec模型在finetune阶段仅对模型补丁和新任务的softmax层中的参数进行更新,参数量大大减小的同时却可以达到与微调所有参数相当甚至更好的效果。而且,由于仅有少数参数参与更新,PeterRec模型还具有很好的抗过拟合能力。
Pretrain阶段:
Pretrain时采用softmax的多分类交叉熵损失函数。实际操作中,source业务端中的视频经过各种过滤ID映射后还有数百万级别有效视频。如果采用full softmax,训练效率会很低,所以这里采用了tf.nn.sampled_softmax_loss,实际只采样了20%的item作为负样本用做训练,当然其他efficent采样和loss设置也同样适用,例如NCE loss或者下文讲到的LambdaFM 方式。
Finetune阶段:
对于排序场景,pairwise类方法要比pointwise类方法(直接看做分类或者回归)更合适,所以finetune采用了pairwise ranking loss (BPR)。pairwise loss里构造样本时我们同时考虑两个item比如xi和xj ,这两个item是有顺序的,比如用户在排序列表里点击了xi,而未点击xj,我们可以看做xi要优于xj。
因此,我们需要为每一个真实物品label(y)采样一个负样本y-,通过计算用户的隐向量与y和y-的隐向量的内积作为两个item的打分oy和oy-,然后算出最终的BPR loss如下:
具体采样时候,我们采用LambdaFM(CIKM2016)方式,效果显著好于随机采样和仅仅使用曝光未点击的作为负样本方式。
这里介绍我们在优化模型过程中几个有效的数据处理方法:
过滤:
由于涉及到不同业务数据,从source业务端得到用户的原始观看序列后,需要过滤一些过热或过冷的视频item(过热的视频没有区分度,无法看出用户特定的偏好;过冷的视频由于出现次数少,模型学得的隐向量很难准确反映视频的信息,并且没有充分的训练,很容易成为噪声而影响最终效果)。过滤后,source业务端的视频数量在200w+的级别。
编码:
在pretrain阶段,我们采用了sampled_softmax_loss来代替full softmax loss,tensorflow的sampled_softmax_loss函数在进行负采样的时候,是通过log_uniform_candidate_sampler进行的,使用这个sampler时的效果会是:item编号越小,它被采样为负样本的概率越大。针对这种情况,我们在对视频item进行编号时,是按照item在播放序列中的出现次数降序排列,然后从0开始编号。(原因可见下面`LambdaFM负采样`)在finetune阶段,采用了BPR loss,没有用到log_uniform_candidate_sampler,因此可以不用按item频率进行编号。
Pretrain阶段:
首先,我们先从source业务端的流水数据中拿到用户a的播放序列。经过过滤(根据视频的播放时长和完播率,过滤掉自动播放的视频)和去重(对原始播放序列的相邻item去重)后, 取用户a最新的50个播放视频作为一个pretrain的训练样本[x1, x2, x3,······, x50](若用户的播放序列长度不足50,则在前面填充[PAD])。用户播放序列行为可以根据计算资源设置,如果具有较充足的计算资源,可以设置行为序列为更大,例如200甚至1000。
Finetune阶段:
以相同方式从target业务端的流水数据中拿到用户a的播放行为[y1 y2, y3,······, ym]。这时,根据用户a在source业务端和target业务端的播放序列,我们可以为用户a构造m条finetune的训练样本:[x1, x2, x3,······, x50, [CLS], y1], [x1, x2, x3,······, x50, [CLS], y2], ...... , [x1, x2, x3,······, x50, [CLS], ym]。(需要注意的是,只有source业务端和target业务端的交集用户才能用于构造finetune的训练样本,预测时候则不需要。)
经过上述的处理,对于不同观看历史的用户,PeterRec模型预测出来的top-N结果已经具有一定的相关性。实际的case分析显示,这些强相关的视频还是容易出现得分较低于高频item情况,排在top100之外,但是在头部都出现了item vocab中最热的那些视频,由此可见高频item对模型的影响还是很大。为了缓解top-N推荐结果中的头部效应问题,减少高频item对模型的影响,我们尝试了不同的均衡正负样本的策略,其中下列两种较为有效:
高频降采样:
Word2vec的实现中,会指定一个概率P(wi)对高频词进行打压,同时保留所有的低频词。实际源码中,高频词在每个样本中被保留的概率实现如下:
转换成公式就是:
其中,参数sample用于控制降采样的程度,sample值越小,降采样强度越大,实际使用中需要根据item的频率分布来确定,一般取0.001 ~ 0.00001。
于是,我们在构造finetune训练样本的时候,先根据概率分布对用户在target业务端的播放序列[y1 y2, y3,······, ym]进行一次降采样,按照一定比例丢弃一些高频的视频item。然后再与其在source业务端的播放序列做拼接,得到finetune的训练样本。
LambdaFM负采样:
关于负采样,常用的做法有两种(1)采用曝光未点击作为负样本;(2)从总的候选池子中随机取样。我们发现(1)方法效果较差,因此采用从候选item池子随机选择itemID,但这种方式仍然存在一定的缺陷,它采样出来的样本多数集中在长尾处,LambdaFM论文中是这么描述的:`In fact, it has been recognized that item popularity distribution in most real-world recommendation datasets has a heavy tail, following an approximate power-law or exponential distribution. Accordingly, most non-positive items drawn by uniform sampling are unpopular due to the long tail distribution, and thus contribute less to the desired loss function. Based on the analysis, it is reasonable to present a popularity-aware sampler to replace the uniform one before performing each SGD.`
这里popularity-aware sampler的意思是让更受欢迎的item有更大的几率被采样为负样本,这个其实是符合直觉的,因为相比那些不受欢迎且用户没有观看的视频,那些受欢迎的但是用户没有观看的视频更具信息量,更能帮助我们发现用户的偏好。我们发现LambdaFM论文提供了3中负采样方法,本文这里采用了第一种负采样方式,在后续工作我们也会尝试动态负采样,根据论文动态负采样通常推荐top-N效果更好。
finetune训练过程中,我们采用了LambdaFM中的Static & Context-independent Sampler进行负采样,即视频j被采样为负样本的概率pj与它的热度排名rank(j)呈正相关:
,
其中,rank(j)表示视频j在所有视频item集合 中的热度排名, 表示阈值,通常取0.3-0.5。
前面的处理过程已经可以很精准的实现target业务端视频推荐的个性化或者相关性,我们随机挑选了两个实例见表1。同时,还能有效处理用户在source业务端和target业务端的偏好不一致的问题:在具体的case分析中,我们发现部分用户在source业务端看的大多是卡通类的视频,而在target业务端很少看这类视频,此时,PeterRec模型推出的视频是更接近于他们在target业务端看过的真实视频的,而非卡通类的视频。我们推测主要原因可能是该部分用户在source业务端大多是学龄儿童甚至是学龄前期,主要是使用其父母账号观看source业务端,而在target业务端账号大多是其父母在使用,因此推出的视频偏向于年轻父母偏好。
source业务端的点击序列 |
PeterRec推荐的top5标题 |
德云斗笑社 德云斗笑社·秦霄贤 德云斗笑社·烧饼 德云斗笑社 |
岳云鹏认真帮师弟,结果金手指被抢,还被秦霄贤支配着跳下水! 周九良被安排相亲,竟拿秦霄贤的照片去送人,秦霄贤反应好精彩 德云斗笑社,周九良被小岳岳坑,别人不花钱他花4000! 《德云斗笑社》秦霄贤收到七夕娃娃 周九良:谁说我可爱的!现在还说么? |
斗罗大陆 2020-07-12《NBA故事汇》第98期, |
斗罗大陆:唐三得到杀气领域,背后长出了像杀戮之王一样的翅膀, 斗罗118集下,月华妹,我唐昊回来了, 湖人vs开拓者十佳球,安东尼华尔兹舞步后仰 詹姆斯追身大帽西蒙斯, 保罗对库里有多恨?看完这几个球全明白,万幸俩人没打起来!, 当科比去世时,众球星的反应让人心碎!, |
表1: target业务端的新冷用户推荐示例
后续为了增加推荐topN结果中的多样性,我们在Predict的过程中做了一些改变:
图 3 Predict处理
如上图所示,我们在为用户生成推荐列表时,不再是直接将用户在source业务端的播放序列输入到模型中,我们将其拆分成了两类子序列:
第一类是播放序列里的有效播放序列的子串。取子串的原因是,我们发现,用户观看的相邻视频之间兴趣点比较一致,也就是用户会在某个时刻连续观看一些同类的视频。这使得子串里的视频大多属于同一类,用户的兴趣点明确,更有利于模型找到用户的偏好。
第二类是从用户的有效播序列中随机采样一些item来构造子序列,原因是用户的播放序列中往往包含了多个种类的视频,随机构造子序列引入了随机性,可以更好地丰富topN结果中包含的视频种类。
最后将用户对应的所有子序列的top-N结果,经过concat、shuffle和去重,得到用户最终的top-N推荐列表。
模型代码是由参考原始论文源码,采用tensorflow estimator + tf.data + spark-fuel框架实现,完整代码可参考Git
Google官方推荐在对于中大数据集来说,先将数据集转化为TFRecord数据,这样可加快数据读取和预处理中的速度。因此,我们先使用spark对训练数据进行处理,然后转成TFRecord的格式传到hdfs上。TFRecord做好了,要怎么读取呢?可以通过tf.data来生成一个迭代器,每次调用都返回一个大小为batch_size的batch,这样可以很方便地支持多线程读取数据。关于如何优化input pipeline的性能,可参考Better performance with the tf.data API、How to improve data input pipeline performance?
需要注意的是,Pretrain阶段和Finetune阶段的click_id_list的长度是不一样的。
图 4 读入TFRecord
PeterRec模型的网络结构是比较简单高效的,且空洞卷积的使用也使得模型能够并行训练和降低显存需求,这里直接复用了源码中的模型结构和模型补丁结构。另外,在采用PS策略进行分布式训练时,为了均衡ps节点的负载和加速训练,最好是对模型参数做分区,以便模型参数被均匀分配到各个ps上。
图 5 Pretrain网络结构
模型训练的过程采用tf. Estimator实现。tf.Estimator的特点是:既能在model_fn中灵活的搭建网络结构,也不至于像原生tensorflow那样复杂繁琐。相比于原生tensorflow更便捷、相比与keras更灵活, 属于二者的中间态。实现一个tf.Estimator主要分三个部分:input_fn、model_fn、main三个函数。其中input_fn负责处理输入数据、model_fn负责构建网络结构、main来决定要进行什么样的任务(train、eval、predict等等)。input_fn上面`输入处理`一节中已经介绍了,这里只介绍model_fn和main函数。
model_fn函数:模型的网络结构、loss已在上一节中介绍,这里只给出了定义train_op的部分。这里采用了同步更新机制,每个worker节点直接访问外部存储系统(hdfs)获得一个batch,然后计算loss和gradient,汇总到PS节点,当所有worker节点都完成一个batch时,才更新一次参数;在实际实验中,我们通过调节replicas_to_aggregate,我们通过忽略几个速度慢的worker梯度来加速训练 。
图 6 model_fn函数
main函数:有了输入数据input_fn和模型model_fn,main函数就负责如何使用模型和数据。这里使用train_and_evaluate来一边训练一边输出验证集效果。另外,hook可以看作是在训练验证基础上实现其他复杂功能的“插件”,比如本例中的EvalHooks(用于计算NDCG等评估指标)。
图 7 main函数
离线打分时,采用spark-fuel的分布式预测的方式,如下图所示,需要注意的是,预测过程其实就是一个Spark作业,没有TensorFlow Cluster,每个Spark Task中通过TensorFlow API加载模型,对RDD Partition中的每条数据做推理。
图 8 分布式预测
在模型的预测阶段,我们需要对每一个模型输出的用户向量(即[CLS]对应的最后一个hidden layer的输出),快速求出最相关的TopK个视频,如下图所示。当item数量较大时,下图中直接计算内积的速度会比较慢,可以采用faiss的IndexHNSWFlat来完成TopK的查询。参考长视频推荐:基于欧氏转换的top-k内积解决方案
图 9 预测阶段求topK
后续我们将推进PeterRec在其他业务场景上的尝试(包括画像预测), 充分利用PeterRec的参数高效特性优势, 同时腾讯新闻画像平台团队和看点推荐团队近期将发布PeterRec完整的工程化代码和配套迁移学习数据集用于学界和业界研究使用。
另外,近期腾讯看点推荐团队和腾讯新闻画像平台团队联合推出用户表征的lifelong learning(文献4)模型Conure,是首个能实现不同推荐任务,不同业务场景间的可持续学习算法模型, 离线实验结果显示该方法可以实现一个模型支持数十个推荐业务,尤其擅长解决冷启动问题和画像预测问题,如果各个下游任务之间存在一定的关联性,那么Conure可以比PeterRec取得更好的预测准确率。
参考文献:
【1】A Simple Convolutional Generative Network for Next Item Recommendation. Yuan et al, 2019, WSDM.
【2】Parameter-Efficient Transfer from Sequential Behaviors for User Modeling and Recommendation. Yuan et al, 2020, SIGIR.
【3】LambdaFM: Learning Optimal Ranking with Factorization Machines Using Lambda Surrogates. Yuan et al, 2016, CIKM.
【4】One Person, One Model, One World: Learning Continual User Representation without Forgetting. Yuan et al, 2020, Arxiv: https://arxiv.org/pdf/2009.13724.pdf.
专知便捷查看
便捷下载,请关注专知公众号(点击上方蓝色专知关注)
后台回复“PRVR” 就可以获取《【腾讯】PeterRec在PCG短视频冷启推荐场景应用》专知下载链接