PPT下载:点击“阅读原文”,跳转下载页
29:5
36:(视频回放)
导读
嘉宾介绍:网易云音乐资深算法工程师 - 孔昭阳
2018年加入网易云音乐,主要负责私人FM推荐、首页个性化模块排序等工作,曾就职于蚂蚁金服,2015年硕士毕业于哈尔滨工业大学。
目录
关于云音乐
推荐架构演进
负反馈思考与探索
01
关于云音乐
云音乐除了大家印象中的日推、私人FM、歌单等单曲推荐场景以外,现在也包含很多泛娱乐化的资源推荐,比如播客长音频推荐,Mlog广场短视频推荐、直播推荐等等。
这里主要分析下音乐推荐和电商推荐的区别。
首先从相同点上面来讲,现在是一个大数据的时代,商品资源或音乐资源数量级庞大,如果用户自己按照意愿检索,体验很差效率很低,所以两者都是为了解决信息超载的问题,来提升用户对资源的匹配效率。第二个是从应用技术方面,二者会使用一些大数据的平台、算法等。
不同点主要包含以下三个:第一是音乐资源对用户来说是可重复消费的。我们听了一首歌曲,把它收藏在自己的红心歌单里边,后续我还可以去重复去播放这首歌曲,但电商里虽然商品也可以重复购买,但同个资源的消费频次还是有很大差别;第二个不同点是消费音乐资源的成本更高。我们听一首歌曲可能需要几分钟的时间,但在移动端的商品推荐流场景,向上划动屏幕就可以浏览十几个商品,所以消费音乐资源的成本会更高一点;第三个不同点是在音乐场景存在更加丰富和可信的用户反馈。比如用户可以对音乐进行收藏、跳过或是垃圾桶等行为,且这些反馈的置信度比较高,究其本质原因还是消费歌曲的成本比较高。
云音乐中我们有两大口碑比较好的单曲推荐场景,一个是每日推荐,一个是私人FM。这两个场景从业务角度讲有什么区别呢?第一个区别是每日推荐是列表式的推荐,每天打开后推荐的歌曲内容是不会变的。而私人FM是一个流式单曲播放场景,只要用户停留在私人FM,那么它就一直顺序向下播放,并且在私人FM场景,用户播放歌曲存在一种探索心理,因为用户永远不知道下一首会推荐什么歌曲。第二个区别是用户操作路径,进入每日推荐需用户更长的操作行为,从点击日推-列表曝光-点击歌曲-播放歌曲,而私人FM的操作路径会相对简单一些,只要点击私人FM入口就开始播放了。
02
推荐架构演进
下面为大家介绍私人FM推荐系统架构。
首先我们来看一下整体的系统链路(黄色部分),最左边是用户在客户端发起请求,这个时候客户端会传一些参数到服务端,这个参数包括用户id、客户端版本、客户端类型等;然后服务端会把这些参数传到推荐算法引擎,算法端的工作包括特征计算、召回、排序、二次排序及多样性,最后会把推荐结果反向传回到客户端。
下面的红色部分是用户实时行为的数据链路,算法端依赖于这些实时数据捕捉用户的实时短期偏好,提升用户推荐体验。实时数据主要包括用户的点击行为、播放行为、搜索行为、红心收藏等,然后通过kafka将数据存储到线上可读取的中间件存储,最终在推荐算法的各个阶段中被使用进来。
私人FM的推荐算法体系主要包含4个阶段。
首先是召回阶段,我们根据用户在云音乐平台的离线长期行为和实时短期行为,从千万级的曲库中召回用户感兴趣的歌曲子集。这个阶段的目标是尽可能全的把用户长短期偏好的歌曲子集选择出来。
然后是粗排阶段,粗排是在召回和精排阶段之间。粗排在推荐场景里边不是一个必要的阶段,是否需要该阶段要通过不同场景具体分析。对于音乐推荐场景数据量会比较大,如果从召回直接到排序阶段,中间会有一些推荐体验指标和链路RT性能上的损失,所以在召回和排序阶段,我们增加了一层粗排阶段。
接下来是精排阶段,我们将精排阶段的优化看作CTR点击率优化的过程,该阶段会根据用户的长短期偏好及复杂模型的迭代优化,对粗排出来的结果进行排序。
最后我们会根据用户偏好的风格、语种以及歌曲年代等等去做一些业务打散和负反馈的策略排序。
下边为大家分享我们在各个阶段的一些工作和经验。
首先为大家介绍召回阶段的优化内容。
召回阶段的主要目标是尽量把用户感兴趣的候选集(单曲)选择出来,重点是能够覆盖用户长短期的兴趣偏好。私人FM包括基础的i2i召回,在这个基础上位了提升用户兴趣覆盖度和召回准确性,进行了下面三个优化工作:
第一个工作是图召回。图网络可以刻画不同介质之间的关联性,而用户、歌曲、专辑、艺人介质在歌曲推荐场景天然存在一定的关联性,在此基础上可以很好的扩展召回阶段多样性;
第二个工作是即时兴趣召回。私人FM作为一个流式播放场景,存在很多用户实时的正向反馈和负向反馈,为了更好的利用这些实时行为这里我们做了一些实时兴趣召回,捕捉用户的一些即时兴趣;
第三个我们是尝试了一些深度长短期兴趣向量召回;
图召回的第一种用法是根据拓扑结构直接进行召回。音乐本身存在一些属性,比如说歌曲有艺人、有所属的专辑、也有风格语种等等,它自身可以构成一张异构的实体图。如右边的示例,比较简单的一种使用方法是从图当中的某个节点出发,通过多跳的关联关系直接做一些召回。举个例子,歌曲A是某个动漫的主题曲,我们通过动漫和歌曲的这种实体关系,可以获取该动漫的其他关联歌曲,这样就扩大了一层召回。我们还可以继续扩展,通过该动漫到歌曲,歌曲到艺人,艺人到其它动漫的这种实体关系,获取A歌曲的对应的艺人X在其他动漫的演唱主题曲。
图召回的第二种用法是把图召回中的歌曲节点进行向量化,但这个图和前面的图不太一样,前面的图是一个多介质的异构图,而向量化的工作我们是重构了一个图,这个图是同构图,介质只包括单曲。
那这个图我们是怎么构建的?首先我们将用户红心且完整播放歌曲的id构成一个序列,用红心且完整播放序列是因为这种操作可以看成是用户对单曲比较强的正向行为;然后根据播放序列去构建出来一个pair对,pair对指的是歌曲A和歌曲B在整个数据集里边成对出现的次数;之后对这种共现次数较少的pair对进行截断,假如我们设的预值是10,那共现pair次数小于10这个pair就被过滤掉,通过上述方法就构建出歌曲和歌曲之间的同构无向图;最后根据pair出现的次数计算边权重,此处会遇到有一些节点和节点共现次数较多的情况,也就是图中点的度数会比较高,因此我们会对度数较高的节点进行采样优化。右图的例子就是上述构图的过程。第一个框中是用户的播放序列,不同颜色的圆圈代表不同的歌曲。第二个框中是构建出一个pair对,比如红色和棕色的是一次,棕色和紫色的变成两次,根据上面序列,就会有每个歌曲成对出现的次数,依据次数计算边的权重。
图构建好之后,我们使用random walk + word2vec算法进行图挖掘。具体的算法在此不做赘述,最终会产出歌曲对应的embedding向量,我们根据embedding向量去计算歌曲的相似度,这样就得到了一个歌曲到歌曲的i2i数据,然后用这个数据来做相似歌曲召回。
此处有个实现的细节,如果根据歌曲embedding向量去算歌曲之间相似度的时候,在离线通过分布式计算平台去执行,会因为数据量比较大而执行很慢或执行不出结果。我们的优化方法是先根据歌曲的向量进行聚类,然后在每一个簇中去计算歌曲之间的相似度,计算效率有了比较大的提升。
召回的第二个优化是实时兴趣召回。在实时兴趣召回前,i2i召回主要依赖离线T+1的偏好数据,比如根据用户的历史红心、历史收藏和历史完播这些行为。后来我们觉得FM应该做的更实时一些,需要能够捕捉到用户实时的兴趣偏好,于是依赖于实时计算平台提供的实时数据能力,根据用户实时行为准确获取用户实时召回源,结合离线i2i相似数据和上述的图挖掘相似数据,进行相似歌曲召回。用户实时行为主要包括用户的红心、收藏、实搜索、完整播放等。
第三个是深度长短期兴趣向量召回。用户对歌曲的偏好类似于电商,也会存在长期和短期,而且二者之间可能会存在一定的差异。比如某个用户长期偏好欧美歌曲,但因为最近观看了某个综艺节目,于是对某个艺人的中文歌曲比较感兴趣,或者对某种曲风特别感兴趣,这种长期和短期偏好融合的问题也是在召回阶段需要去考虑优化的一定点。
我们参考了SDM这篇文章,并且在歌曲推荐场景做了些调整与优化。在私人FM场景中,输入包括用户序列与用户画像两个部分,用户序列包括对歌曲的红心、完播等正向行为,并且我们融合了用户离线序列和当天实时播放序列,这样能够捕捉到用户更短期更实时的一些兴趣;用户画像中包括用户的性别、年龄、风格、语种偏好等。然后通过门结构对用户的长期兴趣和短期兴趣进行融合,而我们最终上线的版本将用户的长期兴趣和短期兴趣作为两个不同的向量分别去召回,这样可以更加清晰的区分这种长短期兴趣存在很大差异的情况。
那么比如刚才我们提到的SDM怎么去做离线训练和线上推理呢?可以看这个图,在离线的时候我们是通过用户的画像特征,包括统计类特征,用户的序列特征,还有歌曲的属性特征和歌曲统计类特征,然后将清洗好的样本数据放到SDM模型中进行训练,会得到歌曲的向量并且把歌曲向量存储在线上的引擎中,就是离线的训练过程;同时这个模型我们会把它抽象出来,放在线上推理平台去做实时的预测得到用户的长短期兴趣向量,然后用该向量和存储在引擎中的歌曲向量做一个相似的计算检索,得到Top N结果,也就是我们召回的结果。
以上就是我们在召回阶段做的一些工作。
第二部分介绍一下我们在粗排方面做的工作。粗排阶段是在召回和精排的一个中间阶段,它不是一个必要的阶段,只是为了减少精排的压力并且能够承受更多量的召回。粗排阶段相比于召回来说它更强调准确性,相对于精排来说它更强调模型简单、实时性更好。所以在粗排阶段我们需要平衡准确性和时效性。
粗排阶段从建模角度来说有两种思考维度,主要是在样本选择方面不太一致。第一种思考维度是把粗排当做召回的一个补充阶段,选样本的方式可以去参考召回阶段对负样本进行全局负采样,然后按照这个思路去往下做;另一种思路是把粗排当成精排的一个前置,那么粗排的目标就要保证和精排的目标是一致的。我们在实际用的时候是采用后边一种思考方式。
粗排模型的结构,我们采用的是双塔结构,双塔模型的优点是在线上实际预测的时候只需预测用户侧就可以了,Item这一侧可以根据在离线训练后把Item对应向量在离线都预测出来,线上去做一个相似度的计算。但是双塔结构的缺点是,在最后一步点击+sigmoid之前,塔的两边是没有任何交叉的,虽然降低了准确性,但线上做预测就简单很多,不需要计算交叉特征,因此节省推理计算时间;
最后阶段的距离计算我们采用的是点击+sigmoid的方式,此处的变种有很多,大家可以去尝试不同的方式。包括在这种NN层里边,使用的激活函数也可以有很多选择,比如说选relu、sigmoid、tanh等,对模型的最终准确度的提升还是有一定效果的。我们这个场景里边用的是tanh效果会比较好一点。
下面聊一下粗排样本的选择,我们尝试过两种方式,第一种使用的方式是使用用户真实反馈的标签作为正负样本,它的样本选择和精排是一模一样的。我们的模型是一个多目标模型,一个是是否红心,另一个是是否完整播放,线上效果相比没有粗排的效果是有很大提升的。收益主要来源于两个方面,第一个是把召回的量扩大了,扩大以后会有更多用户感兴趣的候选集在里边。第二个是我们原来的召回集合里面,是通过一些规则去选出来一些集合,然后直接进入到精排,而规则的选择不是最优解,而通过模型的方式去选择会更加合理;
第二种使用方式是我们直接去学习精排样本的排序结果,类似于蒸馏的过程,具体方式可以看右边这个图,从上到下是精排排序的结果,我们会取前面的Top3做一个正样本,中间的5个和尾部的5个作为负样本,然后让粗排模型直接去学习这个样本对应的目标。我们实际线上做的收益相比使用一的方式效果更好一点,后续我们也会在蒸馏方向上做一些探索。
第三个部分介绍一下精排的优化工作。在深度模型上线前,线上还是以传统的机器学习模型为主,包括LR、GBDT模型等等。随着深度模型在各个领域取得一定的成功后,我们也开始在音乐推荐场景进行尝试。我们参考电商领域的CTR模型优化方向,但是会在音乐推荐场景里做一些改进优化。
私人FM精排模型主要向两个方向进行优化,第一个方向是用户听歌时的长期兴趣与短期兴趣的识别与融合。比如说用户既喜欢古风类别的,也喜欢摇滚类、电子类别,又或者是用户既听中文歌曲又听英文歌曲,那就会有多兴趣的问题。所以第一个问题是怎么去解决中长期兴趣和多兴趣的表达,怎么在精排里面进行刻画?解决的方法是去参考DIN模型、BST模型或者DSIN模型进行深度行为序列建模,根据用户不同的时间窗的行为序列去刻画中长期或者长短期的兴趣偏好。
第二个目标是用户的实时兴趣捕捉。这里边有两个问题,第一个是我们怎么去捕捉用户的实时兴趣以及捕捉出来以后怎么在模型里边进行使用;第二个问题是一个工程方面的问题,加了实时特征以后,我们怎么保证离线训练和线上推理的一致性,也就是特征一致性,我们云音乐是自己研发了一套snapshot系统,后面会做介绍。
首先来回顾一下FM场景里边精排模型迭代的过程,第一个阶段是会用一些传统的机器学习模型,这些模型特点是简单,但是需要手动对Item和User的特征进行交叉,模型整体的表达能力是有限的;第二个阶段是结构比较单一的深度模型,相比于传统的机器学习模型,这一阶段通过模型自动化的学习Item和User之间的交叉关联性,可以把一些高维的embedding特征用在这里边;第三个阶段我们在深度模型中加入了序列结构,沿着Din模型、Bst模型或者Dsin模型方向进行迭代优化,且每一个迭代的过程在线上的指标都有一定的提升。
DIN模型是我们上线的第一个深度序列模型。它的模型输入主要包括用户的画像特征、待排序的目标Item的特征、上下文特征以及序列特征。
用户的画像特征包括风格、语种、艺人、年代偏好的统计类特征,Item侧特征包括歌曲自身属性特征及统计类特征,此外我们加入了Item预训练Embedding特征以及基于此计算出的用户侧Embedding特征。Embedding特征根据用户对歌曲的红心、完播行为序列使用word2vec算法计算出来的,然后通过用户最近一段时间红心或完播歌曲集合,使用avg_pooling汇总出来。因为间隔一段时间后会存在一些新的item,因此我们会对的Item侧的Embedding定期更新,而用户对应的User Embedding我们会每天更新一次,因为每天用户对歌曲都会有完播或者红心行为。
上下文的特征主要是一些交叉特征,这部分特征也是在第一阶段基于传统机器模型建模时沉淀下来的,虽然深度模型可以自动进行调整较差,但基于业务的手动交叉特征还是必不可少的。
除了上述几个特征部分外,还加了用户的行为序列特征。在我们的场景里边主要包括三个序列特征:用户的红心序列、用户对歌曲的完整播放序列以及用户对歌曲的跳过序列。在模型里面,红心序列可能表达的是用户更强的正向偏好,完播序列可能会稍微弱一点,但因为在Din模型里边,它没有能力去刻画红心和完播到底有什么区别,那在后面的模型我们会做一些优化。
针对序列我们主要做的优化点有两点,一个是我们的序列包括实时和离线两个部分,用户在FM里面听了上一首歌曲,它会实时的加到下一首的预测序列里边,这是第一个优化点。第二个优化点是我们加入了跳过序列,通过跳过序列能够去刻画用户最近不感兴趣的一些行为。
Din模型相对于结构单一的深度模型来说,它的表达能力得到了很大提升,除加入了序列特征外,还使用了Attention机制的注意力机制。Attention机制在音乐场景中,我们可以理解为用户的历史行为它可能会是多样性的,就像前面提到的,用户对风格、语种可能会有多样,而历史播放序列中对应的风格、语种也是会有很多种,当前待预测的可能是一个中文或者欧美的歌曲,这时通过Attention的机制可以计算出当前在序列里边哪些会更相似,或者计算出来这种向量权重会更高一点的,模型会自己去学习。
下面讲下Din模型在训练的时候怎么去保证线上线下的一致性。有两种方式,第一种方式是通过日志去反推,每条日志上面会打一个时间戳,根据播放日志的顺序行为,去反推这首歌曲之前的序列是什么。第二个方式是把线上当时去做预测的对应的特征都都打到日志里边,然后通过解析和实时数据传输沉淀在HDFS上。
第一种方式通过日志进行反推有几个问题在,第一个问题是日志的时间可能会存在错误,也就是说因为打点错误、数据流延迟、日志采集错误等问题,日志时间存在错误;其次是线上和离线要分别去实现一套计算逻辑,这个口径很难保持一致。比如前面提到的实时统计特征,这个口径可能就不太一样;最后有时离线根本没办法去实现线上的这种推理逻辑。
第二种方式就是直接将线上的计算结果通过日志把它保存下来。我们现在已经是采用这种方式了,是通过snapshot系统来实现的。整个的数据链路就是右侧这个图,上面框图是线上提供的服务,就是算法业务系统请求精排系统进行排序,精排系统返回结果给到算法业务系统。我们假设待排序的Item是100个,但是我只需要给服务端和客户端或者给用户返回几首歌曲就够了,比如每次返回top3到服务端;同时会有一条旁路服务,可以把Top3的Item输入到精排的旁路系统,然后精排的旁路系统会根据精排系统的计算逻辑重新进行特征计算,通过将特征进行日志落盘并保存到本地服务器,通过日传输放到HDFS,我们再通过T+1的这种计算方式进行ETL数据清洗关联出来样本进行训练。
这里面比较重要的一点是线上服务的精排系统和旁路服务的精排系统的逻辑是保持一致的。当然这个旁路的精排系统所计算的特征可能会比线上的精排系统要多,出现这种情况的原因是多的这部分特征只用来做样本沉淀,而不参与推理计算。所以通过这种方式我们就保证了线上线下的一致性。
在实践的时候,我们起初采用的第一种方式,通过日志去反推,后边有了snapshot系统以后我们是采用了后一种方式。实际测试下来的效果是通过保证这种数据的一致性,我们也是在线上取得了比较大的收益,包括用户的红心率、完播率、对播放时长等指标都有比较大的提升。
Din模型之后我们迭代到了BST模型,它使用了一个Transformer的结构,相比于DIN模型的Attention的结构,表达能力更强一些。在我们这个场景里边,使用了一个多头的结构,可以表达用户的一些多兴趣向量在里边,也提升了网络的表达能力。
后面我们在BST的基础上探索DSIN模型。因为我们发现用户在每一个场景里边,他的偏好会不一样,比如在每日推荐中因为是列表展示的,所以推荐结果更偏向用户历史偏好,是用户比较熟悉的歌曲,这样点击率、播放时长会比较高;而在私人FM场景,因为用户不知道下一首是什么,因此存在一些探索性的心理在里边,这个时候给他尝试一些历史没有听过的风格或者语种,会有不错的效果。所以用户在不同场景里边,所表现出来的偏好是不一样的,所以我们想通过模型去刻画这种不同,提升模型的表达能力。
这里我们是想把用户的播放的序列进行Session分割,Session分割的逻辑主要有两个,一个是根据不同场景的播放行为去做拆分,第二个是根据用户的播放时长,假如上一首歌曲的播放时长和下一首歌曲的播放时长超过了一定时间,就被分割成两个不同的Session。然后我们在Session内去做Self-attention或者双层的LSTM,然后去结合用户的画像特征、歌曲的画像特征、交叉特征以及实时特征,concat之后通过NN层,最终进行多目标的训练。
迭代到DSIN模型相比于BST模型得到了3到4个点的收益,这个收益主要体现在两方面:一个是我们用了更多用户历史播放的数据作为特征。比如原来的序列特征只提取了最近的20首的播放行为,通过Session以后,我们可能会拉长到两百首或者一千首的播放行为,可以对用户的历史播放行为和用户的画像使用的数据更多了。第二点是这种数据拉长了以后,如果不进行Session的切分,或者不进行模型结构的优化,直接放入不一定会取得很好的效果。因为本身模型的表达能力是有限制的,所以我们通过切分Session的方式,在Session内部做一些优化,然后在Session外部做一些双向的LSTM等模型结构的优化。
03
负反馈思考与探索
上面主要介绍了召回、粗排和精排的一些优化工作。最后介绍一下我们在负反馈数据使用方向上的工作。首先介绍下私人FM场景里负反馈都有哪些,右图是私人FM的播放页面,用户有几个地方可进行操作,点击右上角三个点之后,下边会弹出来一个列表,里边会有拉黑艺人的操作,也就是用户对艺人不喜欢的行为;左下角红心带了一个斜杠,它是私人FM的垃圾桶,可以让用户快速的进行歌曲拉黑来表达对歌曲的不喜欢,同样此处也有一个拉黑艺人的入口;右侧是一个跳过按钮,同样表达了用户的不喜欢行为,但是没有上述的两种强,也许用户只是觉得下一首歌曲会更符合自己的口味。当前有很多前沿的论文在探索曝光未点击的数据如何更加合理的利用起来,正因为我们收集负反馈的成本比较低,数据相对稠密,准确性也有一定的保障,所以我们才在将负反馈内容作为一个优化的方向。那怎么去刻画用户不感兴趣的偏好,并且如何在模型里面进行刻画呢?
我们在模型中使用的方式主要有两种:第一种方式是增加负向统计类特征,比如去统计最近一段时间用户垃圾桶的歌曲的风格语种这种统计类特征,或者是跳过的风格语种统计类的特征。第二种是在深度序列模型里边加入一路用户的跳过序列来表达用户不感兴趣,然后和目标Item去做Attention或者Transformers等计算,让模型自动学出来一种反向的不喜欢偏好。
那在序列里边单独去加一路用户跳过的序列真的能表达用户不感兴趣的这种偏好吗?这种使用方式是最好的吗?
我们可以以右边的这个图为例。首先介绍下我们在模型中使用的序列特征,我们在DSIN模型里边的行为序列包括正向的红心序列,正向的完整播放序列和负向的跳过序列,因为垃圾桶序列相对比较稀疏,所以我们对垃圾桶序列和跳过序列进行了合并。然后每个序列分别和目标Item去做Attention或者Transformer。
那类比右边黄色的图,我们可以把右边黄色的三角形当做候选集目标Item,红色的当成负向序列,绿色当成正向序列。我们可以思考一下,从距离度量角度来讲,我们希望绿色的正向序列和黄色的目标Item距离越近越好,红色的负向序列和黄色的目标Item距离越远越好,这也是我们做Attention或者Transformer所预期的结果。如果假设这两个距离是个定值的情况下,这个距离是可以随着以黄色目标Item为圆心,距离为半径的圆周上进行移动的。我们固定绿色点的位置不动,而移动红心点的位置,那么图中左上角的红色点位置要优于又上角红色点的位置。这是为什么呢?因为DSIN建模过程中忽略了红色点与绿色点的相对位置,也就是左边红色的点距离绿色的点更远。
针对这个点我们做了一个Loss优化。Loss1是我们在模型中常用目标Label和预测Score对应的交叉熵,在此基础上我们新增一个三角函数对应的Loss的一个优化,把刚才提到的这几条边对应的距离计算出来。我们简单看一下第二行的Loss_tri公式,被减数第一部分可以理解为正向序列和Target之间的距离,这个值是越小越好。中间的减数部分可以理解成正向的序列和跳过序列(负向序列),这个距离是越大越好。第三部分是Target和负向距离,所以整个它的优化点是它越小越好。然后最终我们把这种交叉熵的Loss函数,和三角函数的辅助Loss_tri相加变成最终的Loss。这个是我们加入了用户负反馈序列以后,在Loss函数上进行的一些优化,上线后播放时长指标是有1%-2%的收益。
PPT下载:点击“阅读原文”即可下载
-End-
推荐阅读
【加入社区】
AICUG技术交流群开始招募啦,欢迎对AI感兴趣的同学,请加管理员微信834436689,申请信息提交:姓名-公司-职位-AI技术方向;通过审核后我们将邀请进群。(专业群审核较严,敬请谅解)