句子相似度计算

时间:2022-06-25
本文章向大家介绍句子相似度计算,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

思路一:先求句向量,然后求余弦相似度

1.求得两个句子的句向量

  • 生成文本词频向量 用词频来代替,句子,当然这样做忽略近义词信息、语义信息、大量文本下运算等诸多问题。如果两段很长的文本进行比较(比如上万字的文章),岂不是维度要扩增很多倍?而且矩阵会非常稀疏,就是很多取值都是0,计算开销大且效率低
  • tfidf提取句向量 对刚才的问题进行特征降维,可依旧解决不了文本语义问题
  • 深度学习方法包含语义信息,参考前面的文章: bert生成句向量
  • 传统的方法生成句向量

用每个词的词向量相加,然后求平均

def sent2vec(s):
    words = s
    M = []
    for w in words:
        try:
            M.append(w2v.wv[w])
        except:
            continue
    M = np.array(M)
    v = M.sum(axis=0)
    return v / np.sqrt((v ** 2).sum())

2.求两个向量之间的余弦夹角

####计算余弦夹角
def cos_sim(vector_a, vector_b):
    """
    计算两个向量之间的余弦相似度
    :param vector_a: 向量 a
    :param vector_b: 向量 b
    :return: sim
    """
    vector_a = np.mat(vector_a)
    vector_b = np.mat(vector_b)
    num = float(vector_a * vector_b.T)
    denom = np.linalg.norm(vector_a) * np.linalg.norm(vector_b)
    cos = num / denom
    sim = 0.5 + 0.5 * cos
    return sim

思路二:求得词向量,计算词移距离WMD

词移距离

Word2Vec将词映射为一个词向量,在这个向量空间中,语义相似的词之间距离会比较小,而词移距离(WMD)正是基于word2vec的这一特性开发出来的。 两个文档中的任意两个词所对应的词向量求欧氏距离然后再加权求和

image.png

image.png

这个加权矩阵T有些类似于HMM中的状态转移矩阵,只不过其中的概率转换为权重了而已。 如图,我们假设’Obama’这个词在文档1中的的权重为0.5(可以简单地用词频或者TFIDF进行计算),那么由于’Obama’和’president’的相似度很高,那么我们可以给由’Obama’移动到’president’很高的权重,这里假设为0.4,文档2中其他的词由于和’Obama’的距离比较远,所以会分到更小的权重。这里的约束是,由文档1中的某个词i移动到文档2中的各个词的权重之和应该与文档1中的这个词i的权重相等,即’Obama’要把自己的权重(0.5)分给文档2中的各个词。同样,文档2中的某个词j所接受到由文档1中的各个词所流入的权重之和应该等于词j在文档2中的权重。 参考资料: Supervised Word Mover’s Distance (可监督的词移距离) – NIPS 2016论文精选#2 https://blog.csdn.net/qrlhl/article/details/78512598 https://blog.csdn.net/weixin_40547993/article/details/89475630

  • 计算wmd词移距离代码如下:
from gensim.models import KeyedVectors
import jieba
import time
import os

start = time.time()
model = KeyedVectors.load_word2vec_format('vectors.bin', binary=True, unicode_errors='ignore')
end = time.time()
print('Cell took %.2f seconds to run.' % (end - start))
s01= "今天是个好日子"
s02= "今天是晴天"
s03= "天气多云转阴"
sentence_01 = list(jieba.cut(s01))
sentence_02= list(jieba.cut(s02))
sentence_03= list(jieba.cut(s03))

结果:

Cell took 16.98 seconds to run.
Loading model cost 0.701 seconds.
distance = 24.3276
Prefix dict has been built succesfully.
distance = 55.7726