YouTube采样修正的双塔模型论文精读
共 11969字,需浏览 24分钟
·
2021-07-26 17:52
「本文概览」
《Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations》是谷歌在2019年的RecSys上发表的一篇非常具有工业风的论文,介绍了在大规模推荐系统中使用双塔模型来做召回的一些经验,值得细细品读。
1. 这篇文章要解决什么问题?
大规模推荐系统一般分为两个阶段,即召回和排序阶段。本文的重点就在于为一个有百万量级物品的个性化推荐构建一个召回系统。
给定{用户,上下文,物品}的三元组,召回模型通用的方法是:
1)分别计算{用户,上下文} 和 {物品} 的向量表示; 2)利用一个简单的打分函数(例如点积)来计算二者的匹配得分。
“上下文”通常是有动态性质的变量,例如一天里的时间、用户的设备等等。这种基于表示学习的方法通常面临两个方面的挑战:
1)工业级推荐系统的物品集通常很大; 2)从用户反馈中收集的训练数据通常很稀疏,导致对长尾内容的预测过拟合。对于cold-start问题,推荐系统需要适应数据分布的变化来更好地推荐新内容(fresh content)。
工业界现有的推荐系统都需要从一个超大规模的候选集中拉取item进行打分排序。解决数据稀疏和大规模候选集分布的一种通用做法是从item的内容特征中学习出item的稠密表示。这里很自然地就想到了工业界大名鼎鼎且应用广泛的双塔神经网络结构,其中的一塔就是从丰富的item内容特征中学习到item的表示。双塔网络结构如下所示:
上图中双塔模型两侧分别对 {用户,上下文} 和 {物品} 进行建模,并在最后一层计算二者的内积。模型训练好后用图中的两个向量 和 求dot,对相似度高的item做推荐。其中分两部分:左侧user塔后面的user embedding需要在请求来的时候实时计算;右侧item塔训练的时候预计算好,然后灌入一个向量检索工具中,首先建立索引,然后转化为一个向量检索问题,这方面基本做推荐的各家大公司都有自己的开源工具,比如faiss,annoy等。
YouTube将视频召回看做一个多分类问题,多分类问题中最常使用的激活函数就是Softmax,但是要知道YouTube上视频素材库中的视频数量是巨大的,当类别数量特别大时,使用Softmax来训练模型是比较耗时的。所以一种常用的方法就是进行采样,工业界目前采用流式训练双塔结构一般是通过随机mini-batch内负采样的方式来优化损失函数。这种训练方式存在的一个显著问题就是in-batch loss会因为随机采样偏差而导致模型效果不好,尤其是当样本分布出现明显倾斜的时候。这种batch内负采样的方法具有采样偏差,无法保证采样后的分布和原始数据分布是一样的,这样模型学习到的将会是错误的分布从而影响模型的效果。
为此,作者一方面对损失函数进行了改进(加权对数似然函数),另一方面提出了一种对采样概率进行自适应修正的算法,可以从流式数据中预估item的频率。通过理论分析和实验结果表明,该算法有能力在不知道候选集全部的词典情况下做出无偏差的估计并且可以自适应候选集分布的变化。随后,作者采用了这种“采样偏差修正”的方法为 YouTube 建立了一个基于神经网络的大型检索(召回)系统,该系统用于从包含数千万个视频的语料库中提供个性化服务。
Microstrong在尝试采用流式训练数据做双塔召回时,思考以下问题:
流式训练中,batch内随机负采样效果不佳,如何能拿到item的出现频次,做Negative Sampling呢?我们知道流式训练,训练数据是以滚动的方式输入到网络模型中的,我们无法维护一个动态且占高内存的词表及item频次信息。如果无法拿到item出现的频次,就不能准确的进行负采样操作。 在batch内如何采样,才能使用batch softmax 损失函数呢?召回场景下batch softmax与交叉墒相比,优势在哪里? 当我们进行batch内负采样的时候,item被采作负样本的概率约等于其出现在原始样本中的概率。这样会导致一些热门的受欢迎的item更容易被当成负样本。而在大多数推荐场景中有很明显的热点效应,对于这些热门item的过度打压会使得模型倾向于推荐一些冷门的item,从而影响线上表现。是否可以使用这篇论文提出的修正loss解决此问题呢?
以上三个问题,都促使我精读Google在YouTube视频推荐中具有落地指导意义的这篇论文。
2. 用了什么方法解决?
2.1 采样概率修正
整个召回系统采用的是双塔结构,即分别构建用户侧的Embedding和视频侧的Embedding,两个塔的输出就是各自的embedding向量,最终模型的输出为两个Embedding内积后的结果,即:
假设有 条训练样本,模型的目标是从这些训练样本中学习模型参数 ,即:
其中, 表示用户特征和上下文特征, 表示物品特征, 表示每条样本的回报,比如文章的阅读时长、视频的播放比例等。
这篇论文将视频召回看做一个多分类的问题,通常各个类别的权重都为 ,但是在该场景中,论文中引入了一个用户偏好的权重 (用户观看某视频的播放比例)。给定一个用户 ,从 个物品的候选集 中选择要推荐的物品。这是一个多分类问题,将模型的输出经过一个Softmax函数之后得到具体对应的类别概率,多分类Softmax函数定义如下:
基于上述Softmax函数的输出和用户偏好权重,损失函数采用加权对数似然函数的形式,具体如下:
「接下来就是这篇论文的第一个核心点了」,上述的做法相当于把该样本中的 作为正样本,其余所有的物品当作负样本。当视频素材库的视频数量巨大时( 非常大),计算上述的Softmax函数是十分低效且不太现实的。一种通用的做法是通过随机mini-batch的方式来优化损失函数。假设一个包含 条数据的mini-batch,那么对于任意一条数据,Softmax计算公式如下:
这种做法相当于把一个batch中此条数据之外物品当作负样本。但是这种做法存在的缺点就是会因为随机采样偏差而导致模型效果不好。对于热门物品来说,由于采样到的概率非常高,当作负样本的次数也会相应变多,热门物品会被“过度惩罚”。所以论文对user和item的embedding向量计算得到的内积 进行了logQ修正,即:
上式中, 代表第 条样本对应的物品 在一个mini-batch中被采样到的概率。这里埋下一个伏笔, 如何计算呢?这在下一节会详细介绍。基于此修正的内积,得到修正后的Softmax函数的输出:
以及修正后的损失函数如下所示:
然后利用优化器SGD进行参数的更新。具体的模型训练算法如下所示:
「上述模型训练过程可以归纳为:」
从实时数据流中得到一个batch的样本; 基于下文即将提到的采样概率估计算法得到采样概率 ; 计算上文介绍的修正后的损失函数; 利用SGD更新模型参数;
2.2 Streaming Frequency Estimation
「这篇论文的第二个核心问题是如何得到 和 设计一个算法维护更新 。」 上文中提出的采样概率修正方法,核心思想在于通过采样频率来估计采样概率,如果某个item的采样频率为 ,则其采样概率为 ,按照这样的想法, 的定义为:
其中, 代表什么呢? 又是一个怎么的函数呢?这里我猜测 肯定代表 的采样频率,带着这些问题,我们接着看 到底是如何计算的。
由于YouTube中采用流式训练,因此不断会有新物品出现,那么使用固定长度的词表不太合适,因此采用 的方式来对物品的采样概率 进行更新。
具体来说,首先定义一个 函数 ,把所有视频 都映射到 之间。这里 一下是因为视频是动态的,随时都可能有新的视频进入系统,所以用 函数映射一下固定住视频库大小。同时使用两个长度为 的数组 和 ,通过 来得到给定的 在数组 和 中下标。
: 表示 上一次被采样的step; : 表示 平均多少个step被采样一次,即采样频率。这里频率的意思是预估每过多少步可以被采样到一次,那么倒数就是预估被采样到的概率。
当第 步物品 被采样到,基于如下的公式更新 :
其中, 则被赋予当前的训练步数 。当训练完成时,预估的物品 的采样概率是 。从数组 的定义可以看出, 越小,即在训练样本中采样到的概率越高,比如 ,每两次就会被采样到一次,那么 会比较大,就代表比较热门。接着就是更新 ,其中 可看作学习率,剩下的就是带入到损失函数 中梯度下降求解的过程了。
这里还有一个问题,既然是 过程,当 时,就会存在冲突的情况。冲突的情况会导致 较小,因为 会较小,从而导致采样概率预估过高。这里的改进方案是使用Multiple Hashings
。即使用多组 方程和数组 、 。当训练完成后,在线推理时,使用最大的一个 去计算采样概率。
当然论文里还给出来了"Streaming Frequency Estimation"算法的分布式计算方法,这里把用于估计流式数据中,每个batch下item被采样的概率的算法引申到深度学习的分布式训练中,真的是把这个算法运用到工业中落地的细节也讲到了,想详细了解这一块的知识可以读原论文。
这里说到分布式训练模型,我就想给大家聊一下分布式训练在工业界的重要性。我们都知道,现在稍微复杂的业务,都是分布式训练模型的。这里我必须要强调一下,在工业界中大规模分布式推荐算法工程师的一些必备技能:
「对分布式框架的理解。」 掌握分布式训练这个技能非常重要,比如Tensorflow框架中的ps/worker/chief是怎么协同工作的,参数更新在哪里,模型训练在哪里,模型同步训练还是异步训练,分布式训练框架通信问题等等。 「PySpark/Scala的熟练使用。」 Spark是非常强大的处理大规模数据的工具,为模型准备训练数据非常方便,与Hive SQL的交互也十分方便。因此熟练使用Pyspark、Scala处理大规模训练数据非常的重要。 「Hive SQL。」 这是工作中使用频次很高的语言,推荐算法工程师有时也需要从大规模数据中使用Hive SQL发现问题、分析问题。这也是我们常说的推荐算法工程师要有强烈的数据敏感性。
2.3 一些Tricks
(1)「最近邻搜索」:当Embedding映射函数 (user塔或query塔)和 (item 塔)学习好后,在线预测包含两步:
计算query的向量 ; 从事先训练好的函数 中得到所有item的Embedding向量,然后采用近邻搜索的方法用user Embedding找到最邻近的item Embedding。
在实际工程中用双塔模型做大规模物品召回,item塔产出的item Embedding得先灌入faiss中。线上实时得到user Embedding,然后去faiss中计算相似度,实现u2i召回。
(2)「归一化」:经验表明,对两侧输出的Embedding进行 归一化效果更好,即:
(3)「对于内积计算的结果,除以一个固定的超参 」:
除以超参的效果是把Softmax的结果变得更加明显(sharpen),通过对超参 的微调可以使召回率或精确率变的更好。这里温度 和知识蒸馏中温度超参的出现位置和作用是一样的。关于温度超参 的详细解释请看我的这篇文章:
深度学习中的知识蒸馏技术(上),地址:https://mp.weixin.qq.com/s/E7-MF18Y-UeKx694kGFHzA
3. 模型结构与线上部署
实际中的YouTube双塔到底是怎么用的?整个召回的模型网络如下图所示:
将模型分为两个塔,查询塔(包含上下文特征和用户特征)和物料塔,这个模型使用大量的seed video特征和用户观看历史来训练模型。seed video features 是指用户正在观看的视频所具有的属性,某种程度上表征了用户当前的兴趣。
3.1 训练标签
点击视频为正样本。 是一个乘到每个样本的 上的加权系数,论文中解释这个系数代表播放进度,如果 秒视频看了 秒则 ,加权的初衷是播放进度越长则表明喜好程度越大,配上点击 则更强地表达了偏好。
「这里引申出一个问题:在视频推荐场景中的召回阶段,用论文中定义的含加权 的 是否是最优解?」
这里我觉得可以换个思路尝试一下,因为像视频推荐场景我们可能会用完播/播放百分比/播放时长等目标,完播、播放百分比往往会偏好短视频,播放时长会偏好长视频,一般都需要做消偏处理,把点击目标和播放百分比目标结合到一起反倒是不好消偏了。而且这种召回有点不伦不类,线上召回本身就是多路,完全可以将一路召回拆成点击召回和播放召回两种单独做优化,更能体现召回的本质——从多个角度初筛可能感兴趣的候选。
「更近一步的考虑另外一个问题:像视频推荐场景我们可能会用完播/播放百分比/播放时长等目标,完播往往会偏好短视频,播放时长会偏好长视频,那么也需要做debias,有没有什么好办法来消偏呢?」
方法就是统计后验的指标做消偏,即不是对长视频加权,是对该视频消费时长减去相同时长视频大盘消费时长,对diff加权。
3.2 视频特征
视频特征有诸如视频id、频道id之类的类别特征,也有连续特征。类别特征分为单值类别特征(如 video id)和多值类别特征(如 video topic)。单值类别特征,视频id、频道id等特征转化为embedding,对于多值类别特征,采用对其多值embedding加权求和的方式得到最终的embedding。
这里的channel id不是指的体育/美食这种频道,而是类似于作者id的东西,理由是打开每个视频的作者,其url链接是http://www.youtube.com/channel/***。
3.3 用户特征
用户特征主要是基于用户的历史观看记录来捕获用户的兴趣,比如说,用户最近看过 个视频的embedding的平均值来刻画用户兴趣。
对于ID型的类别特征,embedding在模型的两侧是共享的。比如,视频id,两个塔进行共享,更好的学习,保证两个塔在一个空间内。
「这里再抛出一个问题:video id共享embedding的原因是什么,共享是最优解吗?」
模型结构图中有多处用到了video id,比如用户观看历史/正在看的seed video/候选集合。由于都是一个video id的embedding,很容易想到share embedding。我认为这个insight初衷应该是两个,其一能够降低ps存储压力,其二是让embedding学习得更加充分。YouTube实验发现share与否对结果没啥影响,那干脆share还能减资源。
我自己一直都是把能share embedding的ID类特征尽量share embedding,以避免线上服务模型太大,造成线上更新耗时太多的问题。但是,@iwtbs 在文章《借Youtube论文,谈谈双塔模型的八大精髓问题》(地址:https://zhuanlan.zhihu.com/p/369152684)中提到自己的经验是share embedding会让预估效果变差,因为严格意义上来说并不完全是一个空间,所以这个点他持怀疑态度。最终要不要share还是得自己试试才知道,即使效果好也要考虑效果和存储资源trade-off的问题。
3.4 在线服务
模型基于Tensorflow实现,并且进行了分布式实现。同时,YouTube 每天都会生成新的训练数据集,模型也会以天为单位进行更新,这样模型便能适应最新的数据分布变化。
infer阶段就跟普通的DNN召回类似,将全量的视频的embedding计算好,然后线上实时生成查询塔的embedding,通过faiss等工具进行topK的查询。
通过双塔的结构和采样校正,YouTube实现了又快又准的召回,YouTube双塔召回同样也运用在广大公司的线上业务中,并且效果还不错。这里列举一些工业界的实践案例:
向量化召回在360信息流广告的实践 - 被包养的程序猿丶的文章 - 知乎 https://zhuanlan.zhihu.com/p/93257390 [58同城]深度召回在招聘推荐中的挑战和实践,地址:https://mp.weixin.qq.com/s/mcETNOICbabRRq9BBdL4zw
4. 效果如何?
论文的实验部分向我们展示了item frequency estimation算法和建模框架的有效性,离线和在线的评估结果都有提升。总的来说,这篇文章便于实现,可以从字里行间看到很多实践出真知的影子,也是对经典知识在实践中改进的例子,是一篇工程性很强的文章。
5. 总结
论文详细介绍了工业界应用双塔DNN模型解决大规模视频召回场景下的问题,详细介绍了双塔模型在使用时的一些 Tricks,包括流式数据处理中的采样概率修正,使用 等技术来提高检索效率,Embedding归一化提高准确率,加入超参 来微调召回率和精确率。相信很多人对双塔DNN模型并不陌生,也有很多公司实际在这么做,但是文章中提到的很多细节问题可能是我们平时所忽略的,比如对embedding进行归一化处理、对embedding内积引入修正系数、线上如何进一步提高检索效率等。总的来说,还是一篇比较值得细品的论文。
最后,借此机会我们来回顾YouTube的三篇重要的实践论文:
(1)首先是YouTube的深度学习开山之作《Deep Neural Networks for YouTube Recommendations》,这是深度学习在推荐领域的首次工业应用,这篇文章野心很大,将召回和排序都囊括进整篇论文。关于这篇论文的解读,推荐大家读以下两篇文章:
重读Youtube深度学习推荐系统论文,字字珠玑,惊为神文 - 王喆的文章 - 知乎 https://zhuanlan.zhihu.com/p/52169807 YouTube深度学习推荐系统的十大工程问题 - 王喆的文章 - 知乎 https://zhuanlan.zhihu.com/p/52504407 (2)其次是YouTube的双塔召回《Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations》,进一步优化解决召回的冷启动、长尾等问题。
(3)最后是MMoE的应用文章《Recommending What Video to Watch Next: A Multitask Ranking System》,该论文主要聚焦于大规模视频推荐中的排序阶段,介绍一些比较实在的经验和教训,涉及到对多个目标进行建模和解决 Selection Bias这两个排序系统的关键点。关于这篇论文的详细解读,推荐大家阅读这篇文章:
多目标学习在推荐系统中的应用,地址:https://mp.weixin.qq.com/s/c7BdWUM9BFQZfzWP7C_wfQ
可以看到,这三篇论文代表了推荐系统中最重要的两个模块——召回和排序的演进,在搭建推荐系统的过程中,也可参照这个流程去搭建适合自己业务的框架。
6. 关于这篇论文的若干问题的思考
在文章开头部分,我提出了自己在尝试采用流式训练数据做双塔召回时,思考的三个问题,现在尝试一下自己给自己答疑。
(1) 流式训练中,batch内随机负采样效果不佳,如何能拿到item的出现频次,做Negative Sampling呢?我们知道流式训练,训练数据是以滚动的方式输入到网络模型中的,我们无法维护一个动态且占高内存的词表及item频次信息。如果无法拿到item出现的频次,就不能准确的进行负采样操作。
「引申出问题:要回答这个问题,我们首先需要清楚召回阶段为什么需要采样?以及现在流行的采样方法有哪些?batch内随机负采样到底是如何做的?」
这个问题的答案来源于:SENet双塔模型:在推荐领域召回粗排的应用及其它 - 张俊林的文章 - 知乎 https://zhuanlan.zhihu.com/p/358779957
我们训练精排模型的时候(假设是优化点击目标),一般会用“用户点击”实例做为正例,“曝光未点击”实例做为负例,来训练模型,基本大家都是这么做的。现在,模型召回以及粗排,也需要训练模型,意思是说,也需要定义正例和负例。一般正例,也都是用“用户点击”实例做为正例,但是怎么选择负例,这里面有不少学问。
我们先来看下不同阶段模型面对的输入数据情况,对于召回模型来说,它面临的输入数据,是所有物料库里的物品;对于粗排模型来说,它面对的输入数据,是各路召回的结果;对于精排模型来说,它面临的输入是粗排模型的输出结果。如果我们仍然用“曝光未点击”实例做为召回和粗排的负例训练数据,你会发现这个训练集合,只是全局物料库的一小部分,它的分布和全局物料库以及各路召回结果数据差异较大。即,召回和粗排模型面临的实际输入数据与采用“曝光未点击”实例做为负例训练数据,分布差异比较大。所以根据这种负例训练召回和粗排模型,效果如何就带有疑问,我们一般把这个现象称为“Sample Selection Bias”问题。
为了解决“Sample Selection Bias”问题,我们在召回或者粗排模型训练的时候,应该调整下负例的选择策略,使得它尽量能够和模型输入的数据分布保持一致。这里 @张俊林(知乎ID)老师简单归纳下可能的做法。
「选择1: 曝光未点击数据」
这就是上面说的导致Sample Selection Bias问题的原因。我们的经验是,这个数据还是需要的,只是要和其它类型的负例选择方法,按照一定比例进行混合,来缓解Sample Selection Bias问题。当然,有些结论貌似是不用这个数据,所以用还是不用,可能跟应用场景有关。
「选择2: 全局随机选择负例」
就是说在原始的全局物料库里,随机抽取做为召回或者粗排的负例。这也是一种做法,YouTube DNN双塔模型就是这么做的。从道理上讲,这个肯定是完全符合输入数据的分布一致性的,但是,一般这么选择的负例,因为和正例差异太大,导致模型太好区分正例和负例,所以模型能学到多少知识是成问题的。
「选择3: Batch内随机选择负例」
就是说只包含正例,训练的时候,在Batch内,选择除了正例之外的其它Item,做为负例。这个本质上是:给定用户,在所有其它用户的正例里进行随机选择,构造负例。它在一定程度上,也可以解决Sample Selection Bias问题。比如Google的双塔召回模型,就是用的这种负例方法。
「选择4: 曝光数据随机选择负例」
就是说,在给所有用户曝光的数据里,随机选择做为负例。这个我们测试过,在某些场景下是有效的。
「选择5: 基于Popularity随机选择负例」
这种方法的做法是:全局随机选择,但是越是流行的Item,越大概率会被选择作为负例。目前不少研究证明了,负例采取Popularity-based方法,对于效果有明显的正面影响。它隐含的假设是:如果一个例子越流行,那么它没有被用户点过看过,说明更大概率,对当前的用户来说,它是一个真实的负例。同时,这种方法还会打压流行Item,增加模型个性化程度。
「选择6: 基于Hard选择负例」
它是选择那些比较难的例子,做为负例。因为难区分的例子,很明显给模型带来的 和信息含量比较多,所以从道理上讲是很合理的。但是怎样算是难的例子,可能有不同的做法,有些还跟应用有关。比如Airbnb,还有不少工作,都是在想办法筛选Hard负例上。
以上是几种常见的在召回和粗排阶段选择负例的做法。
「正式回答自己提出问题:」 看到这里这个问题就相对简单了,论文提出的“Streaming Frequency Estimation”算法,不就是为了解决流式训练中,没有固定的词表,得不到item的频次信息,而提出的预估item采样频率的算法么。在流式训练中可以直接抛弃Negative Sampling算法,采用“Streaming Frequency Estimation”算法。
(2)在batch内如何采样,才能使用batch softmax 损失函数呢?召回场景下batch softmax与交叉熵相比,优势在哪里?
「回答第一小问:」 上面提到的“Batch内随机选择负例”的办法,就可以直接使用batch softmax 损失函数。
「回答第二小问,答案来源于」:借Youtube论文,谈谈双塔模型的八大精髓问题 - iwtbs的文章 - 知乎 https://zhuanlan.zhihu.com/p/369152684
交叉熵实际上就是建模为二分类问题,这种兴趣绝对值是point-wise。召回本身需要负采样,在不构建hard-negative情况下流式训练一般维护一个实时更新的他人正例采样池,如果负样本难度不够大(往往都不够大)其实最后auc会学得很高,拟合效果未必学的好;而精排由于是准确的正负样本用二分类刚刚好。
batch softamx则是把batch内的所有样本作为彼此的负样本,这种采样的方式强依赖于batch的分布,会带来非常大的bias。batch softmax建模的是相对兴趣pair-wise,但是还是同样的问题,负样本过于简单比较相对兴趣也没特别大意义?而且看很多人都提到在推荐领域用pair-wise不如point-wise,搜索用pair-wise更好,所以之前我也一直没试,相比较margin hinge loss这种方式多加了一个阈值更说得通。
(3)当我们进行batch内负采样的时候,item被采作负样本的概率约等于其出现在原始样本中的概率。这样会导致一些热门的受欢迎的item更容易被当成负样本。而在大多数推荐场景中有很明显的热点效应,对于这些热门item的过度打压会使得模型倾向于推荐一些冷门的item,从而影响线上表现。是否可以使用这篇论文提出的修正 解决此问题呢?
答:由于大多数推荐场景的物品都服从长尾分布,因此在batch内负采样的时候,对于热门物品来说,由于采样到的概率非常高,当作负样本的次数也会相应变多,热门物品会被“过度惩罚”。所以论文对user 和 item的 embedding向量计算得到的内积 进行了logQ修正,可以使用这篇论文提出的修正 解决此问题。
7. Reference
【1】借Youtube论文,谈谈双塔模型的八大精髓问题 - iwtbs的文章 - 知乎 https://zhuanlan.zhihu.com/p/369152684
【2】【百家争鸣】YouTube,地址:https://mp.weixin.qq.com/s/KHsJk_NZZvBY6qOUh-QdRg
【3】谷歌最新双塔DNN召回模型——应用于YouTube大规模视频推荐场景 - 被包养的程序猿丶的文章 - 知乎 https://zhuanlan.zhihu.com/p/128988454
【4】【推荐系统经典论文(九)】谷歌双塔模型 - 努力搬砖的小李的文章 - 知乎 https://zhuanlan.zhihu.com/p/137538147
【5】Youtube2019双塔召回论文精读,地址:http://yougth.top/2021/02/01/2019Recsys%E5%8F%8C%E5%A1%94%E5%8F%AC%E5%9B%9E%E8%AE%BA%E6%96%87%E7%B2%BE%E5%BA%A6/
【6】RS Meet DL(72)-[谷歌]采样修正的双塔模型,地址:https://cloud.tencent.com/developer/article/1556169
【7】 youtube 双塔模型 ,地址:http://d0evi1.com/youtube-2tower/
【8】【CTR】Youtube:双塔召回模型,地址:https://mp.weixin.qq.com/s/G-8eqvQyG480HOv9eQbPqA
【9】推荐系统中的debias算法 - iwtbs的文章 - 知乎 https://zhuanlan.zhihu.com/p/369948358
【10】 深度召回在招聘推荐中的挑战和实践,地址:https://mp.weixin.qq.com/s/mcETNOICbabRRq9BBdL4zw
【11】推荐算法岗是否存在严重人才过剩? - 阿里巴巴淘系技术的回答 - 知乎 https://www.zhihu.com/question/320805246/answer/1906346931
【12】SENet双塔模型:在推荐领域召回粗排的应用及其它 - 张俊林的文章 - 知乎 https://zhuanlan.zhihu.com/p/358779957