论文阅读|Embedding-based Retrieval in Facebook Search
创始人
2024-04-23 03:59:17
0

该论文是facebook发表在KDD2020上的一篇关于搜索召回的paper。这篇文章提到的大多trick对于做过召回的同学比较熟悉了,可贵之处在于全面,包括了特征、样本、模型、全链路等各种细节知识。

1. 整体思路与框架

本文的出发点是搜索只做到query关键词匹配的程度是远远不够的,还要结合用户信息及上下文提供个性化搜索服务,比如一个热爱数码的大学生农村卖水果的果农搜索【苹果】得到的结果应该分别是手机水果

通常的搜索分为召回和排序两个阶段,基于embedding的语义召回主要在第一阶段,它要解决的问题是如何从千万个文本中找到相关的topK个,难点一个是【准】,一个是【快】,准要求和用户+query高度的匹配,快要求从海量候选中搜索的延时低。

模型是双塔模型,当然这里做了一些特征和样本的trick,后面会提。整个架构如下:

  • 左边采用了query understanding+embedding inference两部分,即向量表征是补充而非替换
  • 在构建index时采用了embedding quantization
  • retrieval包括NN operator和Boolean Match

评估的时候为了快速迭代验证,采用了离线topk命中作为评估。我个人认为从召回的本质出发,本就没办法离线去准确评估一个召回的价值,当然迫于迭代效率+搜索场景,这个指标阐述一些feature的价值是可以接受的。下面就围绕这个指标的提升,阐述一下本文的各种工业界trick经验总结

2. 模型

模型结构是双塔,为了优化triple loss, 我们模型包含三个部分:提供query embedding的query encoder f(Q),document encoder g(D),相似度计算function S() 采用cosine similarity。在我们的模型中,f(),g()是拥有一些共享参数的两个独立的network。

unified embedding encodes 文字,社交,以及其他的上下文特征来分别表示query和document。举例来说,对于query,可能包含了地理位置以及社交关系,而document侧,可能包含聚合位置信息以及社交群组信息。

很多特征是高维离散特征,one-hot multi-hot的vector。我们使用embedding look-up layer学习得到一个dense的vector输入encoder。multi-hot的vector,我们将multiple的embedding做一个weighted combination 作为最终的feature-level的embedding。图2是我们unified embedding model,在section3中,我们将讨论更多的feature engineering。

2.1 损失函数

本文将搜索相关性以pair-wise的角度建模,采用的是triplet loss,形式如下:

 margin是很重要的,说白了这个参数是划分样本难度的,如果特别大没办法收敛,如果特别小又没区分度,虽然对于m本文没讲怎么设置。我们认为使用random samples去构建负例可以更好的approximate recall optimization task。因为如果我们为每一个正例去采样n个负例,那我们模型就是在size n中优化召回在top one position。假设真实的candidate pool大小是N, 我们近似最优化召回 K 约等于 N/n。在2.4我们验证我们这个假设。

2.2 Training Data Mining (重点)

hard negative mining

本文提出了online和offline两种mining方式

  • online:在线一般是batch内其他用户的正例当作负例池随机采,本文提到选相似度最高的作为hard样本,同时强调了最多不能超过两个hard样本。
  • offline:在线batch内池子太小了不一定能选出来很好的hard样本,离线则可以从全量候选里选。具体做法是对每个query的top-k结果利用hard selection strategy找到hard样本加入训练,然后重复整个过程。这里提到要从101-500中采,太靠前的也许根本不是hard负例,压根就是个正例。以及两个很好的经验,第一个是样本easy:hard=100:1,第二个是先训练easy再训练hard效果<先hard后easy

hard positive mining

本文认为有一些用户未点击但是也能被认为是正样本,做法就是从日志中挖掘潜在的正样本,这也能解释为什么上面hard负样本是101-500了,因为这里可能1-10就是正样本了。

如果定义召回任务的正例和负例是一个很重要的问题。下面我们对于几种选择进行了一个比较。对于负例,我们最初采取了以下两个选择,选用点击为正例:

  • 随机sample:对于每个query,在document池子中sample document作为负例。
  • 未点击impression:对于每个query,impressed但是没有点击的结果作为负例。

使用未点击impression作为负例的得到显著的更差的model recall: 55% regression在people embedding model recall。我们相信这些negative bias来自 hard cases在一个或者几个factor上可以match query,而大多数的情况下都是完全不能match query的easy cases。当我们所有的负例是这样的hard case的时候,相比真实的召回任务将改变我们training data和真实之间的一致性,导致我们学习到的embedding存在很大的 bias。

The model trained using non-click impressions as negative has significantly worse model recall compared to using random negative: absolute 55% regression in recall for people embedding model. We believe it is because these negatives bias towards hard cases which might match the query in one or multiple factors, while the majority of documents in index are easy cases which do not match the query at all. Having all negatives being such hard negatives will change the representativeness of the training data to the real retrieval task, which might impose non-trivial bias to the learned embeddings.

