心法利器
本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。
2022年新一版的文章合集已经发布,累计已经60w字了,获取方式看这里:CS的陋室60w字原创算法经验分享-2022版。
往期回顾
- 心法利器[71] | NLP的学习思考(新手和进阶)
- 心法利器[72] | 有无监督的特性和选型
- 心法利器[73] | 科研和落地之间的差别
- 心法利器[74] | 技术分享中的技术陷阱
- 心法利器[75] | 相似、搜索和问答对匹配问题的差异
检索是一个非常经典的问题,从检索的内容出发,目前已经被分为向量检索和字面检索这两个分支,在深度学习流行之前字面检索可以说是一统天下,而现在随着深度学习的逐渐深入,对文本的表征能力加强,加上多模态信息的加入,向量检索更容易被大家选择,今天我就来和他家讨论一下这两者的差别,并给出一些方案选择上的建议。
两种方案的主要概念
首先先明确一下检索的概念,根据《信息检索导论》中的说法:
信息检索是从大规模非结构化数据(通常是文本)的集合(通常保存在计算机上)中找出满足用户信息需求的资料(通常是文档)的过程。
说人话,就是从大海里找出我要的那根针(抱头痛哭)。
对于我们一般看到的搜索场景,最常见的就是两种,一种是直接拿着文档直接构造索引,然后用文本直接去搜,即字面索引,另一种是文档用向量来表征,构造向量索引,文本则也用向量来表征,进行检索。
先来讲字面检索。对于文档,一般是切好词后,那去构造倒排索引存到库里面去,这是离线的任务,在线的话就对query进行切词,切好后拿去搜库里面最近的结果,具体的方案大家看看倒排索引的原理就好了,难度不是很高,即使自己手写一个基础的也不会很复杂,但其实没啥必要,一般要用到检索了,数据量就不会小,分布式的方式来做会更好些,常用的就是ElasticSearch,可以直接用这个其实就比较好了。
向量检索,之前有一篇文章有详细讲过,这里不赘述了:心法利器[16] | 向量表征和向量召回。
字面检索的优缺点
字面检索作为最早期搜索的主流方法,即使在今天,也没有被完全淘汰,自然是有他的很多优势的,先列举一下:
- 字面的可解释性高,对应的也是可控性强。
- 准确率相对高,召回的内容可靠程度高。
- 字面检索对很多基础工作有要求,算法上例如同义词、紧密度、改写之类的,工程上需要完善的倒排索引,但是这些问题的解决方案其实都相对成熟。
- 快速构建,对比向量检索可以不需要模型支撑(向量检索刚需表征模型),这也让性能需求降低,上线压力小。
- 基础的检索,不需要进行模型训练,不需要训练数据。
但是,当然也是有缺点的,我也列举一下:
- 局限在字面,因此泛化能力刚需各种支持工作,例如同义词、紧密度、改写等,所以天花板较低,而且后续的维护和提升基本都局限在这里。
- 基础工作的展开,类似意图识别、NER之类任务的加入,是有利于就准确率提升的,但是就是会有依赖。
- 字面依赖高后,不分内容召不回会导致需要构造更多的文档来保证答复率或召回率,因此文档数量会提升,存储压力加大(当然这个量可能早期不会很高)。
- 泛化能力不足,召回率不足。
这么看,评价起来其实就是字面检索其实有很高的下限,在项目初期的时候其实挺推荐用字面检索的方案来处理大量的问题,而且可控性高。
向量检索的优缺点
向量检索是现在大家都聊的比较多的问题了,口碑没什么问题的。那么展开聊一下他的优劣势吧。首先是优点:
- 精准度尚可,泛化能力高,能匹配到很多同义词、新说法之类的。
- 相比字面检索,对基础工作的要求不会很高,同义词、紧密度、改写等要求不高(当然在模型训练是还是可用来做数据增强的)。
虽然有点比较少,但是这两个收益就已经足够大,前者其实能让有限的数据被更多召回,而后者看上去则降低技术工作的成本,这也是很多人其实更倾向于选择这个类型的方法作为首选,但其实会有些缺点:
- 强依赖表征模型的效果,下限很低。
- 开放域固然可以使用训练好的开放域模型,但是对于自己的特定领域,或者有些业务需求,是需要依赖数据的。
- 调优成本高,模型训练、模型切换、重构索引等,可控性低。
- 因为要模型,性能这个问题自然就要被关注起来。
- 有些特定问题向量检索不合适或者不优先,例如“筛选年龄18岁以上的人员”之类的检索要求。
可以看到,其实这是个不太泛用且不太可控的方案,但其实因为很多客观原因可能并非是真正的万能解。一分为二吧,其实更像是一个在某些场景下锦上添花的方案,能在一定场景下快速提分。
两者的选型策略
我对这俩整体的选型策略,其实和之前我一些别的问题里的思路是类似的:
- 初建项目,首先考虑字面检索。
- 逐步完善字面检索的各种基础工作,确保准确(宁可不出,不要出错)
- 随着泛化能力的逐渐暴露,开始考虑上向量检索。两套方案并行形成多路召回。
- 优化两者协同性,开始考虑重点优化精排等部分。
这整套思路,其实是有一定的原因的。
首先,初建项目,大多有如下特点,因此,其实我更推荐优先考虑字面检索。
- 排期紧,且算法还要承担一定的功能和基础工作开发,没有太多时间关注算法效果,能达到baseline已经不错了。
- 缺少足量可靠的训练数据,模型训练难度很大。
- 质量需要严格把控,对高频的关键的部分,要求预测的是更精准的。所以准确率往往比召回率要求更高。
一阶段结束后,通过case分析等方案定位问题,一定要做,确认好当下的关键问题再来确定技术方案。例如关注面对于高频的精准需求是否已经足够处理,如果不够则需要通过意图识别、NER等优化检索召回的能力,再例如关注未召回的看是否是因为说法或者泛化能力不足,如果占比比较高了就可以开始准备上向量召回了。
对于前者,就是有些基础工作的完善,例如精准的意图识别、NER(当然,意图识别、NER也不只是只有模型这一种方法,各种策略也可以用的,重点是能从局子里抽得出东西来),或者是同义词挖掘、词典挖掘等能力,如果因为缺少这部分而导致效果不好,那就需要优先把这个搭建起来,原因如下:
- 通过实体槽位的准确召回,构造更加精准的查询语句,例如直接约束"movie_name=钢铁侠2",肯定比直接搜全文更加精准,避免类似“复仇者联盟”下有些介绍可能也会提到钢铁侠之类的误召,这种方式其实能进一步提升召准。
- 有一些需要同义词、改写的部分,这些操作其实不做,跳过这个去做向量召回,也不见得就能召的回来,因此优先级其实不是很高。
- 这里很多基础工作,其实都是在尝试为这个检索系统加入很多精准的知识信息,这些信息如果不提供,什么方法模型都是解决不了这种问题的,就跟没有火药,手枪大炮都发挥不出来。
在基础工作完善以后,可能通过补充词典知识、各种精准信息的抽取已经对整体效果没有太大空间时,就是考虑引入向量召回的时机了,这点和我之前写的心法利器[63] | 预训练模型的上线时机的思路其实很类似。
- bad case里面大部分其实都是口语化或者是说法上的差别,导致误召或漏召。
- 此阶段,各种数据集、样本都比较多了,具备训练模型,尤其是自己场景的模型的资源了。
- 优化遇到瓶颈,原有方案的表征和学习能力已经不能支撑现有的知识和数据了,那模型就是一个很好的升级点。
上了向量检索后,我们并没有说要下掉原本的字面召回,我们设置是需要谨慎考虑两者的结合关系。具体的思路是这样的:
- 大部分情况,字面检索的准确率更高,所以其实整体排序优先级上,不应该低于向量召回。更不要说下掉字面检索了,可以跑跑离线数据,测一下两者的重要性或各自单独使用下的准确情况。
- 要开始考虑两者的深度融合和精排模块了,例如更加深度的交互模型等,在召回层面已经可以保证“对的都尽可能找到了”的前提下,通过精排方案,让“能在这些可能对的里面尽可能找到最正确的”。
小结
本文给大家对比了字面检索和向量检索两者的优势,并根据项目迭代的阶段给出各个阶段该关注的事,希望对大家有所收获。