搜索中的NLP技术

搜索技术除了涉及基础的搜索算法,也涉及到很多NLP技术,本文转载于只是做个学习记录,侵删。

推荐系统被捧为目前算法领域的主流,推荐系统不需要用户主动进行操作就能获取自己喜欢的东西,但是实际上,搜索系统在很长一段时间占据了重要位置,大到百度的大搜,小到音乐、视频、电商、应用商店等,都有各种各样的搜索引擎,这些搜索搜索能更为精准直接的满足用户需求,即使是推荐系统如日中天,目前也仍会有搜索的一席之地。今天我来为大家介绍,搜索系统中涉及的算法问题,也让大家了解,搜索中需要什么算法。

数据预处理模块

这个很好理解吧,用户query进来,一般要做如下处理:

  • 大小写转化。

  • 删除标点符号(当然有的分析会保留标点,但是建议在这个场景下还是去掉更好)。

  • 繁体转简体。

  • 数字处理,转中文,转阿拉伯数字,甚至罗马字等,部分情况要删除数字。

  • 长度截断。(总不能让用户输入一本西游记,然后你还在整吧?)

理解模块

query理解其实是一个非常重要的模块,好的query理解能为后续的工作提供很大的支持。这部分往往不直接应对下游,而是按需使用,有点像辅助吧。

  • 分词。基操。

  • 关键词抽取。会涉及丢词、排序等功能。

  • 命名实体识别。一方面协助用户识别,另一方面可能会涉及数据库查询匹配的内容。在垂搜中比较常见,大搜也有但是相比之下没那么精准和常见。

  • 紧密度分析,避免由于切词出现错误导致词义偏移的问题,这个其实并不少见,尤其是在人名上,这个是别的精准度会很低,近期的如“武大靖”,会被分为“武大 靖”,“曾舜晞”直接被分为了3个字,挺头疼的。

  • 非法信息过滤。例如黄色、暴力血腥、反动等。

改写模块

改写模块其实非常关键,这是连接用户query和数据库底层数据的桥梁,数据库的存储有特定的形式,但是用户不会按照你的底层数据结构去写,例如,用户不见得会输入和平精英,而是吃鸡,数据库里可不见得会存吃鸡对吧,所以这块很重要。

  • 同义词改写。上面的吃鸡就要改写为和平精英,这个需要通过同义词挖掘等方式去构造词典实现。

  • 拼音改写。数据库是罗密欧与朱丽叶,但是用户输入的是罗密欧与朱莉业,拼音改写其实颇为常见,用户经常由于找不到需要的结果或者不知道应该需要哪个,于是直接输入后开始搜索。

  • 前缀补全。非常常见,用户输入射雕,射雕英雄传就要出了,这个一般的方法也是构造词典,另外有一个很重要的需要了解的就是前缀树,这个能让你查询的时间非常低的水平(只和query长度本身有关)。

  • 丢词和留词。结合上述关键词提取和命名实体识别完成,有些不必要的词汇需要被删除,例如“李小璐到底怎么了”,整个句子只有李小璐是关键词,其他词如果也通过and逻辑召回,就没有信息召回了,这时候其实可以直接删除或者将降级到or逻辑。留词和丢词相反,丢词如果是做减法,留词就是做加法。

  • 近义词召回。这个召回不是从数据库中召回,而是召回近义词,具体的方法是通过embedding方法转化词汇,然后通过ball tree、simhash的方式召回与之意思相近的词汇,该模式虽然比较激进,但是能一定程度增加召回,有一定效果。

  • 意图识别。与其说是意图,我更喜欢理解为这是直接针对底层数据结构产生的需要解决的问题,query这是一条,但是数据库有好几个,我们要去哪个数据库搜,这是需要识别的,而这个数据库的设计往往和品类、意图有关,找酒店、找景点都是不同的,所以此时就要进行意图识别,一般地方法是抽象为文本分类,但是很多时候语义本身是无法体现出真实意图的,例如少年的你,语义上其实很难分析出,有时候更复杂的会夹带一些实体识别、词性、词典之类的信息。

召回模块

结合命名实体识别、改写结果,然后开始召回,模式比较多,包括但不限于下面形式:

  • Elastic Search,著名的搜索平台ES,有些时候甚至简单的搜索平台直接用它管整个搜索引擎但是要精做,就只能把它当做底层的数据库和搜索平台。

  • 关系数据库。MySQL之类的,但是在我的理解速度和并发性都不是特别好。

  • Redis。KV形式的数据库,速度很快,但是Key匹配必须是精确匹配,这需要改写模块具有很强的能力。

说白了,就是把用上面流程处理过的query放到数据库里面查,这个其实就是召回。

排序模块

