概述
传统方法
- 基于TF-IDF、BM25、Jaccord、SimHash、LDA等算法抽取两个文本的词汇、主题等层面的特征,然后使用机器学习模型(LR, xgboost)训练分类模型
- 优点:可解释性较好
- 缺点:依赖人工寻找特征,泛化能力一般,而且由于特征数量的限制,模型的效果比较一般
代表模型:
- BM25
BM25算法,通过候选句子的字段对qurey字段的覆盖程度来计算两者间的匹配得分,得分越高的候选项与query的匹配度更好,主要解决词汇层面的相似度问题。BM25也是Elasticsearch使用的检索算法。
深度方法:基于表征的匹配
-
基于表征的匹配方式,初始阶段对两个文本各自单独处理,通过深层的神经网络进行编码(encode),得到文本的表征(embedding),再对两个表征进行相似度计算的函数得到两个文本的相似度
-
优点:基于BERT的模型通过有监督的Fine-tune在文本表征和文本匹配任务取得了不错的性能
-
缺点:BERT自身导出的句向量(不经过Fine-tune,对所有词向量求平均)质量较低,甚至比不上Glove的结果,因而难以反映出两个句子的语义相似度
主要原因是:
1.BERT对所有的句子都倾向于编码到一个较小的空间区域内,这使得大多数的句子对都具有较高的相似度分数,即使是那些语义上完全无关的句子对。
2.BERT句向量表示的聚集现象和句子中的高频词有关。具体来说,当通过平均词向量的方式计算句向量时,那些高频词的词向量将会主导句向量,使之难以体现其原本的语义。当计算句向量时去除若干高频词时,聚集现象可以在一定程度上得到缓解,但表征能力会下降。
代表模型:
- DSSM(2013)
- CDSSM(2014)
- ARC I(2014)
- Siamese Network(2016)
- InferSent(2017)
- BERT(2018)
- Sentence-BERT(2019)
- BERT-flow(2020)
- SimCSE(2021)
- ConSERT(2021)
- CoSENT(2022)
由于2018年BERT模型在NLP界带来了翻天覆地的变化,此处不讨论和比较2018年之前的模型(如果有兴趣了解的同学,可以参考中科院开源的MatchZoo 和MatchZoo-py)。
所以,本项目主要调研以下比原生BERT更优、适合文本匹配的向量表示模型:Sentence-BERT(2019)、BERT-flow(2020)、SimCSE(2021)、CoSENT(2022)。
该类模型适合召回。
深度方法:基于交互的匹配
- 基于交互的匹配方式,则认为在最后阶段才计算文本的相似度会过于依赖文本表征的质量,同时也会丢失基础的文本特征(比如词法、句法等),所以提出尽可能早的对文本特征进行交互,捕获更基础的特征,最后在高层基于这些基础匹配特征计算匹配分数
- 优点:基于交互的匹配模型端到端处理,效果好
- 缺点:这类模型(Cross-Encoder)的输入要求是两个句子,输出的是句子对的相似度值,模型不会产生句子向量表示(sentence embedding),我们也无法把单个句子输入给模型。因此,对于需要文本向量表示的任务来说,这类模型并不实用
代表模型:
- ARC II(2014)
- MV-LSTM(2015)
- MatchPyramid(2016)
- DRMM(2016)
- Conv-KNRM(2018)
- RE2(2019)
- Keyword-BERT(2020)
Cross-Encoder适用于向量检索精排。
典型算法介绍
DSSM
先来看其结构,DSSM分成了三个部分,embedding层对应图中的Term Vector,Word Hashing,特征提取层对应图中的,Multi-layer,Semantic feature,Cosine similarity,还有输出层Softmax,我们针对这三部分分别讲解。
embedding层
这里我把图中的Term Vector和Word Hashing都归在了embedding层,Term Vector是文本转向量后的值,论文中作者采用的是bag-of-words即词袋模型,我的代码中会采用one-hot的形式。然后是Word Hashing层,英文主流文本转vector的方式更多是采用embedding,但是该方法有一个致命的问题就是会出现OOV的问题,而作者提出了一种word hasing的方法,该方法一方面能降低输入数据的维度,其次也能保证不出现OOV的问题,接下来我们详细看下其原理。
word hashing
这里以good这个单词为例,分为三个步骤
- 在good两端添加临界符#good#
- 采用n-gram的方式分成多个部分,如果是trigrams那么结果是[#go, goo, ood, od#]
- 最终good将会用[#go, goo, ood, od#]的向量来表示
在英文中,因为只有26个字母,加上临界符是27个符号,3个字母的组合是有限的,即 A 27 3 = 17550 A_{27}^3=17550 A273=17550 种可能,因此也就不会出现OOV的问题。
对于discriminative,discriminate,discrimination 三个单词的意思很像,他们的Word Hashing中也有大部分是相同的。这样两个不同的单词也有可能具有相同的tri-grams,针对这个问题论文中做了统计,这个冲突的概率非常的低,500K个word可以降到30k维,冲突的概率为0.0044%。
可见该方法对于英文来说是有效可行的,但是并不适合中文,在我的代码中,会采用字向量的形式,词典包含了大部分的中文,能有效降低oov的可能性。
特征提取层
接下来的结构就很简单了,三个全连接层,激活函数采用的是tanh,把维度降低到128,然后把两个序列的Semantic feature进行了余弦相似度计算
输出层
输出层也很简单,一个softmax,因为是计算相似度所以可以看成是二分类,细节不再赘述。
ARC I
针对上述讲到的DSSM模型对query和doc序列和上下文信息捕捉能力的不足,华为诺亚方舟在2015年在DSSM的模型基础上加入了CNN模块,里面提到了两种模型ARC-I和ARC-II,前者是基于representation learning的模型,后者是基于match function learning的模型将在第三章讲到。两个模型对比原始的DSSM模型,最大的特点是引入了卷积和池化层来捕捉句子中的词序信息,ARC-I全称Architecture-I,框架如图
ARC-I模型引入了类似CNN模块的卷积层和池化层,整体框架如图
总结下ARC-I的特点:
- 对于query和doc两段文本的匹配,相比DSSM引入了word-ngram网络
- 通过卷积层不同的feature map来得到相邻term之间的多种组合关系
- 通过池化层max pooling来提取这些组合关系中最重要的部分,进而得到query和doc各自的表示。
- 表示层:通过上述卷积层和池化层来强化相邻word的关系,因此得到的query和doc的表示比原始DSSM能捕捉到词序信息
- 缺点:卷积层虽然提取到了word-ngram的信息,但是池化层依然是在局部窗口进行pooling,因此一定程度上无法得到全局的信息
Sentence-BERT(SBert)
SBert沿用了孪生网络的结构,文本Encoder部分用同一个Bert来处理。之后,作者分别实验了CLS-token和2种池化策略(Avg-Pooling、Mean-Pooling),对Bert输出的字向量进一步特征提取、压缩,得到u、v。
SBert直接用Bert的原始权重初始化,在具体数据集上微调,训练过程和传统Siamse Network差异不大。
但是这种训练方式能让Bert更好的捕捉句子之间的关系,生成更优质的句向量。在测试阶段,SBert直接使用余弦相似度来衡量两个句向量之间的相似度,极大提升了推理速度。
作者还做了一些有趣的消融实验。使用NLI和STS为代表的匹配数据集,在分类目标函数训练时,作者测试了不同的整合策略,结果显示**“(u, v, |u-v|)”**的组合效果最好。这里面最重要的部分是元素差:(|u - v|)。句向量之间的差异度量了两个句子嵌入维度间的距离,确保相似的pair更近,不同的pair更远。
CoSENT
具体内容在最后一个参考文献
参考
https://pypi.org/project/text2vec/
基于表征(Representation)的文本匹配、信息检索、向量召回的方法总结
https://blog.csdn.net/u012526436/article/details/90212287
https://cloud.tencent.com/developer/news/601293
https://kexue.fm/search/cosent/
最后
以上就是清脆汉堡为你收集整理的文本相似度的全部内容,希望文章能够帮你解决文本相似度所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复