深度学习在花椒直播中的应用——排序算法篇

3,144 阅读18分钟

排序算法概述

现代推荐系统一般分为召回和排序两个阶段。召回阶段一般会用一些成本低、速度快的模型从十万、百万量级的候选集中初步筛选,留下千、百个;然后在排序阶段用更加精细的特征和复杂的模型来进行精排,最终留下topK个。

近十年间,业界排序模型的发展可以说是一日千里,从千篇一律的LR,到2010年FM的提出,再到2014年Facebook提出的树模型GBDT,这几年可以看成是现代推荐系统的上半场;

而2015年至今可以看成是飞速发展的下半场,几年之间,以DNN等模型为代表的深度学习网络,如雨后春笋般的出现,各种模型架构、特征交叉方式层出不穷,各种新的idea、trick令人眼花缭乱,而深度学习也逐渐成为了CTR、推荐领域的主流方法。

本文将沿着这一路线,对这些排序模型进行简单的介绍、梳理和总结。

一、传统模型

1. LR

在深度学习崛起之前,LR以其简单、速度快、可解释性强的优势,几乎垄断了早期的CTR、推荐领域。

h_{\theta}(x)=\frac{1}{1+e^{-\theta^{T}x}}
  • 直观来讲,LR模型目标函数的形式就是各特征的加权和,再通过sigmoid函数将结果映射到0-1之间来表达用户点击某个物品的概率,简单易懂,而且实现时可以并行,速度快。

  • 此外,通过观察学习到的各特征权重,我们可以轻易得知哪些特征比较“重要”,在预测出现偏差的时候,也可以很容易看出哪些因素影响了结果,这就是为什么说它可解释性强的原因。

  • 然而LR的缺点也很明显:由于它是简单的线性模型,就不能处理特征和目标之间的非线性关系,而且特征之间并不是完全独立的,有些特征交叉使用会有特别的效果。因此为了让模型有一定的非线性,当时的数据科学家需要手工做很大量的特征工程,比如连续特征离散化、特征之间的交叉等。但想要提取出高效的交叉特征,需要充分了解数据和场景,人力成本较高,而且再有经验的工程师也难以穷尽所有的特征交叉组合。

既然手工很难,能不能自动寻找特征交叉组合或者借助模型进行呢?后几年中出现了以FM、GBDT为代表的两种自动特征交叉方法。

2. FM/FFM

针对LR中特征交叉的问题,有人提出了下面的多项式模型:

y(\mathbf{x}) = w_0+ \sum_{i=1}^n w_i x_i + \sum_{i=1}^n \sum_{j=i+1}^n w_{ij} x_i x_j

从公式可以看出,模型对所有特征进行了两两交叉,并对所有的特征组合赋予了权重。

但这种暴力的方法存在着下面两个问题:

  • 现代推荐系统中往往包含大量稀疏的特征(如id类),而交叉特征的维度是原始特征维度的乘积,并且当且仅当两个特征值都为非0时,其对应的组合权重才会被更新到,这会使得大部分交叉特征的权重缺乏有效的数据进行训练,无法收敛,而且权重参数的数量由n直接上升到n^2,极大增加了训练复杂度。
  • 无法泛化到未曾在训练样本中出现过的特征组合中

针对上面两个问题,2010年德国康斯坦茨大学的Steffen Rendle提出了FM(Factorization Machine)

y(\mathbf{x}) = w_0+ \sum_{i=1}^n w_i x_i + \sum_{i=1}^n \sum_{j=i+1}^n \langle \mathbf{v}_i, \mathbf{v}_j \rangle x_i x_j

类似于矩阵分解(MF)的思路,FM为每个特征学习了一个隐权重向量(latent vector),在特征交叉时,使用两个特征隐向量的内积作为交叉特征的权重,而不是单一的权重。

  • 通过引入特征隐向量的方式,直接把原先n^2级别的权重数量减低到了nkk为隐向量维度,n \gg k)。在训练过程中,又可以通过优化二阶项的计算过程,使FM的训练复杂度进一步降低到nk级别,极大降低训练开销。

  • 而且FM解决了上面多项式模型中的数据稀疏问题。从公式可以看出,所有包含“x_i的非零组合特征”(存在某个j \neq i,使得 x_ix_j \neq 0)的样本都可以用来学习隐向量v_i,这很大程度上避免了数据稀疏性造成的影响。

  • 而且隐向量的引入也使得模型可以泛化到未曾出现过的特征组合中,兼顾了模型的记忆性和泛化性。

  • 工程方面,FM同样可以用梯度下降进行学习的特点使其不失实时性和灵活性。相比之后深度学习模型复杂的网络结构,FM比较容易实现的inference过程也使其没有serving的难题,直到现在也常被应用于召回阶段。

3. GBDT + LR

FM虽然综合效果很好,但是也只能够做二阶的特征交叉,如果要继续提高特征交叉的维度,不可避免的会发生组合爆炸和计算复杂度过高的情况。那么有没有其他的方法可以有效的处理高维特征组合和筛选的问题?

2014年Facebook在论文中提出了一种级联结构的树模型,用于解决这个问题。

思想很简单:

先训练一个GBDT模型,每棵树自上而下,每个节点的分裂是一个自然的特征选择的过程,而多层下来自然进行了有效的特征组合,这样每个叶子节点就对应了树的一条路径,也代表不同的特征交叉组合,这样后面就可以将所有叶子节点进行编号作为新的特征,再结合原始特征,输入LR训练最终的模型。

树模型的特征组合可以不像FM那样局限于2阶交叉:例如,每棵树的深度为5,那么通过4次节点分裂,最终的叶节点实际上是进行了4阶特征组合后的结果。但也不能因此就说GBDT比FM的效果好,因为树模型也有自身的缺点,比如容易过拟合高维稀疏数据,比如不能并行速度慢、比如泛化性差等。

但GBDT+LR的重要的意义在于,

  • 它提出了一种用模型自动进行特征工程、特征交叉的思想,某种意义上来说,之后深度学习的崛起,以及embedding的广泛应用,各种五花八门的网络结构,都是这一思想的延续和继承。
  • 它还提出了一种级联结构,并且每个模型可以分步更新。树模型训练慢可以每天甚至每周进行一次大型训练,而LR模型可以在线上进行分钟级别甚至秒级别的实时更新。这也为后面的模型提供了一种可以借鉴的serving的想法。

小结

从最早的人工规则排序,发展到人工进行特征组合的LR模型,再发展到自动进行二阶特征组合的FM模型,到后面高阶特征自动组合的LR+GBDT,这基本就是早期推荐系统排序模型的主脉络。

再往后,DNN模型的引入,标志着以深度学习为主的排序模型的崛起。纯粹的简单DNN模型本质上其实是在FM模型的特征Embedding化基础上,添加MLP隐层来进行隐式、特征非线性自动组合。

下面我们将重点介绍近年来独领风骚的深度学习模型。

二、深度模型

2015年之后,以DNN为代表的一系列深度学习模型逐渐出现,个人认为他们可以归结为两类:

  • 以Wide&Deep为代表的一系列模型,它们的共同特点是自动学习从原始特征交叉组合新的高阶特征,它们的区别在于wide部分或者deep进行了部分改动。
  • 以多任务学习为基础的联合训练模型,以ESMM、MMOE等模型为代表。

1. Wide&Deep类模型

这类模型的特点是双塔结构,即一边是以LR为代表的浅层模型(wide部分)用以学习低阶特征的表达,强调的是“记忆性”;另一边是以MLP为代表深层模型(deep部分),强调的是“泛化性”,deep部分的结构也大多可以分为下面几个模块:

  • raw input->embedding: 把稀疏特征映射为低维稠密的embedding向量的过程。
  • input_layer:在这一层通常会对各特征的embedding会做一些聚合操作。
  • input_layer->output: 通常会用几层MLP的全连接框架连接到softmax作为输出层。

大多数模型在deep部分的区别只在于input_layer这一块,不同的模型在交叉方式(隐式/显式,元素级/向量级),或者特征之间的连接方式(concatenate/weighted sum/product/BI-interaction/attention 等)或显示特征交叉的阶数(二阶/高阶)之间会有所不同,以Wide&Deep、(x)DeepFM、DCN、DIN为例,下面会简要介绍这几种模型。

这里先简单介绍下特征交互的方式:

  1. 一种是类似于MLP的方式,因其特殊的结构天然就具有学习高阶特征组合的能力,并且引入了一定的非线性;但至于怎么发生交互组合的,发生了多少阶的交叉,我们并不清楚,而且这种建模是元素级的(bit-wise),也就是说同一个域对应的embedding向量中的元素也会相互影响。因此我们说这种特征交叉方式是“隐式的、元素级的”。
  2. 另一种与之对应的是类似于DeepFM, xDeepFM的方式,在模型结构中,明确设计一些子网络或者子结构,可以对任意高阶的特征组合进行表征。以FM为例,就是向量级的方式明确对特征二阶组合进行建模,这种我们称之为“显式的、向量级的”。

