🍊句子表征优化小结
向量召回本身是个新潮的东西,这次给大家小小的总结一下,工业界和科研界中常见的向量召回方案,希望能给大家一些启示吧。
前沿
首先,什么是向量召回,核心的流程是什么样的,先介绍下。首先,所谓向量召回,就是把物料和用户query都进行向量表征,物料可以构造索引供query向量进行检索,本质还是在库里检索和query最接近的那些物料,相当于推荐中的一路召回。
由于深度学习的逐渐深入,这种泛化的向量表征方式也成为了大家尝试的方向,更有比较激进的在尝试直接跳过字面的召回而直接选择向量召回的方式,可见该方式的热门程度,大家所关注的,就是他对特征的要求低,而且泛化能力强,所以也就成为了“香饽饽”。
那么,工业界和科研界到底是怎么做的,有没有什么先进的思路可以考虑,本文会分模块地详细总结,并给出一些大家一些思路吧。当然,我对图深度学习、图谱等不太熟悉,本文先不聊,主要就是聊双塔。
文章整体思路是这样的(懒人目录):
- NLP技术下的QQ匹配
- 工业界Query塔的表征
- 工业界物料塔的表征
- 难负例的挖掘
本文是综述,不会把每篇文章都展开讲,也不会列举出这个角度的所有文章,而是大概描述文章的特定亮点,并进行总结,说到的参考资料都会放到文末,并标上序号,大家后续按需深入阅读。
NLP技术下的QQ匹配
QQ匹配是最简单而又经典的方案了,在对话系统和传统的搜索系统中非常常见,而且日渐成熟,其本质就是把query和物料放在同一个语义空间下进行训练和推理,专业说法称为语义表征。这方面的研究,我分为3个模块:
- 表征层。
- 预训练模型引入后的新问题。
- 损失函数的优化思路。
表征层
表征成的优化相信大家都比较熟悉的,始于DSSM[1],后续里面的全连接层可以换成CNN,成为CLSM[2],又可以换成LSTM,成为DSSM-LSTM[3],而后续又对这块进行了一些总结性的归纳,有了infersent[4],统一了整个框架,并给出了一些较好的训练方法。(我也在以前有聊过这里的细节,见:心法利器[7] | 漫谈语义相似度与语义向量表征)
而后,就是预训练模型的时代了,最有代表性的是Sentence-BERT[5]和SimBERT[6],这俩在我看来都是在预训练模型用于语义表征的代表之作,虽然说后续对比学习的引入让预训练在此方面的应用更加优秀了,但这两篇工作,仍旧是很有学习和吸收的价值。
SimBERT = BERT + UniLM + 对比学习
SimBERT属于有监督训练,训练语料是自行收集到的相似句对(文本1,文本2,label),通过一句来预测另一句的相似句生成任务来构建Seq2Seq部分,然后前面也提到过[CLS]的向量事实上就代表着输入的句向量,所以可以同时用它来训练一个检索任务。换句话说,对于检索任务在努力训练模型“[CLS]的向量事实上就代表着输入的句向量”,如果仅仅从相似度判断来看(相似度判断等价于检索),强制A生成B一定程度上也是在使A的表征和B更逼近。
我在中文数据集上测试过不少场景,不得不说,simBERT确实是融合了检索和生成的功能,尤其适合于相关性检索,生成的质量还有待提升
预训练模型引入后的问题
预训练模型直接做语义表征是有问题的。如Google开源的bert模型,Next Sentence作为BERT的Pretrain任务,天然提供了文本匹配的范式。一般取【cls】作为文本的feature extraction,然而,这个【cls】具备语义特征信息的前提是微调,也就是被有监督train过之后才能很好的embedding化句子。
若是讲仅通过无监督得到句子的【cls】用于匹配任务,尤其是用cos计算相似度时,实验证明即便两条相关度较低的句子依旧可以获得一定相似度得分。在论文REPRESENTATION DEGENERATION PROBLEM IN TRAINING NATURAL LANGUAGE GENERATION MODELS 中提出了了表达退化问题 (Representation degeneration problem),一定程度上解释了为什么直接用BERT是不可取的。
第一阶段是直接在预训练的表征后增加一些转化的层,比较有代表性的是bert-flow[8]和bert-whitening[9, 10],通过映射的方式把预测的结果从有问题的空间转化到正确的空间里去,所谓的正确理解可能会有所不同,个人是比较喜欢bert-whitening对标准正态分布是各向同性的这一理解,用线性的变换的方式就能轻松解决该问题。
第二阶段,是考虑直接去解决词频和训练的问题,某种程度上说,其实和数据增强类似的思路,从样本或者从训练层面进行增强,从而直接解决预测层间的空间问题,以样本增强为代表的是美团的ConSERT[11],而在模型层面或训练策略层面的增强,代表之作就是现在大家都比较熟悉的SIMCSE[12],SIMCSE 在数据集没有标注的情况下,要增强这一数据集总体的语义特性,直接利用模型的Dropout来完成这种目标,又简单又实用。流程:将数据集放入对比训练,无需标签,自监督增强语义信息。以SIMCSE为例,在STS等标准数据集下的效果,是要比作为极限的BERT要好一大截,算是继预训练模型引入之后的又一质变,甚至可以从数据中看到,无监督的方案甚至是能够逼近有监督方案的,这点其实强的蛮离谱的。
提一下,二阶段的这套思路,其实也很大程度上让NLPer意识到,对比学习可能是进一步优化语义表征的一大突破口。
损失函数的优化思路
与其说对比学习,其实我更想说是损失函数的应用。这块的NLP论文我接触的其实不多,然而是看到了这个东西在CV领域方兴未艾。
这个关注点,我其实在很久之前的文章就有聊到了,就是这篇:前沿重器[8] | CV研究启发语义相似和表征,在人脸识别领域,表征这个事情和我们现在聊的非常接近,相似度表征的训练内部其实有大量可以用来进行优化的方式,例如margin的思想能把不同类的尽可能拉开,类间的壁垒得到提高,从而提升预测性能。这块论文不在提了,直接前面我说的那篇文章吧。
人脸说完,NLP有在用吗,有的,直接给个工业界的例子吧,OPPO的小布助手在这块其实已经有应用并且落了地了,可以参考下[13],我也写过讲解:前沿重器[7] | 小布助手登顶百度千言短文本相似度的秘诀。
工业界Query塔的匹配
有关Query塔的匹配,我比较想聊的是两篇文章吧,都是KDD21的,淘宝[14]和FB[15]的,这两篇都值得稍微的展开,淘宝那篇文章我专门聊过:前沿重器[18] | KDD21-淘宝向量检索。
略……
HARD CASE挖掘
HARS CASE挖掘可以说是向量召回领域的一个特色问题,难负例本身对预测的准确性影响巨大,借此机会,分享几个挖掘方案吧。
- 用字面检索(如BM25粗排的召回)召回与query相似的样本,赋为负例。
- BATCH内,通过两两相似度矩阵进行粗排挖掘[14]。
- 正负例表征加权求和构造负类embedding[13]。
- R-dropout[17]等增强方式。
小结
上面综述了不少方法,让大家能够了解到前沿的向量召回都是用的什么做表征的,划几个重点:
- 工业界和科研界好像尚未有些不同,科研界更多关注语义的表征,预训练模型更多,工业界则更在乎多粒度的语言理解,还有用户行为。
- 科研界,在语义表征上,NLP层面预训练模型还是有很大优势。
- 多信息的组合,以及日常任务的协作,导致了工业界模型虽然都还偏大,但其实都有分多个模块,然后最终组装的模式。
- attention,因为多模块组合的原因,成了工业界的宠儿。
当然了,这里也给大家在向量召回上一些使用建议吧。
- 预训练模型并不是必须得,可以先考虑多粒度的语义理解并进行融合,这个优先级更高。
- 搜索不止有语义信息,无论是query塔还是物料塔,还会有很多信息和特征,前者有用户历史行为,后者有多模态和其他物料特征。
- 向量召回不太能是唯一的召回方案,字面召回还是建议保留,这点在[13]的架构图里有体现,我上一篇文章也有聊这个问题:心法利器[62] | 向量召回和字面召回的选择与权衡。