我们也做了一些正例的尝试:

  • 点击:直觉的使用点击作为正例,用户的点击表示了用户认为这个结果契合他的搜索意图。
  • 展现:这个想法是我们将召回想做一个计算更快的排序的近似,所以我们的目标是设计一个召回模型返回的结果同样可以被排序模型排在前面。使用这个思想,我们将给用户展现出的结果都作为召回模型的正例。

我们实验表明以上两种方法都是一样有效的;使用点击和展现训练出的模型,给出相似的数据量与相似的召回结果。我们试着使用展现训练数据扩充到点击训练数据中,但是没有给点击训练数据的模型带来额外的收获。证明添加展现训练数据没有提供出额外的数据信息,模型也没有从添加的更多数据量上获得新的好处

我们实验告诉我们使用点击作为正例,随机负例的方式可以带来不错的模型效果。我们还做了一些可以帮助增加模型区分相似结果的尝试在6.1.

2.3 Feature Engineering

unified embedding model可以关注不仅是文字的多种特征,给模型带来更好的效果。在events search场景上带来了18%的召回提升,groups search带来16%提升。下面列出了我们认为带来重要提升的几个特征。

Text Features: Character n-gram 是一个常用的text embedding的方式,跟 word n-gram 相比有两个优势,第一,因为他拥有limited vocabulary size,训练更容易;第二,对out-of-vocabulary 的词鲁棒性更好(单词拼写错误或者单词变化)。我们对 Character n-grams 和 word n-grams 分别实验发现前者有更好的效果。但是,character trigrams上面,加入 word n-grams 提供了微小但是持续的提升(+1.5% recall gain)。 word n-grams 的基数一般很大 (e.g. 352M for query trigrams) ,哈希可以帮助减小embedding 查找表。即使有hash collision 这样的缺点, word n-grams 还是可以额外的提升。

Facebook 提取text feature的主要场景是人名或者title。对比 Boolean term matching techniques ,使用单纯的text feature训练出来的embedding 有以下两个优势:

  • 模糊文字匹配。模型可以学习去匹配 query “kacis creations” 与 kacis的页面,term-based match 是做不到的。
  • 选配。当query是"mini cooper nw"时,模型可以学习召回 Mini cooper owner/drivers club ,丢掉 “nw”进行可选字词匹配。

Location features: location 匹配在很多场景带来好处比如在搜索local business/groups/events的时候。为了让embedding model可以考虑上location的信息,我们在query侧和document侧都加入了location feature。在query侧,我们取出了城市地区国家和语言。document侧,我们加入了一些公开信息如,group location tagged by admin。加入了text feature,模型可以学习到了一些内在的location match。Table2 对比了text embedding 模型和 text+ location模型,我们可以看到location feature的模型,将相同location的排在了前面。

Social embedding feature:我们使用一个单独的模型通过social graph 学习user 和 entity的embedding。

2.4 SERVING

(这边开始我简要写一下)

文章使用 ANN(approximate near neighbor) 倒排索引。使用他们自家的Faiss组建。

Faiss 中有几个重要的参数:Coarse quantization,Product quantization,nprobe。文章使用离线实验调试线上测试效果。给出一些调参注意事项:1.cluster间的数据存在很不平衡的情况,下图是一个scanned document和1-recall@10的结果。2.当有重大的模型变化时一定要调整ANN parameters。3.使用OPQ。4.pq_bytes 最好是 dimension/4。5.还是要线上调整参数看一下效果。

2.5 ADVANCED TOPICS

文章发现tok K 的结果存在target result和其他result没有区分度的问题,认为是random sampling导致模型太容易了,所以尝试加入一些hard的数据。

online hard negative mining: 在每个batch的query在batch中选择highest similarity当作hardest negatives,每个positive配两个hard negatives最好。

offline hard negative mining:不使用最hard的当作negative,使用rank在101-500的带来最好的recall效果。仍要保持easy negative的选项,毕竟实际的状况中还是easy选项多。

最好的选择:easy和hard的混合。实验结果是easy:hard = 100:1 最好。使用Transfer learning from hard to easy.

需要注意的一点是使用ANN在一个random shard上面搜索的时候,hard negative的选择,文章选择使用semi-hard negatives。

3.总结

本文有一些经验值得借鉴和思考,但比起结论更重要的是思维的方法,比如为什么要做hard mining,自己的场景哪些数据值得hard mining,自己系统中召回问题最关键的是样本、架构还是数据流,只有先定义了问题才能做ROI最高的优化。

4.code解读

github:UnifiedEmbeddingModel/main.py at main · liyinxiao/UnifiedEmbeddingModel · GitHub

loss部分:

