1.背景
DSSM是Deep Structured Semantic Model (深层结构语义模型) 的缩写,即我们通常说的基于深度网络的语义模型,其核心思想是将query和doc映射到到共同维度的语义空间中,通过最大化query和doc语义向量之间的余弦相似度,从而训练得到隐含语义模型,达到检索的目的。DSSM有很广泛的应用,比如:搜索引擎检索,广告相关性,问答系统,机器翻译等。DSSM主要用在召回和粗排阶段。 在应⽤于推荐系统时,通过两个塔分别去建模user侧和item侧的embedding,计算embedding之间 的内积,最后⽤真实的label计算loss。
论文题目:《Learning Deep Structured Semantic Models for Web Search using Clickthrough Data》
2.DSSM模型结构
论文中的 DSSM的模型, 考虑一个搜索的场景, 在输入一个Query之后, 要在众多的Doc中寻找最为匹配的项, 那么此时如果将Query经过某种模型, 得到其向量表示, 再与Doc对应的向量进行相似度计算, 将相似度高的进行返回, 即可完成匹配。 主要是⽤来解决NLP领域语义相似度任务, 如果把document换成item或是⼴告,就演变成了⼀个推荐模型。
从模型上来看, x x x 是用来表示输入的term向量, y y y 是经过DNN后的输出向量;DSSM模型的整体结构中,Q代表Query信息,D表示Document信息。
- Term Vector:表示文本的Embedding向量;
- Word Hashing技术:为解决Term Vector太大问题,对bag-of-word向量降维;
- Multi-layer nonlinear projection:表示深度学习网络的隐层;
- Semantic feature :表示Query和Document 最终的Embedding向量;
- Relevance measured by cosine similarity:表示计算Query与Document之间的余弦相似度
- Posterior probability computed by softmax:表示通过Softmax 函数把Query 与正样本Document的语义相似性转化为一个后验概率
典型的DNN结构是将原始的文本特征映射为在语义空间上表示的特征。DNN在搜索引擎排序中主要有2个作用:
- 将query中term的高维向量映射为低维语义向量
- 根据语义向量计算query与doc之间的相关性分数
从推荐系统角度看DSSM模型:
双塔模型结构简单,一个user塔(用户侧特征–用户画像信息、统计属性以及历史行为序列等),另一个item塔(Item相关特征–Item基本信息、属性信息等),两边的DNN结构最后一层(全连接层)隐藏单元个数相同,保证user embedding和item embedding维度相同,后面相似度计算(如cos内积计算),损失函数使用二分类交叉熵损失函数。DSSM模型无法像deepFM一样使用user和item的交叉特征。
3.DSSM模型离线训练流程
召回阶段一般用到的特征有三种:
内容 | |
---|---|
user特征 | user ID、用户基础属性信息(性别、年龄、地域等)、用户画像信息、用户的各种session信息等等 |
item特征 | item ID、item基础属性信息(发布日期、作者ID、类别等)、item的画像、item创作者画像等等 |
上下文特征 | 当前时间戳、手机类型、网络类型、星期几等等 |
离线训练双塔召回模型时,将user特征和上下文特征concat起来,作为user塔的输入。将item特征concat起来,作为item塔的输入。
双塔召回模型的离线训练步骤为:
- 将用户侧的特征concat起来,输入一个DNN网络中,最终得到一个user embedding;
- 将物品侧的特征concat起来,输入一个DNN网络中,最终得到一个item embedding;
- 拿user embedding与item embedding,做点积或cosine,得到logit,代表user和item之间的匹配程度;
- 设计loss训练模型,一般loss都选择weighted cross entropy loss或Focal loss,这些loss都是point wise方法。
双塔召回模型的线上预测步骤为:
- 离线刷可推荐item库得到item embedding,具体做法为:离线的、周期性的、批量的将item特征输入item塔,得到item embedding。把得到的item embedding导入Faiss中,建立索引。
- 线上实时得到用户的user embedding,具体做法为:当用户线上请求后,将user特征和上下文特征输入user塔,得到user embedding。
- 拿到的实时user embedding到Faiss中做近邻搜索(ANN),得到与user embedding相邻的Top N个item集合,作为召回内容返回。
4.思考
Q: DSSM 就一定适合所有的业务吗
- DSSM 是端到端的模型 ,虽然省去了人工特征转化、特征工程和特征组合,但端到端的模型有个问题就是效果不可控。
- DSSM 是弱监督模型,因为引擎的点击曝光日志里 Query 和 Title 的语义信息比较弱。 大部分的用户进行点击时越靠前的点击的概率越大,而引擎的排序又是由 pCTR、CVR、CPC 等多种因素决定的。从这种非常弱的信号里提取出语义的相似性或者差别,那就需要有海量的训练样本。
Q:DSSM模型做召回时的正负样本选择?
正样本:曝光给用户并且用户点击的item;
负样本: 从全量候选item中召回,而不是从有曝光的item中召回
召回负样本构造是一门学问,常见的负样本构造方法有( 摘自张俊林大佬文章,SENet双塔模型:在推荐领域召回粗排的应用及其它,关于负样本构造方法总结的非常棒 ):
- 曝光未点击数据 导致Sample Selection Bias(SSB)问题的原因。我们的经验是,这个数据还是需要的,只是要和其它类型的负例选择方法,按照一定比例进行混合,来缓解Sample Selection Bias问题。当然,有些结论貌似是不用这个数据,所以用还是不用,可能跟应用场景有关。
- 全局随机选择负例 就是说在原始的全局物料库里,随机抽取做为召回或者粗排的负例。这也是一种做法,Youtube DNN双塔模型就是这么做的。从道理上讲,这个肯定是完全符合输入数据的分布一致性的,但是,一般这么选择的负例,因为和正例差异太大,导致模型太好区分正例和负例,所以模型能学到多少知识是成问题的。
- Batch内随机选择负例 训练的时候,在Batch内,选择除了正例之外的其它Item,做为负例。这个本质上是:给定用户,在所有其它用户的正例里进行随机选择,构造负例。它在一定程度上,也可以解决Sample Selection Bias问题。比如Google的双塔召回模型,就是用的这种负例方法。
- 曝光数据随机选择负例 在给所有用户曝光的数据里,随机选择做为负例。这个我们测试过,在某些场景下是有效的。
- 基于Popularity随机选择负例 全局随机选择,但是越是流行的Item,越大概率会被选择作为负例。目前不少研究证明了,负例采取Popularity-based方法,对于效果有明显的正面影响。它隐含的假设是:如果一个例子越流行,那么它没有被用户点过看过,说明更大概率,对当前的用户来说,它是一个真实的负例。同时,这种方法还会打压流行Item,增加模型个性化程度。
- 基于Hard选择负例 它是选择那些比较难的例子,做为负例。因为难区分的例子,很明显给模型带来的loss和信息含量比价多,所以从道理上讲是很合理的。但是怎样算是难的例子,可能有不同的做法,有些还跟应用有关。比如Airbnb,还有不少工作,都是在想办法筛选Hard负例上。
新浪微博的实践经验(直接copy大佬原话):以上是几种常见的在召回和粗排阶段选择负例的做法。我们在模型召回阶段的经验是:比如在19年年中左右,我们尝试过选择1+选择3的混合方法,就是一定比例的“曝光未点击”和一定比例的类似Batch内随机的方法构造负例,当时在FM召回取得了明显的效果提升。但是在后面做双塔模型的时候,貌似这种方法又未能做出明显效果。
Q:User Embedding 与 Item Embedding 如何保持一致性?
由于双塔召回模型在Serving环节,主要包括异步Item刷库Serving和User Serving两部分,具体功能如下:
1.异步Item刷库Serving,主要通过刷库Item Serving捕获所有的item embedding,以异步的方式反复刷库,把得到的item embedding导入Faiss中,建立索引。为了保持版本的一致性,更新周期短即可。
2.User Serving,当用户请求推荐引擎后,获取该用户的user features,然后请求User Serving产出user embedding;同时,基于全库Item刷库的Embedding结果产出的Faiss索引服务做近邻搜索(ANN),召回Top N个item集合。
User Embedding是实时从线上服务的模型中产生的,线上服务的模型一定是最新版本的模型。而Item Embedding是周期性拿全量Item库刷线上服务模型得到,会出现有的Item Embedding是新的,有的是旧版的,版本不一致。
那在做近邻搜索(ANN)时,User Embedding会和部分Item Embedding版本一致,都是从一个模型中产生的,而其余部分Item Embedding版本是上一版模型导出的。这种版本的不一致就会导致召回结果的准确性降低!
线上实时得到User Embedding时,也会拿到当前服务模型的版本号,如果用Tensorflow导出模型的话,模型的版本号就是导出模型时刻的时间戳。Item Embedding导入到Faiss中建立索引时,也会对这个建立的Faiss索引库标上模型的版本号。
然后拿着带有模型版本号的User Embedding,到对应版本号的Faiss索引库中做近邻搜索(ANN),召回Top N个item集合。这个优化主要集中在工程上,优化难度也不大,主要就是能提升模型的在线收益。
Q:对于一个用户的一次Batch打分请求,User塔只计算一次
在线Serving打分阶段,一个Batch请求中包含一个用户的特征和多个item的特征。一般是将用户的特征复制Batch Size大小的次数,然后与每一个item的特征进行拼接,最后输入到双塔网络中计算user对每个item的打分。
这里有一个问题是:如果user塔的网络比较复杂或者用户特征非常多时,这种Serving打分的方式容易导致user塔的大量、重复计算。通常推荐系统中用户特征占比非常大,主要是用户的各种session特征及各种画像特征,而item的特征通常是一些属性特征和统计特征,占一个Batch请求包的很小比例。User塔的优化就是,对于一个用户的一次Batch打分请求,User塔只计算一次,在得到最终User Embedding后,复制batch size份。 在线Serving时,每个Batch只有一个用户的所有特征且拿一次,这里不是拿一个用户的特征拿Batch Size次哦,所以在生成稀疏特征的Embedding和稠密特征时,我们只需要取第一行的Embedding数据和稠密特征数据就可以了,也就是用户的特征只过一次User塔,User Embedding只需要生成一遍,这样矩阵运算就可以优化为向量运算。在得到最终的User Embedding后,把User Embedding再复制为batch size的维度。经过这一步的优化,双塔模型在线Serving时的打分耗时及线上服务需要的机器资源都减少了许多。
5.总结
- DSSM其核心思想是将query和doc映射到到共同维度的语义空间中,通过最大化query和doc语义向量之间的余弦相似度,从而训练得到隐含语义模型,达到检索的目的。
- DSSM主要用在召回和粗排阶段。 在应⽤于推荐系统时,通过两个塔分别去建模user侧和item侧的embedding,计算embedding之间的内积,最后⽤真实的label计算loss。
- user塔与item塔的DNN结构最后一层(全连接层)隐藏单元个数相同,保证user embedding和item embedding维度相同,后面相似度计算(如cos内积计算),损失函数使用二分类交叉熵损失函数。
本文仅仅作为个人学习记录所用,不作为商业用途,谢谢理解。
参考:https://blog.csdn.net/u012328159/article/details/123782735