目录
一、无监督方法
1、余弦相似度度量
基本思想:
- 获取两个短文本的表示向量
- 计算两个向量的余弦相似度
- 值越大,表示越相似
文本表示方法:
- 通过 TF-IDF 统计方法获取词频表示/向量
- 通过 word2vec 词向量获取句向量
1.1 基于TF-IDF计算词频向量
TF-IDF
TF-IDF是传统的统计方法,用于评估一个词在一个文档集中对某一个文档的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
TF的意思是词频(Term-frequency),IDF的意思是逆向文件频率(Inverse Document Frequency)。
基本步骤:
- 找出待计算文本的关键词/列出所有的词
- 将找出的关键词组成一个合集,计算每个文本对于该合集中的词的词频
- 生成两个文本各自的词频向量
得到每个句子的词频向量后,计算两个向量的相似程度,可以使用余弦相似度计算。向量夹角越小,则表示文本越相似。
注:
- 计算两个句子的相似度时,只要计算每个句子中的词在词的合集中的词频向量
- 对于计算文本集合中与输入文本最相似的topK个文本的问题时,需要获取所有文本的词组成词的合集,然后计算每个文本的词频向量。如果查询文本中的所有词都不在词的合集中,则会出错。
上图来自参考资料[1]
1.2 基于Word2Vec计算词向量
基本流程:
- 使用训练好的模型或者使用准备的语料库训练word2vec模型
- 进行中文分词,通过word2vec计算句子中词的词向量(word vector)
- 获取句向量,可通过对词向量的加权平均等方法获取
- 直接取所有词向量的均值作为句向量
- 以每个词的tf-idf权重进行加权平均求句向量
- 以SIF为权重,对每个词的词向量加权平均,最后减去principal component得到句向量
获取sentence embedding后,计算余弦相似度。
上图来自参考资料[1]
2、基于simHash计算文本相似度
具体可参照前一篇博文:
3、直接度量句子间相似度—WMD
Word Mover's Distance(WMD),又称为词移距离
词移距离(Word Mover's Distance)是在词向量的基础上发展而来的用来衡量文档相似性的度量, 是一种计算句子之间距离的方法,距离越小,相似度越高。
具体原理可参考其他博客,此文只介绍具体的实现及使用。
反映文档与文档之间的相似度的一个想法是将文档距离建模成两个文档中词的语义距离的一个组合,比如说对两个文档中的任意两个词所对应的词向量求欧氏距离,然后再加权求和。
词移距离的gensim官方例子在gensim_WMD_tutorial
主要步骤:
- 文本预处理
- 获取词向量,可借助word2vec训练好的模型
- 计算WMD相似度
- 使用gensim中的WmdSimilarity()方法
关键代码:
# 导入库
import jieba
from gensim.models import KeyedVectors
from gensim.similarities import WmdSimilarity
# 加载模型
model = KeyedVectors.load_word2vec_format(model_file, binary = True)
# 文本预处理
documents = []
corpus = []
with open(data_file) as file:
for line in file:
line = line.strip()[4:]
seg = jieba.lcut(line)
if stopwords is not None:
seg = [w for w in seg if w != '\t' and w not in stopwords]
else:
seg = [w for w in seg if w != '\t']
corpus.append(seg)
documents.append(line)
# 计算相似度
instance = WmdSimilarity(wmd_corpus, model, num_best)
# 输入语句预处理
sent = input('输入查询语句: ')
sent_w = list(jieba.cut(sent))
query = [w for w in sent_w if w != '\t' and not w in stopwords]
# 相似度
sims = instance[query]
。。。。
# 计算两个句子的距离
def get_distance(s1, s2):
l1 = jieba.lcut(s1)
l2 = jieba.lcut(s2)
distance = model.wmdistance(l1, l2)
print('distance of %s and %s = %.4f' % (s1, s2, distance))
二、有监督方法
有监督方法,需要额外的标注数据,常见的有监督任务有:
- 分类任务:例如训练一个CNN的文本分类器,取最后一个hidden layer的输出作为 sentence embedding,其实就是取分类器的前几层作为预训练的 encoder。
- sentence pairs的等价性/等义性判定,不仅可以得到 sentence embedding,还可以直接学习到距离度量函数里的参数。
参考资料: