今天要和大家分享的论文是来自Facebook的『Embedding based Retrieval in Facebook Search』。
不得不说,F家的文章还是一如既往浓浓的工业风,这篇论文从工程角度讲解了一个召回的全流程,不管是做语义信息检索召回还是推荐召回都值得认真学习。有过前几个月的embedding召回方向工作后,深觉这篇论文对于做召回的同学来说有非常多可以总结思考的地方。
社交网络中的搜索除了要考虑传统web搜索中的query文本,搜索人所处的上下文也是需要重点考虑的,其中Facebook搜索场景中特有的社交图谱便是典型的一种上下文。尽管向量检索(Embedding_based Retrieval, EBR)已经广泛应用于web搜索,但是Facebook的搜索还是沿用之前的布尔匹配。这篇论文也是从升级Facebook搜索系统开始,总结Facebook将Embedding技术应用到其搜索场景过程中的踩坑经验。
文章中的成果有两个:
在进行整个系统的端到端优化过程中,积累了大量的工程优化经验和技巧,如ANN调参,全栈优化等,还有一些如召回模型样本构建,特征工程方面的技巧。
通过引入Embedding技术,使用Embedding表示query和文档,将检索问题转化为Embedding空间的最近邻搜索问题。Facebook搜索中的EBR不仅面临海量数据的问题,如数十亿甚至上百亿的文档,而且需要同时兼容Embedding检索和布尔检索。Facebook搜索还有一个独特的点是用户的搜索意图不仅跟query的文本内容有关,还跟提问者及其所处的环境有关,这一点是比常规的信息检索方向要复杂的多的。
文章从模型、线上服务、全栈优化三个方面介绍了引入Embedding技术过程中遇到的种种问题。
作者将搜索中的预取看成召回优化问题,给定搜索的query,及其对应的目标集和模型返回的topK集合,最大化topK结果集中的召回率,其中目标集一般是根据用户点击或人工打分的相关文档。
召回优化问题又可以看成是根据文档和query之间的距离排序的问题,使用cos相似度度量被神经网络编码成稠密向量的query和文档之间的距离,再使用triplet loss作为召回目标学习Embedding编码模型。
但Facebook的搜索和通常的信息检索不同的地方是除了要考虑文本信息外,还要考虑用户的个性化信息以及用户所处的上下文。因此,文章提出统一Embedding,将查询的query文本和搜索人及其所处上下文融合到一个embedding中。
接下来从统一Embedding模型内容,模型损失函数,训练数据的挖掘和评估指标四个方面介绍Facebook的Embedding模型。
首先「模型内容」方面,和双塔结构一样,统一Embedding模型由三部分组成:query编码器生成query的Embedding,文档编码器生成文档的Embedding,相似度计算函数生成文档和query之间的打分。Facebook的模型中,query和文档的编码器是共享部分参数的独立模型。使用Cosine相似度作为相似函数,实际的Cosine距离定义为
。
编码器模型的输入包括query和文档的文本内容、社交和其他上下文特征。比如query侧的搜索人位置及其社交连接,文档侧group搜索时用到的小组聚合地址和社交群。原始特征大多为高基类别特征,进入模型的方式都是通过Embedding层,跟普通深度模型一样。
其次是「损失函数」,基于尽量把正例和负例的距离控制到一个固定距离之上的想法,Embedding模型的损失函数使用triplet loss:
其中
表示向量u和v之间的距离度量,m是正负样本之间的最小距离, N是从训练集中挑选的三元组数目。实验中发现margin参数m会导致KNN召回率有5~10%的波动,不同训练任务的最优margin差别也比较大。作者还认为随机采样作为triplet loss的负样本对可以近似召回优化任务,原因是一个正样本匹配n个负样本时,模型会优化n个召回池中选取top1时的召回率,假设放大到实际服务时的召回池规模为N,近似优化的就是召回topK=N/n的召回率。
然后是「训练数据」挖掘方面,Facebook基于召回指标验证召回流程中不同正负样本的选择策略。
针对以用户点击为正样本时的负样本选择:
结果表明,曝光未点击作为负样本的召回率远低于随机负样本,约55%的召回率退化。作者认为原因在于全部以hard case做负样本的训练数据和实际召回任务面对的数据分布不一致,实际索引中大多数是和用户query差别很大的easy case。
针对正样本的选择策略:
实验表明,用户点击和曝光分别作为正样本的召回指标相差不多,添加曝光数据并不能增加额外价值,增大训练数据规模也不能。
最后是「评估指标」,为了减少线上实验成本,快速评估模型效果并定位问题,文章提出基于索引后的Embedding执行KNN搜索再统计recall@K指标。
统一Embedding模型的优势之一就是可以通过融合文本之外的特征提升模型。Facebook的统一Embedding模型相比只基于文本特征的模型,在事件搜索上的召回率可以提升18%,分组搜索的召回率提升16%。统一Embedding模型中用到的特征主要有Text文本特征、位置特征、社交Embedding特征。
说完离线建模,再说说线上serving。Facebook的线上服务采用基于ANN的倒排索引搜索,出于两点考虑:Embedding量化后存储需求更小,便于集成到现有召回系统的倒排索引中。使用Faiss库索引向量,再在现有倒排索引表中做高效NN搜索。
这里先介绍一下Embedding量化的背景知识,在向量集合中查找与指定向量距离最短的k个最近邻,暴力搜索的时间在海量规模下是不现实的,Embedding量化就是为了解决向量空间搜索的效率问题,具体来说就是将原有的无限的向量空间映射到一个有限的向量集合(codebook)中,通过映射后的向量近似代表原向量。Embedding量化有三种形式:
首先是每个向量y的量化结果:
其中,
是粗糙量化结果,
是残差量化结果。然后是计算查询向量x和y之间的距离:
第一项是x和y的粗糙量化结果向量的欧式距离,第二第三项与查询向量x无关,可以提前计算好,第四项是x和y的残差量化结果的内积。
Facebook的Embedding量化使用的是层次量化:粗糙量化加残差的乘积量化。粗糙量化阶段的参数有num_cluster和具体量化算法IMI和IVF。乘积量化阶段是pq_bytes和不同的乘积量化变种PQ,OPQ,带PCA的PQ。还有一个nprobe参数,表示查询query向量可以属于多少类簇,决定了查询近邻时需要计算多少个粗糙类簇向量。文章中也介绍了ANN调参过程中的一些经验技巧:
。乘积量化将原本的d维向量压缩成x个字节的编码。x越大精度越高但内存和延时也越高。经验表明,
最佳。
Facebook原本的检索引擎支持的是布尔检索,为了避免创建新的系统,扩展了现有引擎的embedding字段以支持nn查询操作(nn <key>:radius <radius>)。索引阶段,每个文档的Embedding被量化成一项(粗糙类簇)和一个payload(量化后的残差向量)。查询阶段,nn查询操作会被改写成一个or运算项,or的内容是和查询Embedding最近的nprobe个粗糙类簇,对于匹配到的文档再使用payload验证半径限制。这里作者针对NN操作对比了半径查询模式和top-K查询模式,发现半径模式更能平衡系统性能和结果质量,作者给出的理由是半径模式下是一个受限NN搜索而topK需要扫描全部索引。
Facebook搜索排序是个复杂的多阶段排序系统,每层都是对前一层的结果提取精华。检索层是最底层,也是EBR应用的地方,其结果会被后续的排序层排序过滤。每一阶段的模型都是根据前一层的结果数据分布来做优化的。因此,当前的排序系统是根据当前的检索层设计模型,会导致新的检索结果不会得到最优排序。文章提出两个方法解决这个问题:
为了进一步提升EBR的效果,文中尝试了两个方向:hard样本挖掘和Embedding模型集成。
hard样本的说法来自于CV的分类任务,搜索召回中没有类别的概念,无法直接应用CV的hard样本挖掘方法。FB尝试了两种hard样本挖掘的方法:hard负样本挖掘和hard正样本挖掘。
不过hard样本作为easy样本的补充比单独使用hard样本有更好的效果,因为线上实际召回的数据分布中还是easy样本居多。
首先是通过实验发现,相比easy样本有助于表示检索空间,hard样本能够帮助提升模型精度。随机负样本训练出的模型能模拟实际的检索数据分布,优化的是较大K时的topK召回率,当K比较小时,效果不佳。但如果以精度优化模型,比如以曝光未点击做负样本或离线hard负样本,都会使得模型擅长小数据集内排序而不适合召回任务。因此作者考虑以多阶段的方式融合针对不同难度的样本训练模型,即第一阶段关注模型召回率,第二阶段专注于区分第一阶段中比较相似的结果。文中试验了两种模型集成方式:权重拼接和模型级联,而且这两种都证明是有效的方式。
总的来说,曝光未点击作负样本对排序是关键,而对召回并无太大用处。
这篇论文中可以学习到的经验: