seq搜索引擎优化至少包括那几步?(知乎搜索文本相关性的演进(一)|Before)
优采云 发布时间: 2022-02-16 17:21seq搜索引擎优化至少包括那几步?(知乎搜索文本相关性的演进(一)|Before)
01
知乎搜索文本相关性的演变
1. 文本相关性的演变
让我们首先在 知乎 搜索中引入文本相关性。在搜索场景中,文本相关性可以定义为用户的搜索查询意图与召回的文档内容之间的相关程度。我们需要通过不同的模型来模拟这种相关程度。总的来说,文本的相关性一般可以分为两个维度,字面匹配和语义相关。知乎搜索中文本相关性模型的演进也是从这两个方面出发,重点发展。在知乎搜索的整个架构中,文本相关模型主要定位于为第二轮细排模型提供更高维度/抽象的特征,同时也考虑到一些召回相关的工作。
2. NN 之前
知乎搜索中文本相关性的整体演变可以分为三个阶段。在引入深度语义匹配模型之前,知乎搜索的文本相关性主要是基于TF-IDF/BM25的bag-of-words模型。下图右侧是BM25的公式。词袋模型通常是一个系统项目。除了需要人工设计公式外,在统计词重和词频的基础上,还需要覆盖、扩展同义词、紧密度等各个模块的协调,才能达到更好的效果。知乎搜索相关性的早期版本对此进行了迭代。右下部分展示了一些基于词袋模型可以参考的具体特征。
3. BERT 之前
无论基于BM25的词袋模型是如何设计的,它主要解决的是文本相关性中的文字匹配问题。第二阶段引入的深度语义匹配模型侧重于解决语义相关问题,主要分为双塔表示模型和底层交互模型两部分。微软的 DSSM(左下)是典型的双塔模型。双塔模型使用两个不同的编码器分别得到query和doc的低维语义句向量表示,然后为这两个语义向量设计一个相关函数(如余弦)。DSSM摆脱了词袋模型复杂的特征工程和子模块设计,但也存在先天缺陷:query和doc的语义表示是通过两个完全独立的encoder得到的,两个固定的向量不能动态拟合doc在不同query中的不同表示。这反映到最终的准确性上,肯定会有一些损失。
底层交互模型在一定程度上解决了这个问题。这种交互主要体现在query和doc term/char交互矩阵的设计上(中),使得模型能够在靠近输入层的地方获取query和doc的相关信息。在此基础上,采用不同的神经网络设计实现特征提取,得到query-doc对的整体表示,最后通过全连接层计算出最终的相关性得分。Match-Pyramid(右下)和KNRM(右上)是交互模型的代表设计。我们在这两种模式的基础上进行了一些探索和改进。与传统的BM25词袋模型相比,我们取得了更好的效果。很大的进步。
4. BERT
由于转换器结构,BERT 模型具有非常强大的文本表示能力。在第三阶段,我们介绍了 BERT 希望进一步提高 知乎 搜索中文本相关性的表型。BERT的应用也分为表示模型和交互模型。
对于交互模型,如下左图,query和doc分别是sentence1和sentence2,直接输入到BERT模型中。BERT作为一个整体encoder得到句子对的向量表示,然后通过全连接层得到相似度得分。因为每个doc都依赖于query,每个query-doc pair都需要在线实时计算,消耗大量GPU机器资源,对整体排序*敏*感*词*能影响比较大。
基于以上原因,我们也做了一个类似DSSM的表示模型,使用BERT作为编码器,在输入层不区分训练数据中的每个query和doc,作为不同的句子输入,每个句子都是获得。向量表示,然后做两个表示向量的点积,得到相关分数。通过大量的实验,我们最终采用了BERT输出token序列向量的平均值作为句子向量的表示。从交互模型到展示模型的折衷本质是空间换时间,因为doc离线可以完全计算存储,在线只需要实时计算比较短的query,然后doc直接通过查表,节省大量在线计算。与交互模型相比,准确性有部分损失。
02
BERT 搜索在 知乎 上的应用和问题
1. 搜索业务架构中的 BERT
在下图中,我们可以看到BERT在搜索业务的召回和排序阶段扮演着重要的角色。交互模型主要服务于二轮细排模型,依靠query和doc的在线实时计算为细排模块提供关联特征。表示模型分为在线和离线两部分。在线表示模型为用户输入的查询提供实时的句向量表示,离线表示模型对库中的doc进行批量句向量计算。一方面,doc vector采用TableStore/TiDB和Redis的两级存储设计,为在线排序提供查询服务;另一方面,faiss 用于为批量文档向量构建语义索引,
2. BERT 表示模型语义召回
我们在下面详细介绍我们的语义召回模型。我们先来看一个例子。以“玛莎拉蒂ghlib”为例,用户真正想搜索的是“玛莎拉蒂吉卜力”这辆车,但用户一般很难记住全名,可能会出错。在输入错误的情况下,基于传统的词条匹配方法(以谷歌搜索为例),只能召回与“玛莎拉蒂”相关的doc,但无法进行该车型的召回。在这种情况下,需要语义召回。更一般地说,语义召回可以理解为增加对字面上不匹配但语义相关的文档的召回。
语义召回模型作为一个整体是两塔表示模型在BERT相关任务中的应用。BERT 用作编码器来表示查询和文档向量。在faiss的基础上,为全文档向量构建语义索引,查询向量用于在线实时召回。该策略上线后,在线top20文档中语义召回的文档数量占召回文档总数的5%+。
3. BERT 的问题
BEER模型推出后,为不同的模块取得了不错的收益,但也给整个系统带来了很多问题。这些问题可以概括为三个方面:在线实时计算、离线存储、模型迭代。详情见上图。
4. 蒸馏前的尝试
针对上述性能或存储问题,我们在提炼 BERT 之前也做了很多不同的尝试。
BERT交互模型的部署摒弃了原生TF服务的使用,而是在cuda的基础上用C++重写了模型的加载和服务,加上混合精度的使用。在我们的业务规模上,在线实时性能提升到原来的1.5倍左右,使得BERT交互模型满足最低在线要求。在此基础上,在线 BERT 表示模型中加入缓存,减少了约 60% 的请求,有效降低了 GPU 机器资源的消耗。
另一个想法是尝试在水平和垂直维度上缩小 BERT。横向上,一方面可以减少serving期间max_seq_length的长度,以减少计算量;另一方面,可以对表示向量进行维度压缩以减少存储开销。两次尝试都在离线和在线指标上遭受了不同程度的损失,因此被放弃了。纵向上,主要目的是减少模型的深度,即减少transformer层数。这可以针对视频内存和计算进行显着优化。前期尝试直接训练一个小模型,使用几层BERT-base对下游相关任务进行微调。对于这两种方案,离线指标的表现都不能满足要求,
针对文档数量过多、存储开销过大、语义索引构建速度慢等问题。对此,做了一个折中的解决方案:通过wilson score等规则过滤掉大部分低质量的doc,只存储表示向量,为大约1/3的doc建立语义索引。这种方案会导致一些文档的相关特征缺失。针对表示模型交互性低的问题,尝试Poly-encoder(Facebook方案)将固定的768维表示向量转化为多头的形式,并使用多头进行attention计算,保证性能部分降低在获得部分准确度提升的前提下。
03
知识蒸馏和常见解决方案
1. 知识蒸馏
下面简单介绍一下知识蒸馏。从下图中,我们可以将知识蒸馏的整体形式简化为:大模型在不考虑性能问题的情况下学习尽可能多的知识(数据),小模型通过适量的学习高效学习大模型的输出的数据以达到知识转移的效果。实际服务使用小型模型。
为什么知识蒸馏有效?关键点是软目标和温度。软目标对应于教师模型的输出,类似于概率分布。知识蒸馏从硬目标到软目标的转移有利于模型更好地拟合标签。温度的引入是为了进一步平滑标签,让模型学习到类别和类别内的知识。这里需要注意的是,温度的选择不宜过大。太大的温度会导致不同类别之间的差异被完全抹平。
2. BERT 蒸馏协议
我们对 BERT 的蒸馏做了很多研究,并对目前主流的蒸馏方案进行了归纳和分类。基于任务维度,主要对应目前pretrain+fine-tune的两阶段训练。预训练阶段和下游任务阶段涉及的方案很多。在技能方面,主要包括不同的迁移知识和模型结构的设计。后面我会简单介绍两个典型的模型。
3. 蒸馏 - MiniLM
MiniLM是一种基于预训练任务的蒸馏,是一种通用的基于Transformer的预训练模型压缩算法。主要改进点有3个,一个是蒸馏教师模型最后一层Transformer的self-attention模块,另一个是self-attention模块中values-values点积矩阵的知识迁移,以及三是利用助手网络辅助蒸馏。
4. 蒸馏 - BERT 到简单 NN
BERT to Simple NN 更多地以损失的形式设计,以使其训练方法更高效。
04
知乎BERT 蒸馏的搜索实践
1. BERT 蒸馏的实践和好处
在之前的介绍中,我提到在BERT蒸馏之前已经做了很多尝试,但是会有一些准确性的损失。因此,我们蒸馏的第一个目标是与在线 BERT 相比,离线模型的准确性没有损失。但是没有办法通过直接蒸馏BERT-base来避免准确性的损失,所以我们尝试使用更大的模型(例如BERT-large/Robert-large/XLNET)作为teacher进行蒸馏。这些多层模型在我们的 知乎 完整语料库中进行预训练,然后进行微调,然后对微调后的模型进行提炼。
2. 蒸馏 - KD 患者
我们提炼了交互模型和表示模型,主要使用了Patient KD模型的结构设计。Student模型是基于BERT-base的几层,使用不同的策略初始化参数来学习Robert-large模型的解。
知识迁移主要由三部分组成:学生预测与真实标签之间的交叉熵,学生预测与教师预测之间的交叉熵,以及中间隐藏层向量之间的归一化 MSE。
3. BERT 交互式模型蒸馏
对于我们选择的teacher模型Robert-large,纯预训练模型的nDCG指数为0.914,之前在线使用的BERT-base为0.907。直接做fine-tune可以达到的最高指标是0.903,相比BERT-base会损失很多准确率。
我们在这方面做了一些尝试。基于 Robert-large 从 24 层蒸馏到 6 层,可以达到 0.911,可以超过在线 BERT-base 的效果。
在训练数据方面,我们经历了点击日志数据挖掘,逐步建立了完整的标注数据集。目前,相关任务训练和蒸馏主要基于标记数据集。标注数据分为标题和内容两部分。查询数量达到10w+规模,标注文档在300w到400w之间。
4. BERT 代表模型蒸馏
在 BERT 表示模型上,我们希望在蒸馏过程中同时压缩向量维度和模型层数,但是蒸馏后得到的学生模型并没有达到预期的效果。因此,在最终的在线解决方案中,模型的层数仍然保持在 12 层。蒸馏过程中,为了提高准确率,选择交互模型作为teacher进行蒸馏。因为交互模型是query和doc之间的score,所以交互模型得到的logits与表示模型的点积后的score相比,交互模型得到的logits在量化值上会有很大的差异,所以loss是通过成对形式的teacher差异拟合来计算的。.
在维度压缩方面,我们做了一个对比实验。BERT 模型的输出在平均池化后压缩到 8-768 维,然后是全连接层。如图所示,128维和64维的性能与768维相差不大。上线时,我选择了64和128这两个维度来试一试,两者的上线性能并没有明显的区别。最后选择了64维的方案,将模型的维度压缩了12倍,存储消耗更低。
5. 蒸馏收益
蒸馏的好处主要分为线上和线下两部分。
在线的:
交互模型的层数从12层压缩到6层,排名相关特征P95减少到1/2,整体搜索入口减少40ms,模型部署所需的GPU机器数量也减少了减少一半,减少资源消耗。
表示模型语义索引的存储大小减少到1/4,内容维度从768维压缩到64维。虽然维度减少了 12 倍,但是倒排索引 docs 的数量增加了,所以内容最终减少到了 1/6。
语义索引召回率也大大提高,标题减少到1/3,内容减少到1/2。细排模块需要在线实时查询离线计算的向量,因此查询服务也有所提升。
离线端:
意味着模型语义索引的构建时间减少到1/4,底层知乎自研TableStore/TIDB存储减少到原来的1/6。LTR 训练数据和训练时间都得到了很大的改善。使用了BM25等基本特征,后来又引入了32维的BERT向量来提高精细排序的精度。