内容是召回回来了,其实怎么展现给用户呢?这里是需要深度挖掘用户的实际需求的,很多时候甚至需要做个性化,但是更多时候是我们能够得到的只有短短的一句用户query,那么,我们就要好好利用好这个query,来做好排序,让用户喜欢的(当然,还有广告商喜欢的哈哈哈)东西放在前面,实际上就是一个学习排序的问题了,这个我之前也做过一些简单的介绍,那么在特征层面,可以考虑如下的信息:

  • query层面:

本身的embedding,后续迭代可以走elmo后逐渐形成的pre-train的模式。

词性、实体、词权重、offset等序列标注得到的结果。

  • document层面。

如果文档本身有文本,最好是标题类的,也把embeding引入,和query层面那种一样。如果只有query文本和document文本,其实就是个文本相似度模型了对吧。

  • 综合层面:

query和document的ctr、cqr、bm25,句向量余弦相似度等匹配信息。

  • 其他层面:

意图识别结果。

模型上,DSSM系列似乎是比较流行的方法,但是提取一些特定的特征,有点的时候简单的LR、XGBOOST就能一定程度把问题解决好了。

而在排序模块中,还会涉及一些硬规则等。

搜索引导模块

query suggestion是一个上述搜索过程非常类似的模块,只不过处理的结果大部分是放在离线,在线是指一个查字典的过程,那么离线部分,其实是做了一整个搜索过程的:预处理、query理解、改写、召回、排序。

  • 预处理:和上面的预处理类似,不赘述。

  • query理解,和上述内容类似,但是有的时候会简化,直接进入改写模块。

  • 改写模块,会进行容忍度更高的前缀匹配,去找回一些用户可能会喜欢的内容,这时候往往还会带上统计特征,从整体层面上看用户喜欢的内容,毕竟不同时间用户喜欢的可能不同,例如对热点新闻的偏好。

  • 召回和排序模块。召回模块不是召回数据了,而是召回相似的doc信息,也可以是相似的历史用户query,尤其是后者,如果是后者,则要确认历史用户query是有结果的。

其他辅助模块

显然,整个搜索系统远远不止这些内容,在算法视角下,其实还需要很多辅助模块协助我们进行算法开发。

  • 日志模块。无论是线上的运行日志,还是线下的模型实验和离线模型运行,都需要日志协助,对于线上运行和离线模型运行而言,出现错误可以方便追溯,找到ERROR出现的时间和具体问题,而线下的模型试验能方便我们计算运行时间、找到bug,而非每次训练模型的时候功亏一篑才来找问题。

  • 实验模块。由于算法策略存在很多不确定性,无论是算法内存占用和时间,还是算法实际结果,因此需要利用AB实验的方式来验证,快速进行分析,对有问题的算法及时下线检查原因。

  • 数据分析和报表模块。结合实验模块,需要对日常用户数据进行分析,这个比较好理解,不赘述。

  • 特征生产模块。特征生产涉及两块,一个是线上的实时计算,对于一些实时数据,是需要即时生成的,例如微博热搜里面就需要一些诸如5分钟搜索量之类的特征,这个只能从实时计算模块中获取;另一个是离线模块,为了进行离线模型训练,需要定时将生肉(原始数据)转化为特征,方便进行下一步计算,如果这个能变成日常任务,那开发人员就不需要临时造轮子执行,还要长时间等待。

  • 定时任务模块。很多任务其实是定时开始的,报表生成、特征生产,甚至是一些实时任务(说白了就是短时间内的计算),因此有定时任务模块去管理这些定时任务,将会非常方便。

  • 模型管理模块。首先一个项目中可能存在大量模型,然后因为各个模型训练需要花费大量资源,还要结合AB试验,另外还有模型的更新和保存机制(防止模型加载失败导致的无模型可用),因此需要构建模型模块统一管理模型,这个不是每个部门都有,或者说每个模型都是各自管理,但是有一个比较好管理模型平台是非常高效的。

  • 数据平台。额,简单地说就是写SQL的地方,但是也有类似ETL之类的内容,和特征生产模块很接近。

小结

搜索作为一个完整地系统,难度甚至比搜索要困难,在更多的场景下,搜索系统只能针对短短几个字的query进行分析,从而在海量数据中找到用户需要的东西,而由于是用户主动输入的,所以用户的预期非常高,但因为是用户主动的行为,所以不会太过复杂,甚至可能会有各种各样的歧义,只有详细分析和挖掘才能得到,因此在我看来,搜索这个事情非常具有挑战性,即使这个东西已经发展多年,年龄比推荐系统更大,还是很多可挖掘的地方。

Author: CinKate
Link: http://renxingkai.github.io/2020/12/26/searchandnlp/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.