搜索算法框架综述

参考资料

[1] jieba分词_从语言模型原理分析如何jieba更细粒度的分词
[2] 全面理解搜索Query:当你在搜索引擎中敲下回车后,发生了什么?
[3] 新词发现"算法探讨与优化-SmoothNLP
[4] 新词发现(一):基于统计
[5] 一文带你了解搜索功能设计
[6] 搜索中的纠错问题初探
[7] 美团机器学习实践
[8] 浅谈Query理解和分析
[9] 搜索中的命名实体识别
[10] 深入理解搜索引擎-搜索召回
[11] 策略算法工程师之路-召回策略(搜索部分)
[12] Huang P S, He X, Gao J, et al. Learning deep structured semantic models for web search using clickthrough data[C]//Proceedings of the 22nd ACM international conference on Information & Knowledge Management. 2013: 2333-2338.
[13] DSSM 损失函数是 Pointwise Loss 吗?
[14] 自然语言处理(NLP)面试必备:pointwise 、 pairwise 、listwise
[15] Query 理解和语义召回在知乎搜索中的应用
[16] 学习排序 Learning to Rank:从 pointwise 和 pairwise 到 listwise,经典模型与优缺点
[17] Learning to Rank: pointwise 、 pairwise 、 listwise
[18] Tie-Yan Liu (2009), “Learning to Rank for Information Retrieval”, Foundations and Trends® in Information Retrieval: Vol. 3: No. 3, pp 225-331. http://dx.doi.org/10.1561/1500000016
[19] 强化学习未来五年内在推荐系统领域的应用前景如何?


1 搜索算法框架流程

搜索的过程就是根据输入 query 筛选目标结果的过程,大致可以分为 query 理解、召回、排序三大模块。
在这里插入图片描述
query 理解利用 NLP 手段对用户的输入进行处理,目的在于方便后续与候选集进行匹配。

召回和排序的过程都是筛选候选集的过程,整体呈现一个漏斗的形状,候选集数量会逐渐减少,排序逐渐精准,所利用的算法模型也会逐渐复杂。其中排序阶段包含多个排序子阶段。

2 query理解

query 理解一般包括 query 预处理、分词、query 改写、意图识别等步骤。

2.1 query预处理

query 预处理目的为初步提高数据质量,方便后续其他模块进行分析,一般包括以下步骤:

  • 全半角转换:将在输入法全角模式下输入的 query 转换为半角模式的,主要对英文、数字、标点符号有影响,如将「wechat123」全角输入转成半角模式下的「wechat 123」。
  • 大小写转换:统一将大写形式的字母转成小写形式的。
  • 拼音转文字:将拼音转换成概率最高的文字。
  • 繁简体转换:将繁体输入转成简体的形式,当然考虑到用户群体的差异以及可能存在繁体形式的资源,有些情况还需要保留转换前的繁体输入用于召回。
  • 无意义符号处理:移除诸如火星文符号、emoji 表情符号等特殊符号内容。
  • Query 截断:对于超过一定长度的 query 进行截断处理。

2.2 query分词

query 分词就是将 query 切分成多个 term,其准确性很大程度影响后续的模块,如 term 重要性分析和意图识别。

2.2.1分词原理

目前分词技术相对来说已经比较成熟,主要做法有基于词典进行前后向最大匹配、对所有成词情况构造 DAG、hmm/crf 序列标注模型以及深度学习模型+序列标注等。目前无论学术界还是工业界开放的分词工具或服务还是比较多的,如主要有腾讯内部的 QQSeg、百度 LAC、Jieba 分词、清华 THULAC、北大 pkuseg、中科院 ICTCLAS、哈工大 PyLTP、复旦 FNLP、Ansj、SnowNLP、FoolNLTK、HanLP、斯坦福 CoreNLP、Jiagu、IKAnalyzer等。它们的原理大体相似,但一些细节功能以及性能处略有差异,具体包括:切词准确性、粒度控制、切词速度、是否带有 NER、NER 识别速度、是否支持自定义词典等。

