今天分享的是Youtube 2016年的推荐系统论文《Deep Neural Networks for YouTube Recommendations》
YouTube是如今工业界最大、最复杂的推荐系统之一,作者提出了一种高效的基于深度学习的推荐系统。该系统和工业界经典的推荐流程一样,分为候选集生成( candidate generation也称为召回),排序(ranking)两个阶段。
在推荐系统领域,特别是YouTube的所在视频推荐领域,主要面临三个挑战:
首先figure2中的millions、hundreds、dozens:表示数据量的级别,全部的video corpus大概是millions级别,经过candidate generation之后大概是hundreds级别,经过ranking之后大概是dozens级别。
Candidate Generation Model:输入包括millions video corpus、user history and context ,旨在快速高效地筛选部分视频集合。
Ranking Model:输入包括hundreds video corpus、user history and context、other candidate sources、video features,旨在得到高精度的TOP N。
我们把推荐问题建模成一个“超大规模多分类”问题。即在时刻 t t t,用户 U U U(上下文信息 C C C)会观看视频 i i i的概率(每个具体的视频视为一个类别, i i i即为一个类别),用数学公式表达如下:
P ( w t = i ∣ U , C ) = e v i u ∑ j ∈ V e v j u P(w_{t} = i|U,C) =\frac{e^{v_{i}u}}{\sum _{j\in V}e^{v_{j}u}} P(wt=i∣U,C)=∑j∈Vevjueviu
很显然上式为一个softmax多分类器的形式。
其中 u u u为
DNN架构如下图所示:
整个模型架构是包含三个隐层的DNN结构。输入是用户浏览历史、搜索历史、人口统计学信息和其余上下文信息concat成的输入向量;输出分线上和离线训练两个部分。
离线训练阶段输出层为softmax层,输出3.1中公式表达的概率。而线上则直接利用user向量查询相关商品,最重要问题是在性能。我们利用类似局部敏感哈希(Locality Sensitive Hashing)
使用DNN的一个关键优点是,DNN的输入可以方便的处理离散和连续变量。
每一秒中,YouTube都有大量视频被上传,推荐这些最新视频对于YouTube来说是极其重要的。同时,通过观察历史数据发现,用户更倾向于推荐那些尽管相关度不高但最新(fresh)的视频。
为了拟合用户对fresh content的bias,模型引入了“Example Age”这个特征,sample log距离当前的时间作为example age(文章并没有定义)。例如24小时前,用户观看该视频,会产生日志,这个example age就是24。而在线上服务阶段,该特征被赋予0值甚至是一个比较小的负数。这样的做法类似于在广告排序中消除position bias。
文章也验证了,example age这个feature能够很好的把视频的freshness的程度对popularity的影响引入模型中。[详见Q&A 3]
从上图中我们也可以看到,在引入“Example Age”这个feature后,模型的预测效力更接近经验分布;而不引入Example Age的蓝线,模型在所有时间节点上的预测趋近于平均,这显然是不符合客观实际的。
在这里,正样本是用户所有完整观看过的视频,其余可以视作负样本。
此外,还进行了如下设计:
下图所示图(a)是held-out方式,利用上下文信息预估中间的一个视频;图(b)是predicting next watch的方式,则是利用上文信息,预估下一次浏览的视频。我们发现图(b)的方式在线上A/B test中表现更佳。只留最后一次观看行为做测试集主要是为了避免引入future information,产生与事实不符的数据穿越。
评估输入特征以及网络层数对于实验效果的影响,评价指标是MAP(Mean Average Precision)。
第0层的输入向量全连接到softmax输出层,第0层以及输出层都是采用固定的256维度。依次增加网络深度(+512 → +1024 → +2048 → …),预测效果如下图:
可以很明显看出,增加了观看历史之外的特征很明显的提升了预测得准确率;从网络深度看,随着网络深度加大,预测准确率在提升,但继续增加第四层网络准确率已经没有显著的提升了。
对于在线服务来说,有严格的性能要求,youtube没有重新跑一遍模型,而是通过保存用户的embedding和视频的embedding,通过最近邻搜索的方法得到top N(approx topN,使用hash的方法来得到近似的topN)的结果。
ranking是对生成的候选集做进一步细粒度的排序,可以参考更多维度的特征。通常,排序阶段还涉及到对多个不同召回源进行有效集成,不同召回源的打分有时候并没有可比性,所以排序阶段也需要解决此类问题。(如果召回阶段采用多路召回,每一路召回因为采取的策略或者模型不同,所以各自的召回模型得分不可比较,比如利用协同过滤召回找到的候选Item得分,与基于兴趣标签这一路召回找到的候选Item得分,完全是不可比较的。)。
在目标的设定方面,单纯CTR指标是有迷惑性的,有些靠关键词(“clickbait”)吸引用户高点击的视频未必能够被播放。[详见Q&A 4]
尽管深度学习很少需要人工特征工程。然而在搜索和推荐场景,我们的很难把原始数据直接作为DNN的输入,特征工程仍然很重要。而特征工程中最难的是如何建模用户时序行为(temporal sequence of user actions),并且关联这些行为和要rank的item。但是通过对用户和物品之间的交互行为,我们仍然能提取出一些有用信息,
比如我们要度量用户对视频的喜欢,可以考虑用户与视频所在频道间的关系:例如用户浏览该频道的次数、最近一次浏览该频道距离现在的时间。
在排序阶段,输入的特征主要有:
第4个特征是用户上次观看同频道时间距现在的时间间隔,这里有一点attention的意思,假如我们刚看了一场NBA比赛的集锦,我们很可能继续观看NBA频道的其他视频,那么这个特征就很好地捕捉到了这一行为。引入第5个特征previous impressions避免同一个视频持续对同一用户进行无效曝光。尽量增加用户没看过的新视频的曝光可能性。
(1) Feature Engineering
在进行video embedding的时候,只保留用户最常点击的N个视频的embedding,剩余的长尾视频的embedding直接用0向量代替。
可能的解释主要有两点,一是从模型角度讲,出现次数较少的视频的embedding没法被充分训练。二是为了节省online serving中宝贵的内存资源。
(2) Embedding Categorical Features
对于相同域的特征可以共享embedding,比如用户点击过的视频ID,用户观看过的视频ID,用户收藏过的视频ID等等,这些公用一套embedding可以使其更充分的学习,同时减少模型的大小,加速模型的训练。
(3) Normalizing Continuous Features
NN对输入特征的尺度和分布都是非常敏感的,实际上基本上除了Tree-Based的模型(比如GBDT/RF),机器学习的大多算法都如此。我们发现归一化方法对收敛很关键,推荐一种排序分位归一到[0,1]区间的方法。(归一化还可以加速模型的收敛)
除此之外,我们还把归一化后的的根号和平方作为网络输入,以期能使网络能够更容易得到特征的次线性(sub-linear)和(super-linear)超线性函数。(引入了特征的非线性)
在训练阶段,Youtube没有把问题当作一个CTR预估问题,而是通过weighted logistic 建模了用户的期望观看时间。
这里主要有两个问题:
对于传统的深度学习架构,输出层往往采用LR或者Softmax,在线上预测过程中,也是原封不动的照搬LR或者softmax的经典形式来计算点击率(广义地说,应该是正样本概率)。但是,YouTube这一模型的输出层没有使用LR,而是采用了weighted logistic regression。
首先,回到LR的定义:
h θ ( x ) = g ( θ T x ) = 1 1 + e − θ T x h_{\theta}(x) =g(\theta ^{T}x) = \frac{1}{1+e^{-\theta ^{T}x}} hθ(x)=g(θTx)=1+e−θTx1
对于一个二分类问题而言:
P ( y = 1 ∣ x ) = h θ ( x ) P(y=1|x) = h_{\theta}(x) P(y=1∣x)=hθ(x) P ( y = 0 ∣ x ) = 1 − h θ ( x ) P(y=0|x) = 1-h_{\theta}(x) P(y=0∣x)=1−hθ(x)
一件事情的几率(odds)是指该事件发生的概率与该事件不发生的概率的比值,如果事件发生的概率是 p p p,那么该事件的odds是:
p 1 − p \frac{p}{1-p} 1−pp
对于LR而言:
1 1 + e − θ T x 1 − 1 1 + e − θ T x = 1 1 + e − θ T x / e − θ T x 1 + e − θ T x = e θ T x \frac{ \frac{1}{1+e^{-\theta ^{T}x}}}{1- \frac{1}{1+e^{-\theta ^{T}x}}}=\frac{1}{1+e^{-\theta ^{T}x}}/\frac{e^{-\theta ^{T}x}}{1+e^{-\theta ^{T}x}}=e^{\theta ^{T}x} 1−1+e−θTx11+e−θTx1=1+e−θTx1/1+e−θTxe−θTx=eθTx
所以Serving函数计算的是odds。
为什么Youtube要预测的是用户观看时长,线上serving却是odds?
这就要提到YouTube采用的独特的训练方式Weighted LR,这里的Weight,对于正样本 i i i来说就是观看时长 T i T_{i} Ti,对于负样本来说,则指定了单位权重1。
Weighted LR的特点是,正样本权重 w w w的加入会让正样本发生的几率变成原来的 w w w倍。
备注 严格的说,Weighted LR中的单个样本的weight,并不是让这个样本发生的概率变成了weight倍,而是让这个样本,对预估的影响(也就是loss)提升了weight倍。因为观看时长的几率 = ∑ T i N − k \frac{\sum T_{i}}{N-k} N−k∑Ti,非wieght的odds可以直接看成N+/N-,因为wieghted的lr中,N+变成了weight倍,N-没变,还是1倍,所以直接可得后来的odds是之前odds的weight倍。
也就是说样本i的odds变成了下面的式子:
o d d s ( i ) = w i p 1 − w i p odds(i) = \frac{w_{i}p}{1-w_{i}p} odds(i)=1−wipwip
由于在视频推荐场景中,用户打开一个视频的概率 p p p往往是一个很小的值,因此上式可以继续简化:
o d d s ( i ) = w i p 1 − w i p ≈ w i p odds(i) = \frac{w_{i}p}{1-w_{i}p}\approx w_{i}p odds(i)=1−wipwip≈wip
而且由于YouTube采用了用户观看时长 T i T_{i} Ti作为权重, w i = T i w_{i} =T_{i} wi=Ti,因此式子可进一步写为:
o d d s ( i ) = w i p 1 − w i p ≈ w i p = T i p odds(i) = \frac{w_{i}p}{1-w_{i}p}\approx w_{i}p = T_{i}p odds(i)=1−wipwip≈wip=Tip
由于 p p p就是用户打开视频的概率, T i T_{i} Ti是观看时长,因此 T i ∗ p T_{i}*p Ti∗p就是用户观看某视频的期望时长。
总结:
模型采用了expected watch time per impression作为优化目标,所以如果简单使用LR就无法引入正样本的watch time信息。因此采用weighted LR,将watch time作为正样本的weight,在线上serving中使用 e W x + b e^{Wx+b} eWx+b做预测可以直接得到expected watch time的近似。
上图是离线利用hold-out一天数据在不同NN网络结构下的结果。如果用户对模型预估高分的反而没有观看,我们认为是预测错误的观看时长。weighted, per-user loss就是预测错误观看时长占总观看时长的比例。
我们对网络结构中隐层的宽度和深度方面都做了测试,从上图结果看增加隐层网络宽度和深度都能提升模型效果。而对于1024→512→256这个网络,测试的不包含归一化后根号和方式的版本,loss增加了0.2%。而如果把weighted LR替换成LR,效果下降达到4.1%。
1. user vector和video vector是如何生成的?
DNN的输入特征是
video vector是预测时使用softmax matrix中每个video对应的w作为该video的vector,最终通过user_vec与item_vec的内积最大索引就能快速得到结果。 待继续完善
2. 将推荐问题转换成多分类问题,在预测 w t w_{t} wt的场景下,每一个备选video都会是一个分类,因此总共的分类有数百万之巨,这在使用softmax训练时无疑是低效的,应该如何解决?
负采样(negative sampling) 的方法,并用importance weighting对采样进行校正,提高模型学习的效率。
例如:在当前场景下的负采样:假设有一个样本,label=video_18,如果分类总共有100个,训练到这条样本的时候,由于最后是softmax,模型更新参数使video_18的softmax输出偏向1,剩余99个item的softmax输出偏向0。负采样指的是当总分类达到十万,正常softmax需要使得剩余99999个item的softmax输出偏向0,这样更新量很大,所以采用sample softmax,在更新这次样本时指定全集只有5001,屏蔽了剩余的94999个item,即负采样数目=5000,这样这次更新只会使得当前item输出偏向1,剩余5000个item的softmax输出偏向0。
3. 引入fresh content的bias的作用?
我的理解是:视频的点击率实际上都会受fresh的影响,训练的时候加入example age ,为的就是“显式”的告诉模型example age对点击的影响。在预测的时候,example age置0,就排除了这个特征对模型的影响。类似于广告,广告在展示列表中的位置,对广告的点击概率有非常大影响,排名越靠前的广告,越容易被点击,在产生训练样本的时候,把展示位置作为特征放在样本里面,并且在使用模型的时候,把展示位置特征统一置为0。
4. YouTube为什么不采用经典的CTR,或者播放率,而是采用了每次曝光预期播放时间(expected watch time per impression)作为优化目标?
因为 watch time更能反应用户的真实兴趣,从商业模型角度出发,因为watch time越长,YouTube获得的广告收益越多。而且增加用户的watch time也更符合一个视频网站的长期利益和用户粘性。