登录    注册      
    
  

News Message

双塔模型:DSSM原理与实践



双塔模型:DSSM原理与实践

用户发布的文档

加载速度比较慢比较慢,请稍等,手机环境下,有可能无法显示!


一 、背景

DSSM是Deep Structured Semantic Model(深层结构语义模型)的缩写,即我们通常说的基于深度网络的语义模型,其核心思想是将query和doc映射到到共同维度的语义空间中,通过最大化query和doc语义向量之间的余弦相似度,从而训练得到隐含语义模型,达到检索的目的。DSSM有很广泛的应用,比如:搜索引擎检索,广告相关性,问答系统,机器翻译等。DSSM主要用在召回和粗排阶段。

论文题目:《Learning Deep Structured Semantic Models for Web Search using Clickthrough Data》

论文地址:


二、DSSM双塔模型的原理结构

2.1 原理结构

先来看看愿论文中的模型:


典型的DNN结构是将原始的文本特征映射为在语义空间上表示的特征。DNN在搜索引擎排序中主要是有下面2个作用:

1.将query中term的高维向量映射为低维语义向量

2.根据语义向量计算query与doc之间的相关性分数

从模型上来看,x是用来表示输入的term向量,y是经过DNN后的输出向量,计算如下:


W,b是模型的参数,f是激活函数,其中f为tahn激活函数:


相似度计算为:


其中,  与  是query与doc的语义向量。在搜索引擎中,给定一个query,会返回一些按照相关性分数排序的文档。

可以看到论文中有一个word hashing层,用来解决在实际场景中,词典的大小非常大,如果直接将该数据输入给DNN,神经网络是无法进行训练和预测的问题。

这里直接上一个画的图,相比较原始论文,这个图更能表示在推荐领域中的DSSM结构,如下图所示:

推荐领域常用DSSM模型结构

模型结果非常简单,主要包括两部分:user侧一个塔,item侧一个塔。user侧特征和item侧特征分别经过各自的DNN(一般情况下,两个DNN结构是一样的,当然也可以不一样)后得到user embedding和item embedding,这里需要注意的是如果你的user dnn和item dnn结构不一样,请务必保证输出维度一样,也就是最后一层全连接层隐藏单元个数相同,需要保证user embedding和item embedding的维度相同,因为下一步要做相似度计算(常用内积或者cosine)。损失函数部分则是常用的二分类交叉熵损失,y_true为真实label 0或者1,y_pred为相似度结果。

2.2 优缺点

优点: DSSM 用字向量作为输入既可以减少切词的依赖,又可以提高模型的范化能力,因为每个汉字所能表达的语义是可以复用的。另一方面,传统的输入层是用 Embedding 的方式(如 Word2Vec 的词向量)或者主题模型的方式(如 LDA 的主题向量)来直接做词的映射,再把各个词的向量累加或者拼接起来,由于 Word2Vec 和 LDA 都是无监督的训练,这样会给整个模型引入误差DSSM 采用统一的有监督训练,不需要在中间过程做无监督模型的映射,因此精准度会比较高,肯定满足基本可用需求的

缺点: 上文提到 DSSM 采用词袋模型(BOW),因此丧失了语序信息和上下文信息。另一方面,DSSM 采用弱监督、端到端的模型,预测结果不可控。

三、DSSM用于召回

现在工业界的推荐系统的召回阶段基本上多路召回,比如CF召回、CB召回、语义向量召回等,

3.1 朴素的双塔模型

在模型训练完毕后,user塔跟item塔各自存储在redis这样的数据库中,线上计算的时候,直接从内存中取到两个向量计算相似度即可。

3.2 百度的双塔模型

“百度的双塔模型分别使用复杂的网络对用户相关的特征和广告相关的特征进行 embedding,分别形成两个独立的塔,在最后的交叉层之前用户特征和广告特征之间没有任何交互。这种方案就是训练时引入更多的特征完成复杂网络离线训练,然后将得到的 user embedding 和 item embedding 存入 Redis 这一类内存数据库中。线上预测时使用 LR、浅层 NN 等轻量级模型或者更方便的相似距离计算方式。这也是业界很多大厂采用的推荐系统的构造方式。”

事实上,不管是前面提到的din还是dien都是隐约的有着双塔模型的影子在,都把user跟item两边的特征分离,构建不同的子塔。

3.3 谷歌的双塔模型


利用双塔模型对 user-item 对的交互关系进行建模,从而学习[用户,上下文]向量和[item]向量的关联。针对大规模流数据,提出 in-batch softmax 损失函数与流数据频率估计方法更好的适应 item 的多种数据分布。

四、DSSM代码实践(人生苦短,我选API)

# -*- coding:utf-8 -*-
"""
    
"""

from tensorflow.python.keras.models import Model