在搜索中 query 分词一般会做切分粒度控制,控制原理一般为修改词典中的词频或直接限制结果的长度。在进行召回时可以优先用粗粒度的切词结果进行召回能得到更精准相关的结果同时减少多个term拉链合并的计算量。当粗粒度分词进行召回结果不够时,可以采用拆分后的细粒度分词进行二次重查扩召回。

2.2.2 OOV问题

NLP 中存在一类问题叫 OOV 问题,这类问题在分词中也存在。未登陆词常见于网络的新兴词语或垂直领域的专业词汇,这时候需要对这些未登陆词做新词发现。新词发现可以通过基于统计手段算法手段来解决,通过统计语料中的词语 tfidf 词频、凝聚度和自由度等指标来进行无监督新词挖掘。其中凝聚度的公式为:
S o l i d = P ( ω i ω j ) l o g P ( ω i ω j ) P ( ω i ) P ( ω j ) Solid =P(\omega_i \omega_j) log \frac{P(\omega_i \omega_j)}{P(\omega_i)P(\omega_j)} Solid=P(ωiωj)logP(ωi)P(ωj)P(ωiωj)用于衡量两个 term 共现的概率,两个 term 经常出现在一起,则可以将它们组合成一个词语整体的可能性也更大。自由度取 term 左右邻熵的较小值:
F r e e d e g = m i n ( e n t r o p y ( ω l e f t ) , e n t r o p y ( ω r i g h t ) ) Freedeg = min(entropy(\omega_{left}),entropy(\omega_{right})) Freedeg=min(entropy(ωleft),entropy(ωright))衡量当前 term 左右两边字集合的随机程度,如果左右字集合越随机则这个 term 独立成词的可能性也更大。

举个例子:考虑「被子」和「辈子」这两个片段。我们可以说「买被子」、「盖被子」、「进被子」、「好被子」、「这被子」等,在「被子」前面加各种字;但「辈子」的用法却非常固定,除了「一辈子」、「这辈子」、「上辈子」、「下辈子」,基本上「辈子」前面不能加别的字了。「辈子」这个文本片段左边可以出现的字太有限,以至于直觉上我们可能会认为,「辈子」并不单独成词,真正成词的其实是「一辈子」、「这辈子」之类的整体。

算法方面可以使用 HMM、CRF 等序列标注模型来进行处理。除此之外,对于非中文场景,BPE、WordPiece 等手段也可以应对 OOV 问题。

2.3 query改写

受限于用户的先验知识的参差不齐或输入设备引入的噪音,用户输入的 query 可能不足以表达用户真正的需求进而影响用户搜到想要的结果。为此,除了保证搜索结果的相关性,一个完善的搜索引擎还需要给用户提供一系列搜索引导功能,以减少用户的搜索输入成本,缩短用户找到诉求的路径。其中较为重要的内容包括:query 纠错query 删除query 扩展

2.3.1 query纠错

query 纠错就是对用户输入 query 出现的错误进行检测和纠。一般分为 Non-word 和 Real-word 两类错误,前者一般出现在带英文单词或数字的 query 中,多表现为拼写错误。由于中文 query 通过输入法输入不会带入错字,所以中文 query 一般只存在 Real-word 错误,表现为漏字、多字、颠倒、谐音、形近字等。
在这里插入图片描述纠错的一种解决方案是词典匹配,通过编辑距离来筛选词典召回的结果,如果词典的覆盖度高,甚至可以达到高召回的效果。这种方法的优点在于速度快,而缺点在于效果极大依赖于词典的质量;另一种解决方案是利用输入输出皆为序列的模型,常见的模型有:

  • kenlm 统计语言工具:运用统计学方法进行语言建模从而检测和修正错误
  • rnn_attention:RNN加上attention还是一个非常有意思的方法。
  • rnn_crf模型:这个思路来自阿里2016参赛中文语法纠错比赛的第一名的方法。
  • seq2seq_attention模型:比RNN强一些,长文本效果不错,但是容易过拟合。
  • transformer:目前最强的特征抽取器之一。
  • bert:中文微调,最妙的是mask可协助纠正错别字。
  • conv_seq2seq模型:Facebook提出,在NLPCC-2018的中文语法纠错比赛中,是唯一使用单模型并取得第三名的成绩。

2.3.2 query 删除

query 删除主要是为了去除无关噪声信息和以及解决信息冗余。query删除一般有两种方法,term selection 和 term weight。

term selection主动挑选出重要的词项,要确定的是对每个词项选还是不选,而无需具体计算词项的权重分数。词项选择的实现一般可以考虑作为序列标注问题。

term weight 先尝试计算出词项的权重,再在其之上设置去词策略。一种简单的去词策略是设置阈值,低于设定阈值的词项就被丢掉;也可以用差值丢弃的方式,最小权重的词与次小权重的词的得分差值低于某阈值就丢弃;也可以利用权重占整体权重的比例进行丢弃。总之,此类方式具体实现时会有比较大的灵活性,需要根据具体情况进行优化。

2.3.3 query 扩展

Query 扩展,即通过挖掘 query 间的语义关系扩展出和原 query 相关的 query 列表,扩展的结果可以用于扩召回以及进行query 推荐帮用户挖掘潜在需求

query 扩展最简单的方式就是同义词替换,同义词一般通过人工标注的形式获取,并存储为键值对格式,当查询串出现命中时就可以完成对原查询的扩展。这种方法的难点是同义词的积累,即使是人工标注,都无法保证同义词一定全部正确。

同义词替换是一种局部改写方式,对整串的改写通常有session挖掘二部图两种方式。

session 挖掘的方法来源于用户行为分析,用户在进行搜索时,如果对当前搜索结果不满意可能会进行一次或多次 query 变换重新发起搜索,那么同一搜索 session 内变换前后的 query 一般存在一定的相关性,为此可以通过统计互信息、关联规则挖掘等方法来挖掘搜索 session 序列中的频繁共现关系,也可将其 embedding 后计算相似度。实际中 session 切分也是一个独立的研究课题,session 切分的质量极大影响最终结果。

二部图方法来源于用户的点击下载行为,用户输入 query A 并点击了结果 a,另一个 query B 也召回了结果 a 并发生了点击,那么 query A 和 query B 就通过结果 a 构成了联系,这样的关系很多,从而形成了二部图。二部图 query 和 item 之间可以通过 ctr、cvr、点击量等作为连接边的权重,然后可以训练 swing、simrank/simrank++ 等图算法迭代计算 query 间的相似度,也可以采用 Graph Embedding 的方法来训练得到 query 结点间的 embedding 相似度。

2.4 意图识别

意图识别一般可以看作文本分类问题,难点在于需要人工制定分类体系,这极大地依赖对业务的理解和经验,实现方式一般分为传统方法和基于算法模型的方法。

传统方法包括通过规则、词典、正则等方式进行识别,优点是速度快,缺点是没有利用语义信息,最终结果依赖规则、字典本身的质量。

基于算法模型的方法很多,常用的方法包括fasttext、bert微调等。

2.5 辅助步骤

2.5.1 Term 重要性分析

考虑到不同 term 在同一文本中会有不一样的重要性,在做 query 理解及 item 内容理解时均需要挖掘切词后各个 term 的重要性,在进行召回计算相关性时需要同时考虑 query 及 item 侧的 term 重要性。

term 重要性评估可以分为分级分数两种情况。对于分级的情况,重要级别最低的 term 可以考虑直接丢词,或者在索引库进行召回构造查询逻辑表达式时放宽出现限制;对于定量计算分数的情况,在 query 和 item 内容中的 term 重要性分值则可以用于召回时计算基础相关性,如简单地将 BM25 公式中 term 在 item 及 query 中的词频 tf(t)、qf(t) 乘上各自的 term 权重。