Wide&Deep

  • 模型wide部分长处在于学习样本中的高频部分,“记忆性”好,对于样本中出现过的高频低阶特征能够用少量参数学习。但因为是LR模型,仍需人工进行特征交叉组合。
  • 模型deep部分用于学习特征之间的高阶交叉组合关系,引入了“泛化性”。是一种隐式、元素级的特征交叉。
  • 这种双塔框架结构的提出极大的促进了后续模型的发展

DeepFM

  • Wide&Deep框架固然强大,但由于wide部分是个LR模型,仍然需要人工特征工程。DeepFM模型将wide部分替换为FM,可以自动进行特征的二阶交叉。但它的局限也在于只有二阶交叉,而没有更高阶的交叉。
  • FM和deep部分共享embedding层,双边共同更新权重矩阵。这种share bottom的思想在后面模型中也很常见。

DCN

想要得到任意高阶的特征交叉组合,而不仅仅是二阶,但是又要避免产生组合爆炸的维数灾难,导致网络参数过于庞大而无法学习,同时也会产生很多的无效交叉特征,需要设计一种有“压缩”能力的,并且足够高效的网络结构。DCN就是其中的一种:

向量交叉方式如下:

  • 在保留了MLP结构的基础上,还额外引入了cross layer network,理论上可以表达任意高阶组合,同时每一层保留低阶组合,参数的向量化以及独特的网络结构也控制了模型的复杂度是线性增长的,不至于随着交叉阶数的增大而发生维度爆炸。
  • 但在xDeepFM论文中指出,DCN的特征交叉是限定在一种特殊的形式上的,并且还是以bit-wise的方式构建的。

xDeepFM

xDeepFM模型是自动构建交叉特征且能够端到端学习的集大成者,它有效的解决了DCN中提到的问题,实现自动学习显式的高阶特征交互,同时使得交互发生在向量级上。

模型设计了一种独特的CIN结构,经过外积、卷积等操作来提取特征的交叉。

并且可以通过控制CIN的层数来显式控制特征交叉的阶数,并且计算的时空复杂度是线性增长的,而不会出现组合爆炸导致参数爆炸而无法训练的情况。

  • 集成的CIN和DNN两个模块能够帮助模型同时以显式和隐式,元素级和向量级的方式学习任意高阶的特征交互,并且保持线性复杂度。

DIN

  • 特点在于拿到当前物品以及用户所有交互过物品的embedding,之后通过attention network,对每个兴趣表示赋予不同的权值,之后进行weighted sum,得到一个汇总的embedding作为针对当前物品的用户兴趣的表示,相当于增加了一步自动特征选择。
  • 也反映了模型是服务于场景的这一理念。先观察到用户兴趣的多峰分布以及部分对应的数据特点,再因地制宜的提出合适的模型进行拟合。

小结

2. 多任务类模型

推荐系统的多目标优化,是目前业界的主流之一,也是很多公司的研发现状。以我们花椒直播为例,可以优化的目标有点击、观看、送礼、评论、关注、转发等等。

多任务模型旨在平衡不同目标的相互影响,尽量能够做到所有指标同步上涨,即使不能,也要尽量做到在某个优化目标上涨的情况下,不拉低或者将尽量少拉低其它指标,力求达到全局最优的效果。

这里主要介绍ESMM和MMOE两个模型。

ESMM

论文指出,完整的日志流程应该包括:

impression->click->conversion

样本空间如下图所示:

传统的CVR任务,只考虑从浏览到转化的过程,即

p(cvr) = p(conversion=1|impression)

而本模型还考虑了点击的过程,并引入了浏览转化率(pCTCVR)的概念,即为在浏览的条件下既点击又转化的概率,即

p(conversion=1,click=1|impression) = p(click=1|impression) * p(conversion=1|click=1, impression)

也就是下面的公式:

根据这个公式设计的模型如下图:

  • 用两个任务共享底层embedding的方式,然后将各自的logit进行相乘来拟合pCTCVR的过程。

样本的构建为:

任务 正样本 负样本
pCTR 点击 未点击
pCTCVR 点击且转化 未转化

模型特点:

  • 在全样本空间进行建模,避免了“样本选择偏差”问题,充分利用了业务数据。
  • 共享底层embedding向量,因为推荐中转化率是很低的,对应的数据很少,这种共享特征表示的机制使CVR网络也能够从只曝光没点击的样本中更新embedding向量,有利于缓解CVR训练数据稀疏的问题。
  • ESMM中的子网络可以不止局限于本文中的MLP,可以随意替换成其他模型,也就是说本文为我们提供了一种可扩展的多任务模型架构。阿里后面还有一篇ESM^2的论文也是类似的套路。

MMOE

论文指出:一般的多任务模型结构如上图(a)所示,即对于不同的任务,底层的参数和网络结构是共享的,然后上层经过不同的神经网络得到对应任务的输出,缺点是模型的效果取决于任务的相关性,如果多任务之间关联较小,采用这种结构甚至会出现互相拖后腿的情况。

因此本论文提出了基于图(b)的OMOE和图(c)的MMOE两种结构,主要思路是每个任务有一个独立的expert中间网络,类似于“开关”的功能,通过模型学习,不同的任务可以从相同的底层embedding中提取到侧重点不同的特征,而不是完全共享底层,即达到了“各取所需”的效果,有点类似于上面提到的attention网络。

之后每个任务接各自的tower模型,得到logit,再和label一起计算loss,然后多目标的loss直接可以用类似weighted sum的方式结合起来组成总的loss。

小结

推荐系统的多任务模型,虽然是排序模型的一大发展趋势,但多目标学习的难处在于,每个目标的样本比例是不同的,训练时如何融合loss、何时停止训练以及线上各目标的分数如何组合、A/B test如何衡量总体效果等方面,都要经过比较复杂的衡量和考虑,这些都还有很大的发展空间,需要我们来尝试。

排序模型在花椒直播中的实践

近两年来,花椒直播紧跟业界潮流,在排序阶段进行了多种多样的尝试,如(GBDT+)LR,Wide&Deep,(x)DeepFM,DIN,ESMM,MMOE等。下面以Wide&Deep模型为例,简单介绍下我们的整个排序系统。

首先是离线部分,我们主要用spark/hdfs来处理、存储数据。主要包括用户数据、主播数据、实时数据、行为序列等等。下面是我们用到的部分特征:

类别 特征
用户画像 性别、年龄、机型、地域、看播/打赏/弹幕/转发/关注的统计、行为序列……
主播画像 性别、年龄、地域、等级、类别、标签、频道、达人、时长、收礼、粉丝以及各种统计类排行……
实时特征 实时看播、打赏、弹幕、热度、是否唱歌、是否跳舞、游戏精彩瞬间……

生产好用户、主播画像后,还要生产一个基于用户主播交互数据的标签集,可以是多标签以便于多任务模型使用,比如用户浏览过哪些主播,是否发生了观看、打赏、评论、关注等行为,如果发生了,还可以把如看播时长等程度数据作为权重,以便后面进行加权训练时使用。

之后将标签集和画像join起来,就形成了一天的数据集,可以用多天的训练集共同组成最终的整体数据集来满足数据量和覆盖度的要求,这里要小心不要发生数据穿透。最终的数据集是T级别的,存储在HDFS上。在训练阶段,单机多卡的配置也满足不了速度上的要求,因此我们采用了360私有云的hbox分布式训练平台,来完成日常深度模型的训练。

下面是我们的模型结构图:

下面是我们部分模型的效果:

离线

模型 AUC*100
FM 78.9
Wide&Deep 84.5
DeepFM 84.7

线上:热门频道接入个性化推荐后人均观看时长涨幅>80%

后记

本文只是对业内近年来常用的模型进行的简单的介绍和总结,实际上每个模型除了其典型的结构外,还有许多非常珍贵的细节,比如公式推导,参数的选择,工程上的trick等等,这些建议大家还是要精读下相关模型论文。

并且要注意的是,没有“最好的模型”,只有“最适合的模型”,并不是说模型越fancy越复杂,线上效果就会越好。比如阿里提出了DIN模型,是因为工程师们首先发现了数据中的现象:

用户在浏览电商网站的过程中显示出的兴趣是十分多样性的,并且只有部分历史数据会影响到当次推荐的物品是否被点击,而不是所有的历史记录,即“多峰分布”、“部分激活”。

正是这种特定场景的需要,才使得阿里研发了DIN模型,来捕获用户兴趣的进化,取得了突破的效果。

所以做推荐正确的顺序应该是先有特定的“场景”,然后再基于用户行为和数据的特点,对应的开发适用于这个场景的模型;而不是先拍板一个模型,再去数据中进行试验,就本末倒置了。