总述:这篇文章是先从论文翻译入手,讲解下 YoutuBe 里面是如何利用深度学习做搜索推荐的。YoutuBe 的这篇文章基本上是深度学习做搜索推荐的一篇“鼻祖”文章,在那年提出来这个之后,有很多公司都在这个基础上去试验新的办法(比如阿里的DIN,就是以这个为 baseline 作为效果对照标准),或者直接采纳为公司里面的线上模型方法。
本文先从论文翻译入手,后续还会给出源码理解、以及博主的实践理解
原文链接:https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/45530.pdf
YouTube的推荐技术是现存规模最大,最复杂的工业推荐系统之一。 在本文中,我们将对这个系统进行高级描述,并重点介绍深度学习带来的显着性能改进方法。 本文按照经典的两阶段信息检索二分法进行划分:首先,我们详细介绍了一个深度候选生成模型,然后描述了一个单独的深度排序模型。 我们还提供实践经验和自己的见解,这些经验教训和见解源于设计、迭代和维护一个具有巨大用户的大型推荐系统。
YouTube是世界上最大的创建、共享和发现视频内容的平台。 YouTube推荐系统有助于帮助超过10亿用户,从不断增长的视频中发现个性化内容。 在本文中,我们将重点介绍最近对YouTube视频推荐系统进行的深度学习。 图1显示了YouTube移动应用主页上的页面。
从三个主要方面推荐YouTube视频极具挑战性:
规模:许多现有的推荐算法能够很好地解决小问题,但是对我们的数据、问题规模无法正常运作。 高度专业化的分布式学习算法、以及高效的服务系统对于处理至关重要YouTube庞大的用户群和语料库非常有必要。
新鲜度:YouTube有一个非常动态的语料库,每秒上传许多小时的视频。该推荐系统应该足够的响应能力,对于用户新上传的内容以及用户采取的最新操作,需要有有良好的处理能力,也能平衡新内容,还可以从中了解完善的视频探索/开发的观点。
(图1:YouTube移动应用程序主页上显示的推荐内容)
噪音:由于稀疏性和各种不可观察的外部因素,用YouTube上的历史用户行为来进行建模,本身是很难预测的。 我们很少获得用户满意度的基本事实模型噪声隐式反馈信号。 此外,与内容相关联的元数据结构不良没有明确定义的本体论。 我们的算法需要要坚定我们的这些特点来训练数据。
与Google的其他产品领域相结合,几乎在所有的学习问题中,YouTube已经经历了将深度学习作为通用解决方案的基本模式这个转变。 我们的系统建立在Google上Brain [4]最近开源为TensorFlow [1]。TensorFlow为实验提供了灵活的框架,使用大规模分布式训练的各种深度神经网络架构。 我们的模型大致了解十亿个参数,并接受数千亿个样本的训练。
与矩阵分解方法[19]中的大量研究相比,使用深度学习的工作相对较少被用在推荐系统中。 神经网络用于在新闻中做推荐[17],在[8]中被引用,并在[20]中的用于评级。 协同过滤在[22]和自动编码器中被公式化并被用在深度神经网络[18]。 Elkahky等人,把这种方法用于跨领域的深度学习用户建模[5]。 在基于内容的环境中,Burges等人,使用深度神经网络进行音乐推荐[21]。
本文的结构如下:在第2节中简要介绍系统概述。第3节更详细地描述了候选视频生成模型,包括如何训练并怎么用于系统进行提供建议。 实验结果将展示模型如何从隐藏的深层中受益单位和其他异构信号。 第4节详细描述排名模型,包括经典逻辑回归,如何被修改以训练预测预期观看时间的模型(而不是点击概率)。 实验结果会表明隐藏层在这种情况下也很有用。 最后,第5节介绍了我们的结论和从训练中学到东西。
我们的推荐系统的总体结构如图2所示。该系统由两个神经系统组成网络:一个用于召回,一个用于排名。
候选生成网络把用户在YouTube中的活动历史记录作为输入,并检索来自大型语料库的小部分(数百)视频。 这些候选视频通常与用户相关性很高。 仅候选生成网络仅仅通过协作过滤提供召回结果。用户之间的相似性以粗略表示功能,如观看视频的ID,搜索词和统计值。
要想在候选列表中提出一些“最佳”建议,需要一个高水平的表达,以便用来在高度召回的结果中区分相对重要的候选结果。rank model使用丰富的一组描述视频和用户的特征,再结合完成此任务所需的目标函数,来为每个视频打一个分数。 得分最高视频呈现给用户,按其分数排名。
推荐系统的两阶段方法(召回粗排、然后再精排)允许我们从一个非常大的语料库(数百万)提出可能建议的视频,而且这些数量不多的推荐结果是个性化的,并且对用户有吸引力。 此外,这种设计可以实现把从其他来源产生的候选集混合起来,例如早期作品[3]中描述的候选集。
在开发过程中,我们广泛使用离线指标(precision, recall, ranking loss, 等)来迭代改进我们的系统。 然而,为了最终确定算法或模型的有效性,我们在线实验中 AB测试。 在在线实验中,我们可以测量点击率的细微变化,观看时间以及衡量用户参与度的许多其他指标。 这很重要,因为实时A / B结果是并不总是与离线实验相关联。
在候选集生成期间,巨大的YouTube语料库可能被淘汰到只有数百个视频与用户相关。 这里描述的推荐器的前身是一个基于rank loss的矩阵分解方法[23]。 我们的神经网络的早期迭代模型用浅层网络来模仿这种因式分解行为,仅用户嵌入向量表达用户之前观看过的数据。从这个角度来看,我们的方法可以被视为分解技术的非线性推广。
我们提出将多分类作为推荐办法,通过分类一个特殊的视频集合,预测问题会变得很准确,基于用户U和来自语料库V的视频i(类)上下文C,预测问题在数百万个video之间,在时间t准确地对特定视频打上权重进行分类
其中u∈R的N次方(全集合空间),是用户向量,通过输入用户信息和上下文信息给上面模型架构训练得到,vj∈R的N次方代表每个候选视频嵌入向量(采用word embedding 的方式计算出每个视频的 embedded 向量)。 在此设置中,一个嵌入向量是一个简单的映射关系,映射稀疏实体(单个视频,用户等)进入到R后,形成密集向量N。深层网络的任务是把用户向量,当做用户的历史记录和上下文来学习,可在具有softmax分类器的视频中用于区分。
尽管YouTube上存在明确的反馈机制(拇指向上/向下,产品内调查等),但我们使用隐式反馈[16]来训练模型,用户完成视频的观看是一个正例。 此选择基于更多数量级的隐含的用户历史记录,允许我们在显式反馈非常稀疏的情况下给出更好的推荐结果。
高效的极端多类
为了有效地训练具有数百万个类的这种模型,我们依靠一种技术从正负分布中采样负类(“候选采样”),然后通过重要性加权来校正这种采样[10](importance weighting的方式)。 对于每个示例,对于真实标签和采样的负类标签,都用交叉熵损失最小化作为损失。 在实践中,对几百个负片进行采样,相当于传统softmax速度的100倍以上。 一种流行的替代方法是分层softmax [15],但我们无法达到相当的准确度。 在分层soft-max中,遍历树中的每个节点涉及区分通常不相关的类集,这使得分类问题更加困难并且性能降低。
在线上serving时,我们需要计算最可能的N类(视频),以便选择要呈现给用户的前N个。 在数十毫秒的预估等待时间内,对数百万项视频item进行评分,需要在类的数量上采用近似的评分方案。 YouTube以前的系统依赖于hash[24],这里描述的分类器使用类似的方法。 由于在serving时不需要来自softmax输出层的校准似然,因此评分问题减少到可以使用通用“所有视频item”的点积空间中的最近邻搜索[12](也就是点积的办法,在所有视频向量中,寻找与u点积最大的前N个视频向量”的搜索问题)。 我们发现A / B结果对最近邻搜索算法的选择不是特别敏感。
受"词袋"语言模型的启发[14],我们为每个视频学习高维嵌入固定词汇并将这些嵌入提供给前馈神经网络。 一个用户的观看历史,通过可变长度的稀疏视频ID序列来进行表达,然后通过嵌入映射到密集矢量进行表示。 网络需要固定大小的dense输入,简单地通过比如平均的办法,将这些稀疏向量进行处理(sum,component-wise max等)。 重要的是,这些嵌入向量,是与所有其他模型参数通过正常梯度下降反向传播来更新,所以向量也在不断的学习中。 所有的特征在第一层拼接后给输出进来,然后是几层全连接层(ReLU)[6]。 图3显示了一般情况这样一种网络架构。
图3:图3:深度候选生成模型体系结构,展现了嵌入的稀疏特征、和dense的特征如何相连起来。 在连接之前对嵌入进行平均以转换可变大小的稀疏I序列,到适合输入隐藏层的固定宽度矢量。 所有隐藏层都全连接层。 在在训练中,梯度下降的目标是交叉熵损失最小化,输出端是采样的softmax的输出。在serving中,执行近似最近邻查找以生成数百个候选视频的召回。
使用深度神经网络作为矩阵分解的一个关键优势是,任意连续和分类特征可以很容易地添加到模型中。搜索历史记录、与观看历史记录的处理方式几乎一致,每一个query词被标记为unigrams和bigrams,并且每个标记都被embedding化。 平均后,用户的向量化query,表征成一个一个相加起来的稠密search历史序列。用户统计特征对于提供先验数据而言,对新用户进行推荐来说非常有用。用户的地理区域和设备这两个特征也都被embedding化,并且加到输入第一层的向量里面里面去。 简单的类别特征、连续特征(比如说用户的性别,登录状态和年龄)等被直接归一化为[0,1]区间,然后输入到网络中作为实际值特征。
示例下年龄这个特征的做法:
YouTube上每秒会上传许多小时的视频。推荐最近上传(“新鲜”)内容对于YouTube来说非常重要。不过,我们始终注意到用户更喜欢新鲜内容,甚至和用户以往的观看类型不太一样。 除了在首位推荐用户想要观看的新视频这个点要注意,有一个关键的次要现象,那就是用户经常观看的类别的视频,和一些传播的很热门的内容[11]。
机器学习系统通常表现出隐含的偏见,这些偏见是用户过去的习惯,因为系统就是用过去已经发生的数据来训练的。视频的流行度是非常不稳定的,但我们的推荐人在多达几周的训练窗口期间,将会反应出来一些平均观看行为的现象。 为了纠正这个问题,我们加了一个上传时间长短特征。 在线上预估的是,把这个特征设置成0(或者很小的负数),使得这个特征在线上预估时不起作用,这就是典型的position bias,感兴趣的读者可以看我对这方面做得两个研究。
搜索、推荐业务中 - position bias的工业界、学术界 发展历程 - 系列2(共计2)
搜索、推荐业务中 - position bias的工业界、学术界 发展历程 - 系列1(共计2)
图4展示了,在任意选择的视频中这种方法的有效性[26]。
重要的是要强调该"推荐结果"能解决代理问题,并将结果转移到特定环境下。 一个典型的例子是准确预测电影的评价,以致于能够对电影进行有效的推荐[2]。 我们发现,这种问题下,通过对A / B测试性能具有极大的重要性,但很难通过离线实验来衡量。
所有YouTube的观看历史(甚至是嵌入在其他网站上的观看历史)都会生成训练样本,而不仅仅是用我们自己平台上产生的数据。 否则,新内容将难以浮出水面,而推荐者将过度偏向于我们公司的算法工程师推荐的结果。 如果用户通过我们的推荐结果以外的方式看了其他视频,我们希望能够通过协作过滤将此发现快速传播给其他人。 改进实时指标的另一个关键方式是为每个用户生成固定数量的训练样本,从而在损失函数中有效地加权我们的用户。 这阻止了一小群高度活跃的用户主导损失。
有点违反直觉,必须非常小心地从分类器中隐瞒一些信息,以防止模型利用网站的结构并过度拟合问题。 以用户刚刚发出“tay-lor swift”搜索查询的情况为例。 由于我们的问题是预测下一个观看的视频,给定此信息的分类器将预测最有可能观看的视频是出现在相应搜索结果页面上的“tay-lor swift”的视频。 毫无疑问,再现用户的最后一个搜索页面作为主页推荐表现非常糟糕。 通过丢弃序列信息并用无序的query词组成的新query,来表示搜索查询,分类器不再直接知道标签的来源。
视频的自然消费模式通常会导致非常不对称的共同观看概率。 剧情系列通常是按顺序观看的,用户经常会从最广泛的流行开始,发现一种类型的艺术家,然后再关注较小名气的人。 因此,我们发现预测用户下一个watch视频的性能要好得多,而不是预测随机的watch视频(图5)。 许多协作过滤系统,从随机的一些item中提取label和上下文,然后借助用户历史行为来进行预测(5a)。 这会泄漏未来信息,并忽略任何不对称的观看模式。 相比之下,我们通过选择随机视频来“回滚”用户的历史记录,并且仅保留视频label(5b)之前用户输入所采取的动作。
如图6所示,添加特征,和增加深度可显著提高预测数据的准确性。在这些实验中,嵌入了1M大小视频和1M大小的搜索词汇表,每个最多包含50个最近观看的视频id、50个最近搜索词,每个用256个浮点数表示。softmax层在这1M视频类上输出多项分布,其尺寸为256(可以将其视为单独的输出视频的embedding表达)。这些模型经过训练,直到与所有YouTube用户融合,将整个数据多过几个epoch。网络结构遵循一个共同的“塔”模式,其中网络的底部最宽,每个连续的隐藏层将单元的数量减半(类似于图3)。深度0层网络实际上是线性分解方案,其执行与前一系统非常相似。不断的增加宽度和深度,增加收益会越来越难,并且收敛变得困难:
Depth 0: 线性层简单地转换连接层以匹配256的softmax维度
Depth 1: 256 ReLU
Depth 2: 512 ReLU → 256 ReLU
Depth 3: 1024 ReLU → 512 ReLU → 256 ReLU
Depth 4: 2048 ReLU → 1024 ReLU → 512 ReLU → 256 ReLU
图6:视频嵌入之外的特征改进了保持平均精度(MAP),深度层增加了表现力,因此模型可以通过模拟它们的交互来有效地使用这些附加功能。
图5:为模型选择标签和输入上下文对于离线评估具有挑战性,而且对实时性能有很大影响。 在这里,solid events 是网络的输入特征,而hollow events 被排除在外。 我们发现预测未来的watch视频(5b)在A / B测试中表现更好。 在(5b)中,视频上传时间长短表示为tmax-tN,其中tmax是训练数据中的最大观察时间。
排名的主要作用是使用印象数据来专门化和校准特定用户界面的候选预测。 例如,用户可能一般以高概率观看给定视频,但由于缩略图图像的选择而不太可能点击特定主页。 在排名期间,我们可以得到更多描述视频的特征、以及用户与视频的关系特征,因为最终只能推荐几百个视频,也就只有几百个视频得分,而不是在候选代中得分的数百万。 排名对于对不能直接比较的不同候选来源进行整合也至关重要。
我们使用具有类似架构的深度神经网络,来候选生成这几百个item,使用逻辑回归为每个视频进行打分(图7)。 然后按该分数对视频列表进行排序并返回给用户。 我们的最终排名目标是根据实时A / B测试结果不断调整,但通常是看每次展示的预期观看时间,这样一个简单函数。 按点击率排名通常会促使用户无法完成整个观看,造成一些欺骗性视频(“clickbait”),而观看时间更能捕捉参与度[13,25]。
我们的特征与传统的分类和连续/序数特征分类相隔离。 我们使用的分类特征在其基数上变化很大 - 一些是二进制的(例如,用户是否登录),而另一些则具有数百万个可能的值(例如用户的最后一个搜索查询)。 根据特征是仅贡献单个值(“one-hot”)还是一组值(“multi-hot”)进一步划分功能。 举一个前面说的one-hot类型特征的,正在评分的印象的视频ID,而相应的多价特征可能是用户观看的最后N个视频ID的bag。 我们还根据功能是描述项目的属性(“印象”)还是用户/上下文的属性(“查询”)来对功能进行分类。 每个请求计算一次查询功能,同时为每个item计算压缩功能。
图7:深度排名网络体系结构,描述嵌入式分类特征(包括one-hot和multi-hot),具有共享embedding向量和规范化连续特征的功能。 所有层都完全连接。 在实践中,数百个特征被馈送到网络中。
我们通常在排名模型中使用数百种特征,大致在分类和连续之间分配。 尽管有望用深度学习的办法减轻工程特征的负担,但我们的原始数据的本质并不容易直接输入到前馈神经网络中。 我们仍然花费大量的工程资源将用户和视频数据转换为有用的特征。 主要挑战在于表示用户行为的几个序列、以及这些行为、如何与正在评分的视频相关联。
我们观察到最重要的信号是描述用户之前与item本身和其他类似item的交互的信号,这个经验与其他人在排名广告中的经验相类似[7]。 例如,考虑用户过去使用上传视频得分的频道的历史记录 - 用户在此频道观看的视频数量是多少? 用户最后一次观看有关此主题的视频是什么时候? 描述过去用户对相关项目的操作的这些连续功能特别强大,因为它们可以在不同的项目中很好地概括。 我们还发现,将召回视频的排序结果当成特征是至关重要的,例如: 这个视频候选是来自哪个来源? 他们分配了什么分数?
描述过去视频频率的特征,对于在推荐中引入“流失”也是至关重要的(如果用户连续请求的话,就不会返回相同的列表,这就叫做负反馈)。 如果用户最近推荐了一个视频,但没有观看,那么该模型会在下一页加载时自然降低这种视频的排名。 提供最新的印象和观看历史是本文范围之外的工程专长,但对于制作响应性建议至关重要。
与候选生成类似,我们使用嵌入方法,将稀疏的类别特征映射到适合神经网络的dense表示,也就是将一连串的类别特征表征成一个比如128维度的特征。 每个唯一的ID空间(“词汇表”)都有一个单独的学习嵌入,其维度大致与这个特征去重后的数量的对数成比例增加。 这些词汇表是通过在训练之前过了一遍训练集而建成的一个look up table。 非常大的基数ID空间(例如视频ID或query词)通过在按照点击次数排序后,然后取top N进行截断。 词典外值简单地用全1标书。 与候选生成一样,多类别特征在送到前馈网络之前也被平均成一个embedding向量。
重要的是,同一ID空间中的类别特征也共享底层的emeddings。 例如,(曝光的视频ID,用户观看的最后几个视频ID,算法人推荐的视频ID等)这些都公用一个全局的embedding。 尽管使用了共享嵌入,但每个功能都会单独输入到网络中,以便上面的层可以学习每个功能的专用表示。 共享嵌入对于改进泛化,加快训练和减少内存需求非常重要。 绝大多数模型参数都被这样嵌入在空间中 - 例如,嵌入在32维空间中的一百万个ID,具有比2048个unit的全连接的层多7倍的参数。
归一化连续特征
众所周知,神经网络对其输入数据的缩放和分布非常敏感[9],而诸如决策树集合之类的替代方法对于单个特征的缩放是不变的。 我们发现连续特征的正确归一化对于收敛是至关重要的。 一个具有分布f的连续特征x,使用累计分布的方式,通过缩放值以使特征均匀分布在[0,1],最后被转换为x1,x1 = 从负无穷积分到x的积分值。在训练开始之前,在数据上单次计算的特征值的分位数上对该积分近似进行线性插值。
除了原始归一化特征x1之外,我们还输入x1的平方或者对x1取开方,通过允许网络轻松形成特征的超线性和子线性函数,使网络具有更强的表现力。 我们发现,这样做的连续特征可以提高离线精度。
我们的目标是预测预期用户的观看时间,因为训练示例要么是正样本(点击曝光给用户的样本),要么是负样本(没有点击)。 正面样本和用户观看视频所花费的时间相关。 为了预测预期的观察时间,我们使用加权逻辑回归技术,该技术是为此目的而开发的。
该模型采用交叉熵损失的逻辑回归进行训练(图7)。 但是,正样本(点击样本)会由用户的观看时间加权该视频。 负样本(未点击)将只有单位1的权重。 通过这种方式,逻辑回归学到的可能性是
N是训练集样本数,一般在几千万,K是正样本数,Ti是第i次曝光的观看时间。
假设正样本的得分很小(在我们的业务中是正确的),学习到的几率大约为 E[T ](1 + P ),P是点击概率,E[T]这个曝光样本的期待观看时间。因为P很小,导致这个 计算公式接近于 E[T]。也就意味着,我们可以使用 冥函数 e的x次方,当做最后的激活函数来处理这个可能性。
表1显示了我们在次日数据上试验了不同的隐藏层units数的结果。 通过考虑在单个页面上向用户显示的正(单击)和负(未单击)现象来获得针对每个试验显示的值(“加权,每用户损失”)。 我们首先使用我们的模型对这两个现象进行评分。 如果负样本得分高于正样本,那么我们认为正样本观看时间被错误预测了。 然后,加权每用户损失为错误预测观看时间的总量,作为总观看时间的一小部分而不是保持正负对。
这些结果表明,增加隐藏层的宽度可以改善结果,增加深度也是如此。 然而,也要服务器CPU时间。 配置1024个宽的ReLU,然后是512宽的ReLU,然后是256个宽的ReLU,这使我们得到了最好的结果,同时使我们能够保持在我们的服务CPU预算范围内。
对于1024→512→256模型,我们尝试仅仅在这些特征下,进行归一化,而不加入他们的平方或者开方,就输入前馈网络,这增加了0.2%的损失。 使用相同的隐藏层配置,我们还训练了一个模型,其中正负样本同等加权。 不出所料,这使视频观看时间加权损失增加了4.1%。
表1:更宽和更深的隐藏ReLU层对观看时间加权成对损失的影响,一直在第二天的数据上试验
我们已经描述了用于推荐YouTube视频的深度神经网络架构,分为两个不同的问题:召回和精排。
我们的深度协同过滤模型能够有效地吸收许多信号并模拟它们与深度层的交互,优于YouTube上先前使用的矩阵分解方法[23]。 在为推荐选择替代问题时,艺术比科学更多,我们发现通过捕捉不对称的共同观察行为并防止未来信息泄露,对未来的视频进行分类,以便在线上指标上表现良好。 降低来自分类器的错误信号对于获得良好结果也是必不可少的 - 否则该模型会过度填充代理问题而不能很好地转移到主页。
我们证明了使用训练样本中的视频上传时间长短作为输入特征,消除了对过去上传视频的偏向,并允许模型向新的流行视频进行加权。 这种改进的离线保持精度可以显着提高最近上传的A / B测试视频的观看时间。
排名是一种更经典的机器学习问题,我们的深度学习方法优于先前的线性和基于树的观察时间预测方法。 推荐系统特别受益于描述过去用户对item行为的特征。 深度神经网络需要分类和连续特征的特殊表示,我们分别用嵌入和分位数归一化进行变换。 显示深度层有效地模拟了数百个特征之间的非线性相互作用。
Logistic回归通过加权训练样本,进行了修改,其中包括正样本的观看时间和正样本的统一性,这使我们能够了解与预期观看时间密切相关的几率。 与直接预测点击率相比,此方法在观看时间加权排名评估指标上表现更好。
作者要感谢Jim McFadden和Pranav Khaitan提供宝贵的指导和支持。 Sujeet Bansal,Shripad Thite和Radek Vingralek实施了培训和服务基础设施的关键组成部分。 Chris Berg和Trevor Walker提供了深思熟虑的讨论和详细的反馈。