对于query 侧的 term 重要性问题,可以通过算法类方法和统计类方法来解决。
算法方面,可以将其视为一个分类或回归任务,通过训练 svm、gbdt、xgboost 等传统机器学习模型即可进行预测。麻烦的点在于训练数据的构造,一般有两种方法,人工标注和通过用户的搜索点击日志来自动构造。后者的大概做法是将 query 对应搜索结果的用户点击频次作为共现于 query 及搜索结果 title 中 term 的重要性体现。
统计类常用方法为计算TF- IDF,优势是实现简单,劣势是分数是静态的,无法考虑到不同语境下的相对重要性。除此之外还有基于规则的打分方式,结合词性、前后缀、词项长度与占比等可以设计出基于规则的打分公式。

对于item侧的term重要性问题,可以采用主题模型、TextRank 等方法来挖掘。

2.5.2 Term 紧密度分析

Term 紧密度,主要用于衡量 query 中任意两个 term 之间的紧密程度,如果两个 term 间紧密度比较高,则这两个 term 在召回 item 中出现的距离越近相对来说该 item 越相关。query 中的紧密度并不是单纯利用两个 term 之间的相对距离来衡量,也可以利用共现概率来衡量。

2.5.3 实体识别

实体识别可以看作序列标注问题,可以应用于词性标注或 term 类别标注,结果可以服务于丢词、term weight、意图识别或作为额外的特征等。实体识别常用的实现方案是词典匹配和机器学习方法。

与前面所有的词典方法一致,词典匹配的方法有点在于便捷、快速,缺点在于需要花很大精力维护词典本身的准确性。

机器学习实现实体识别的方法很多,轻量级模型包括最大熵、HMM、CRF等。复杂模型一般包括 RNN 系列模型和 tranformer 结构的模型。

3 召回

召回是根据输入的 query,能够高效的获取 query 相关的候选 doc 集合的过程。相关的 doc 如果不能被被召回,即使后面的粗排、精排做的再好也是徒劳无功。所以召回对于搜索引擎是非常重要的,决定了搜索结果质量的上限。召回策略一般分为基于词的传统召回基于向量的语义召回

3.1 基于词的传统召回

基于词的传统召回底层实现基于倒排索引,倒排索引是通过 term 查找 doc 的过程,如下图所示。
在这里插入图片描述
用户输入 query 后,首先会进行 query 理解步骤,最终得到一个个独立的 term,到倒排索引中进行查找 term 所在的文档即完成了召回。召回过程中存在一些需要注意的策略:

  • 召回截断:每个 term 查询倒排索引都会有一个倒排链,并且可以基于每个倒排索引定制一个召回分数。召回分数可以根据索引的点击量,索引的时间顺序等自定义规则进行打分,最后我们可以根据权重和召回分数大小,对于弱相关性的倒排索引召回进行截断。
  • 搜索性能:在于大数据体量的搜索内容池中,考虑到搜索性能,可以针对 term 对应的倒排链取交集,最终同时包含term1,term2…termN 的倒排索引才进行召回,减少召回量。
  • 召回多样性:召回还需要保持多样性。同一个 term 可能会召回很多不同类型的索引,仅仅根据召回分数进行截断,可能会导致召回不全或者召回不准,所以每个 term 应该在每种类型的数据项召回合适的数量,从而保证相关性和多样性。

3.2 基于向量的语义召回

基于词的传统召回方式无法召回词不同但是语义相似的结果,基于向量的语义召回方法的大体思路是将 query、item 以及其他特征 embedding 化后再计算其相似度。

解决文本相似度问题的一篇著名论文是微软在2013年提出的 DSSM(Deep Structured Semantic Model),其核心思想是基于搜索引擎的曝光点击行为数据,利用多层 DNN 网络把 query 及 doc Embeding 到同一语义空间中,通过最大化条件似然,从而训练学习得到隐层相似度语义模型,从而实现了检索召回。
在这里插入图片描述
DSSM 分别把 query 和 doc 映射成向量,然后通过余弦相似度来衡量二者的相似度,公式如下:
R ( Q , D ) = cosine ⁡ ( y Q , y D ) = y Q T y D ∥ y Q ∥ ∥ y D ∥ R(Q, D)=\operatorname{cosine}\left(y_{Q}, y_{D}\right)=\frac{y_{Q}^{T} y_{D}}{\left\|y_{Q}\right\|\left\|y_{D}\right\|} R(Q,D)=cosine(yQ,yD)=yQyDyQTyD
其中 y Q y_Q yQ y D y_D yD分别表示查询 Q Q Q和文档 D D D通过前向神经网络学到的稠密向量表示。给定查询 Q Q Q,正样本 D + D^+ D+的点击概率定义为:
P ( D + ∣ Q ) = exp ⁡ ( γ R ( Q , D + ) ) ∑ D ′ ∈ D s exp ⁡ ( γ R ( Q , D ′ ) ) P\left(D^{+} \mid Q\right)=\frac{\exp \left(\gamma R\left(Q, D^{+}\right)\right)}{\sum_{D^{\prime} \in D_{s}} \exp \left(\gamma R\left(Q, D^{\prime}\right)\right)} P(D+Q)=DDsexp(γR(Q,D))exp(γR(Q,D+))这就将相似度与点击率联系了起来,模型在学习过程中也学习到了相似度信息。最终的损失函数为正负样本似然的累乘,即:
P ( D + ∣ Q ) = exp ⁡ ( γ R ( Q , D + ) ) ∑ D ′ ∈ D s exp ⁡ ( γ R ( Q , D ′ ) ) P\left(D^{+} \mid Q\right)=\frac{\exp \left(\gamma R\left(Q, D^{+}\right)\right)}{\sum_{D^{\prime} \in D_{s}} \exp \left(\gamma R\left(Q, D^{\prime}\right)\right)} P(D+Q)=DDsexp(γR(Q,D))exp(γR(Q,D+))
自 DSSM 提出后,双塔结构就成了应用在搜索召回领域中的主流结构,query 和 item 分别对应一个 model tower。

  • query 端的 model 输入包括 query tokens、user profile 以及 user history events等特征;
  • item 端包括 title tokens、category 等特征;
  • 离线部分:使用 item tower 训练好后倒出的 item embedding 构建索引;
  • 在线服务:使用 query tower 实时计算 query embedding,然后在线召回;
    除了多层感知机之外,CNN、RNN、transformer 等模型都可以作为编码器模型。

3.3 训练目标

上面说到的 DSSM 最终将问题转化成了一个多分类任务,除此之外还有其他形式,一般可以分为 pointwise、pairwise、listwise。

3.3.1 Pointwise

Pointwise 排序是将训练集中的每个 item 看作一个样本获取 rank 函数,主要解决方法是把rank问题转换为单个item的分类或回归问题。

例如将问题转化为二分类,训练的样本被组织成为一个三元组 ( q i , c i , j , y i , j ) \left(q_{i}, c_{i, j}, y_{i, j}\right) (qi,ci,j,yi,j),其中 q i q_i qi表示query, c i , j c_{i,j} ci,j表示一个候选的 item, y i , j y_{i,j} yi,j为一个二类值,表示该候选item是否为正确(或是否被点击等等)。

这样就把问题转化为了一个二分类问题,训练的目标就为最小化数据集中所有 query 和候选 item 对的交叉熵。在预测阶段,二分类模型输出的概率被用来排序每一个候选答案,选取最 top-ranked 的句子作为正确回答。

当训练标签为相似度时问题就转化为了回归任务。

3.3.2 Pairwise

Pairwise 排序是将同一个查询中两个不同的 item 作为一个样本,目标在于给定 query 后,从一对候选 item 中学习分类任务到最佳 item。训练的样例为 ( q i , c i + , c i − ) \left(q_{i}, c_{i}^+, c_{i}^-\right) (qi,ci+,ci),其中 q i q_i qi表示 query, c i + c_{i}^+ ci+表示一个正向候选的 item, c i − c_{i}^- ci表示一个负向候选的 item。具体的损失函数不是完全固定的,可以根据不同细节进行设计调整,一个例子是合页损失:
L = max ⁡ { 0 , m − h θ ( q i , c i + ) + h θ ( q i , c i − ) } L=\max \left\{0, \quad m-h_{\theta}\left(q_{i}, c_{i}^{+}\right)+h_{\theta}\left(q_{i}, c_{i}^{-}\right)\right\} L=max{0,mhθ(qi,ci+)+hθ(qi,ci)}其中 m m m为边界阀值,目的就是促使正确答案的得分比错误答案的得分大于 m m m

3.3.3 Listwise

pariwise 和 pointwise 忽视了一个情况就是从一系列候选 item 中的预测问题。在 listwise 中单一训练样本的组成为:query 和它的所有候选 item。在训练过程中根据损失函数构造方式的不同,listwise 类可以分成两类直接基于评价指标的算法,间接基于评价指标的算法。

直接优化 rank 的评价指标是最直观的方法,但需要注意的问题是评价指标达多都是离散不可微的,对应的策略有优化评价指标连续可微的近似或上界,或者使用非平滑的目标函数。

间接基于评价指标的方法不再使用和评价指标相关的 loss 来优化模型,而是设计能衡量模型输出与真实排列之间差异的 loss。

3.3.4 多路召回

多路召回策略就是指采用不同的策略、特征或者简单模型,分别召回一部分候选集,然后再把这些候选集混合在一起后供后续排序模型使用的策略。常见的多路召回策略如下:

  • 原始 query 召回:利用原始 query 进行词匹配召回
  • 二次召回:原始 query 的情况下,must 词语放宽要求
  • 改写 query 召回:利用改写后的 query 进行词匹配召回
  • 全匹配召回:原始 query 的情况下,所有词都是 must 词
  • title 语义召回:利用文章 title 进行语义召回
  • content 语义召回:利用文章内容进行语义召回

4 排序

排序阶段会进一步减少候选集并最终将结果列表展示给用户,一般分为粗排、精排、混排和重排,当然并不是所有系统都必须包含这四个阶段。

  • 粗排阶段使用较少的特征、简单的模型或规则对候选集进行粗粒度排序。粗粒度排序过程较快,主要作用为选出较好的候选集进行后续的细粒度排序,将质量不相关的结果放置到后面。
  • 精排是对粗排结果的前 N 个进行细粒度排序。这一层会利用更多的特征,更复杂的模型进行排序。
  • 混排目的是对用户可能点击的不用类别的物料进行混合排序,例如视频、文字、相关商品等,将更有可能点击的物料排在前面。
  • 重排一般作为最后一步排序,目的是优化极少量候选集的展示顺序或是某个垂类内候选集的展示顺序。
  • 业务规则:真实业务下场景往往非常复杂,在有限的数据下算法模型无法对用户行为和心理精准建模,所以需要一些业务规则在最后对结果进行最终微调。

排序模型建模目标一般是ctr预估、cvr预估、购买概率等,损失函数的设计模式一般遵循上一章提到的 pointwise、pairwise、listwise。模型的发展历程大致可以总结为以下步骤:

  • 以 LR、FFM 为代表的传统机器学习算法,优势在于模型简单轻量级,模型原理可解释性强。
  • 以 GBDT、XGBoost、LightGBM 为代表的树集成模型,相比 LR 和 FMM 来说,树集成模型可以实现自动化的高阶特征组合,具有较好的表现能力。其中 FaceBook 提出的 GBDT+LR 的思路是一个经典方法。
  • DNN 等深度学习算法,具有优秀的非线性表达能力以及深度特征挖掘的能力。
  • 强化学习,可以自定义奖励机制,更好的贴合复杂业务目标;具有「探索与利用」的能力,有利于丰富结果的多样性;天生对列表建模友好;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值