# Triplet losstriplet_loss = nn.TripletMarginWithDistanceLoss(distance_function=lambda x, y: 1.0 - F.cosine_similarity(x, y), margin=margin)调用:
def train(self, data_loader, epoch):self.query_encoder.train()self.document_encoder.train()running_loss = 0for _, (query_inputs, positive_document_inputs, negative_document_inputs) in enumerate(data_loader):# Forward passanchor = query_encoder(query_inputs)positive = document_encoder(positive_document_inputs)negative = document_encoder(negative_document_inputs)loss = triplet_loss(anchor, positive, negative)# Backward and optimizequery_optimizer.zero_grad()document_optimizer.zero_grad()loss.backward()query_optimizer.step()document_optimizer.step()running_loss += loss.item()print('Epoch [{}], Loss: {:.4f}'.format(epoch+1, running_loss / len(data_loader)))self.training_loss.append(running_loss / len(data_loader))

参考:
1.将embedding作为排序模型的特征:《Deep Match to Rank Model for Personalized Click-Through Rate Prediction》

2.《Embedding-based Retrieval in Facebook Search》论文精读 - 知乎

3.Embedding-based Retrieval in Facebook Search 阅读笔记 - 知乎

相关内容

热门资讯

安卓se系统怎么启用,确保应用... 你有没有发现,你的安卓手机最近有点儿“懒”呢?运行速度慢,反应迟钝,是不是想给它来个“大变身”呢?别...
微软怎么使用安卓系统,技术融合... 你有没有想过,那个以Windows系统著称的微软,竟然也会和安卓系统玩起“亲密接触”?没错,就是那个...
安卓系统耗电特别快,快速诊断与... 手机电量总是不够用?安卓系统耗电特别快,是不是你也遇到了这样的烦恼?别急,今天就来跟你聊聊这个话题,...
安卓机 桌面 系统菜单,功能解... 你有没有发现,你的安卓手机桌面系统菜单,其实就像一个隐藏的宝藏库呢?里面藏着各种各样的功能,等着你去...
安卓ios系统怎么安装,安卓与... 你有没有想过,你的手机里那些好玩的应用是怎么来的呢?是不是觉得安装个软件就像变魔术一样简单?其实,这...
珍奥助手安卓系统下载,轻松体验 你有没有听说最近有个超级好用的助手软件——珍奥助手?没错,就是那个能让你手机生活变得更加便捷的小帮手...
安卓换ios系统.数据,数据迁... 你有没有想过,手机系统就像是我们生活中的衣服,有时候换一件新衣服,整个人都焕然一新呢?没错,今天咱们...
安卓系统提示怎么关,轻松关闭功... 手机屏幕上突然弹出一个安卓系统的提示,让你不禁皱起了眉头。别急,别慌,今天就来手把手教你如何轻松关闭...
安卓系统如何刷回flyme系统... 你是不是也和我一样,对安卓手机的Flyme系统情有独钟呢?有时候,因为一些原因,我们可能需要将手机刷...
手机订餐系统源码安卓,基于手机... 你有没有想过,每天忙碌的生活中,点外卖已经成为了一种不可或缺的享受?而这一切的背后,离不开那些默默无...
顾问营销系统安卓版,助力企业高... 你有没有想过,在这个信息爆炸的时代,如何让你的产品在众多竞争者中脱颖而出呢?别急,今天我要给你介绍一...
安卓系统连接雅马哈音箱,打造个... 你有没有想过,家里的安卓手机和雅马哈音箱也能来个甜蜜的“牵手”呢?没错,今天就要来给你揭秘,如何让这...
安卓系统文件日志查看,揭秘系统... 手机里的安卓系统文件日志,听起来是不是有点儿高深莫测?别担心,今天我就要带你一探究竟,揭开这些神秘日...
努比亚升级安卓p系统,畅享智能... 你知道吗?最近手机界可是热闹非凡呢!努比亚这个品牌,竟然悄悄地给他们的手机升级了安卓P系统。这可不是...
仿苹果装安卓系统,揭秘仿苹果装... 你有没有想过,如果你的苹果手机突然变成了安卓系统,那会是怎样的场景呢?想象你那熟悉的iOS界面,突然...
安装安卓13子系统,全新功能与... 你听说了吗?安卓13子系统终于来了!这可是安卓系统的一大革新,让我们的手机体验更加丰富多元。今天,就...
安卓系统内核日志保存,深度洞察... 你有没有想过,当你手机里的安卓系统在默默运行时,它其实就像一个勤劳的小蜜蜂,不停地记录着它的“工作日...
安卓系统可以调用dll,安卓系... 你知道吗?安卓系统竟然能调用DLL文件,这可是个让人眼前一亮的小秘密呢!想象你手中的安卓设备,不仅能...
安卓通讯 录系统代码,基于安卓... 你有没有想过,你的手机里那个默默无闻的通讯录系统,其实背后有着一套复杂的代码在支撑呢?今天,就让我带...
安卓系统版本对应关系,安卓系统... 你有没有发现,每次手机更新系统,那感觉就像给手机换了个新衣裳,焕然一新呢!不过,你知道吗?安卓系统的...