本文介绍文本相似度计算的各种方法,可以广泛应用在基于问答对匹配的问答系统中。
TF-IDF
$$
tfidf_i = tfidf = \frac{词i的数量}{词语总数}log\frac{总文档数}{包含词i的文档数}
$$
其中tf称为词频,idf为逆文档频率。
BM25
$$
BM25(i) = \frac{词i的数量}{总词数}\frac{(k+1)C}{C+k(1-b+b\frac{|d|}{avdl})}log(\frac{总文档数}{包含i的文档数}) \
C = tf=\frac{词i的数量}{总词数},k>0,b\in [0,1],d为文档i的长度,avdl是文档平均长度
$$
把 $1-b+b\frac{d}{avdl}$ 中的b看成0,那么此时中间项的结果为 $\frac{(k+1)tf}{k+tf}$ ,通过设置一个k,就能够保证其最大值为1,达到限制tf过大的目的。
即:
$$
\begin{align}
&\frac{(k+1)tf}{k+tf}= \frac{k+1}{1+\frac{k}{tf}} \qquad \qquad \qquad,上下同除tf
\end{align}
$$
k不变的情况下,上式随着tf的增大而增大,上限为k+1,但是增加的程度会变小。
在一个句子中,某个词重要程度应该是随着词语的数量逐渐衰减的,所以中间项对词频进行了惩罚,随着次数的增加,影响程度的增加会越来越小。通过设置k值,能够保证其最大值为k+1,k往往取值1.2
。
此外, $1-b+b\frac{d}{avdl}$ 的作用是用来对文本的长度进行归一化。例如在考虑整个句子的tdidf的时候,如果句子的长度太短,那么计算总的tdidf的值是要比长句子的tdidf的值要低的。所以可以考虑对句子的长度进行归一化处理。
可以看到,当句子的长度越短,$1-b+b\frac{|d|}{avdl}$的值是越小,作为分母的位置,会让整个第二项越大,从而达到提高短文本句子的BM25的值的效果。当b的值为0,可以禁用归一化, b往往取值0.75
。
fasttext
可以使用fasttext获取词向量,然后对一个句子中的所有词语的词向量进行平均,获取整个句子的向量表示,而且通过参数的控制,能实现N-garm的效果。
假设我们有文本a.txt
如下:
|
|
那么我们可以实现获取句子向量的方法如下:
|
|
默认生成的句向量是100维的。
pysparnn
pysparnn
使用的是一种 cluster pruning(簇修剪)
的技术,开始的时候对数据进行聚类,后续再有限个类别中进行数据的搜索,根据计算的余弦相似度返回结果。
数据预处理过程如下:
- 随机选择 $\sqrt{N}$ 个样本作为leader
- 选择非leader的数据(follower),使用余弦相似度计算找到最近的leader
当获取到一个问题q的时候,查询过程:
- 计算每个leader和q的相似度,找到最相似的leader
- 然后计算问题q和leader所在簇的相似度,找到最相似的k个,作为最终的返回结果
代码如下:
|
|
此外,还可以设置两个大于0的数字b1和b2
- b1表示在数据预处理阶段,每个follower选择b1个最相似的leader,而不是选择单独一个leader,这样不同的簇是有数据交叉的
- b2表示在查询阶段,找到最相似的b2个leader,然后再计算不同的leader中下的topk的结果
通过增加b1和b2的值,我们能够有更大的机会找到更好的结果,但是这样会需要更加大量的计算。
在 ci.MultiClusterIndex(features, records_data, num_indexes)
中, num_indexes
能够设置b1的值,默认为2。
在搜索的过程中, cp.search(search_vec, k=8, k_clusters=10, return_distance=True,num_indexes)
, num_Indexes
可以设置b2的值,默认等于b1的值。
孪生网络
孪生神经网络由两个共享权值的网络的组成,通过两个输入,被DNN进行编码,得到向量的表示之后,根据实际的用途来制定损失函数。比如我们需要计算相似度的时候,可以使用余弦相似度,或者使用 $exp^{-||h^{left}-h^{right}||}$ 来确定向量的距离。孪生神经网络被用于有多个输入和一个输出的场景,比如手写字体识别、文本相似度检验、人脸识别等。
模型架构大致如下:
|
|
BERT
也可以使用BERT进行文本相似度计算,这里使用 https://github.com/IAdmireu/ChineseSTS/blob/master/simtrain_to05sts.txt 数据集,两个句子的相似度范围从0到5。然后就和上篇文章中的方法一样,转化为文本分类问题就ok了。
|
|