from deepctr.inputs import input_from_feature_columns, build_input_features, combined_dnn_input
from deepctr.layers.core import DNN, PredictionLayer
from utils import Cosine_Similarity


def DSSM(user_dnn_feature_columns, item_dnn_feature_columns, gamma=1, dnn_use_bn=True, dnn_hidden_units=(300, 300, 128), dnn_activation='tanh',
         l2_reg_dnn=0, l2_reg_embedding=1e-6, dnn_dropout=0, init_std=0.0001, seed=1024, task='binary'):
    """Instantiates the Deep Structured Semantic Model architecture.
    :param user_dnn_feature_columns:An iterable containing user's features used by deep part of the model.
    :param item_dnn_feature_columns:An iterable containing item's the features used by deep part of the model.
    :param gamma: smoothing factor in the softmax function for DSSM
    :param dnn_use_bn: bool. Whether use BatchNormalization before activation or not in deep net
    :param dnn_hidden_units: list,list of positive integer or empty list, the layer number and units in each layer of deep net
    :param dnn_activation: Activation function to use in deep net
    :param l2_reg_dnn: float. L2 regularizer strength applied to DNN
    :param l2_reg_embedding: float. L2 regularizer strength applied to embedding vector
    :param dnn_dropout: float in [0,1), the probability we will drop out a given DNN coordinate.
    :param init_std: float,to use as the initialize std of embedding vector
    :param seed: integer ,to use as random seed.
    :param task: str, ``"binary"`` for  binary logloss or  ``"regression"`` for regression loss
    :return: A Keras model instance.
    """
    user_features = build_input_features(user_dnn_feature_columns)
    user_inputs_list = list(user_features.values())
    user_sparse_embedding_list, user_dense_value_list = input_from_feature_columns(user_features, user_dnn_feature_columns,
                                                                         l2_reg_embedding, init_std, seed)
    user_dnn_input = combined_dnn_input(user_sparse_embedding_list, user_dense_value_list)

    item_features = build_input_features(item_dnn_feature_columns)
    item_inputs_list = list(item_features.values())
    item_sparse_embedding_list, item_dense_value_list = input_from_feature_columns(item_features, item_dnn_feature_columns,
                                                                         l2_reg_embedding, init_std, seed)
    item_dnn_input = combined_dnn_input(item_sparse_embedding_list, item_dense_value_list)

    user_dnn_out = DNN(dnn_hidden_units, dnn_activation, l2_reg_dnn, dnn_dropout,
                  dnn_use_bn, seed, name="user_embedding")(user_dnn_input)

    item_dnn_out = DNN(dnn_hidden_units, dnn_activation, l2_reg_dnn, dnn_dropout,
                  dnn_use_bn, seed, name="item_embedding")(item_dnn_input)

    score = Cosine_Similarity(user_dnn_out, item_dnn_out, gamma=gamma)

    output = PredictionLayer(task, False)(score)

    model = Model(inputs=user_inputs_list+item_inputs_list, outputs=output)

    return model


五、思考与注意点

这里先给读者上一杯美式冰咖啡冷静一下,DSSM 就一定适合所有的业务吗?

这里列出 DSSM 的 2 个缺点以供参考:

  1. DSSM 是端到端的模型 ,虽然省去了人工特征转化、特征工程和特征组合,但端到端的模型有个问题就是效果不可控。对于一些要保证较高的准确率的场景,用有监督人工标注的 Query 分类作为打底,再结合无监督的 Word2Vec、LDA 等进行语义特征的向量化,显然比较可控(至少 Query 分类的准确率可以达到 95% 以上)。
  2. DSSM 是弱监督模型,因为引擎的点击曝光日志里 Query 和 Title 的语义信息比较弱。举个例子,搜索引擎第一页的信息往往都是 Query 的包含匹配,笔者统计过,完全的语义匹配只有不到 2%。这就意味着几乎所有的标题里都包含用户 Query 里的关键词,而仅用点击和曝光就能作为正负样例的判断?显然不太靠谱,因为大部分的用户进行点击时越靠前的点击的概率越大,而引擎的排序又是由 pCTR、CVR、CPC 等多种因素决定的。从这种非常弱的信号里提取出语义的相似性或者差别,那就需要有海量的训练样本。DSSM 论文中提到,实验的训练样本超过 1 亿。笔者和同事也亲测过,用传统 CTR 预估模型千万级的样本量来训练,模型无法收敛。可是这样海量的训练样本,恐怕只有搜索引擎才有吧?普通的搜索业务 Query 有上千万,可资源顶多只有几百万,像论文中说需要挑出点击和曝光置信度比较高且资源热度也比较高的作为训练样本,这样就过滤了 80% 的长尾 Query 和 Title 结果对,所以也只有搜索引擎才有这样的训练语料了吧。另一方面,超过 1 亿的训练样本作为输入,用深度学习模型做训练,需要大型的GPU集群,这个对于很多业务来说也是不具备的条件。

DSSM召回也是语义向量召回的一种,先来看离线部分如何训练DSSM模型。

5.1、DSSM召回离线训练

DSSM离线训练和普通的DNN训练并没有什么大的区别,只是需要把特征分为user侧特征和item侧特征,并且无法使用user-item的交叉特征。 对于DSSM召回的样本,正样本没什么好说的,就是用户点击的item,那么对于负样本呢?对于没什么经验的算法工程师,最常见的错误就是负样本直接用曝光未点击的item。这会直接导致SSB问题,即样本选择偏差问题(sample selection bias),原因很简单,召回在线的时候是从全量候选item中召回,而不是从有曝光的item中召回。

这里,就引申出了一个学问非常大的topic:负样本为王,如何构造负样本?

先说DSSM原始论文里的做法,只有正样本,记为D + D^+D+,对于用户u 1 u_1u1​,其正样本就是其点击过的item,负样本则是随机从D + D^+D+(不包含u 1 u_1u1​点击过的item)中随机选择4个item作为负样本。

召回负样本构造是一门学问,常见的负样本构造方法有(摘自张俊林大佬文章,SENet双塔模型:在推荐领域召回粗排的应用及其它,关于负样本构造方法总结的非常棒):

  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选择负例 它是选择那些比较难的例子,做为负例。因为难区分的例子,很明显给模型带来的loss和信息含量比价多,所以从道理上讲是很合理的。但是怎样算是难的例子,可能有不同的做法,有些还跟应用有关。比如Airbnb,还有不少工作,都是在想办法筛选Hard负例上。

新浪微博的实践经验(直接copy大佬原话):以上是几种常见的在召回和粗排阶段选择负例的做法。我们在模型召回阶段的经验是:比如在19年年中左右,我们尝试过选择1+选择3的混合方法,就是一定比例的“曝光未点击”和一定比例的类似Batch内随机的方法构造负例,当时在FM召回取得了明显的效果提升。但是在后面做双塔模型的时候,貌似这种方法又未能做出明显效果。

5.2、DSSM召回在线infer

提到召回必然面对一个问题:如何在全量候选item中选出用户最喜欢的topX个,也就必然涉及到效率问题。离线训练尚可不太考虑效率问题,当然训练时间越短模型更新越及时,则更好,但对训练时间的容忍度相对较高。但在线infer时对耗时有着严格的要求,效率就必须是首先要面对的问题。DSSM之所以能够在工业界这么流行,就是因为其双塔结构能够做到非常好的解耦,即训练好后user侧塔和item侧塔完全没关系,没有依赖关系。

因为百度在AI算法这一块还是有不错的技术积累,因此有一套非常成熟好用的基建,从日志收集传输、特征抽取框架、模型训练部署框架、embedding向量存储、在线infer等非常齐全。所以我们在线部署DSSM的时候选择了比较奢侈的方法:item侧塔和user侧塔都部署到线上,有个server会每间隔几个小时就请求item塔,计算出全量item的embedding向量,然后存储更新。当每个用户请求到达时,会请求user塔计算出user的embedding向量,然后拿着这个user向量去做item库里做ANN检索选出相似度最大的topX个ietm。关于ANN检索技术比较有很多,比如:kd树、Annoy、HNSW等,Facebook开源了ANN库FAISS,国内很多公司在用,百度则有自己的一套ANN检索框架。看到这里,你应该已经明白为什么DSSM无法使用user#item的交叉特征了。

参考内容:

microsoft.com/en-us/res

推荐系统论文阅读(七)-借鉴DSSM构建双塔召回模型

github.com/shenweichen/

github.com/wangzhegeek/



Share Http URL:  http://www.wittx.cn/get_news_message.do?new_id=1234



请输入评论





























Best Last Month

Capital Market Line

Capital Market Line

Information industry

by wittx


GPT解数学题准确率升至92.5%!微软提出MathPrompter



Nature:CAR-T 细胞免疫疗法

Nature:CAR-T 细胞免疫疗法

Information industry

by wittx


强化学习在金融中的运用 DeepTrader

强化学习在金融中的运用 DeepTrader

Information industry

by wittx


Nature Reviews Physics

Nature Reviews Physics

Information industry

by wittx


Modeling and Simulation for Meeting the Challenges of Battery Design



量化投资策略与Smart Beta

量化投资策略与Smart Beta

Information industry

by wittx


美国粮价持续上涨!

美国粮价持续上涨!

Information industry

by wittx


2020/11/24金融行情

2020/11/24金融行情

Information industry

by wittx


DeepMind最新研究NFNet:抛弃归一化,深度学习模型