文本语义匹配/相似度度量

Word2vec语义相似度计算

上一章节,我们用1.1G的中文维基百科语料训练了词向量。而短文本的语义相似度度量,最简单的方法便是把每个句子的词向量相加,然后计算其余弦相似度。gensim包中同样用函数实现了这一算法,如下:

1
2
3
4
def n_similarity(self, ws1, ws2):
v1 = [self[word] for word in ws1]
v2 = [self[word] for word in ws2]
return dot(matutils.unitvec(array(v1).mean(axis=0)), matutils.unitvec(array(v2).mean(axis=0)))

建立一个target.txt文件存放待匹配的问题,代码比较简单如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# -*- coding:utf-8 -*-
#!/usr/bin/env Python
from gensim.models import Word2Vec
import sys
import jieba
jieba.load_userdict("dict.txt")
class ResultInfo(object):
def __init__(self, index, score, text):
self.id = index
self.score = score
self.text = text

target = "target.txt" # 问题集合
model = "./model/word2vec"

model_w2v = Word2Vec.load(model) #加载模型 文字摘要
print ("模型加载成功!")
candidates = []
with open(target) as f:
for line in f:
candidates.append(line.strip().split()) # candidates列表中加载所有问题,
并用空格分割
while True:
text = input("请输入查询指令: ")
words = list(jieba.cut(text.strip()))
if len(words) == 0:
continue
flag = False
for w in words:
if w not in model_w2v.wv.vocab:
print ("输入指令中词汇“%s”不在字典中" % w)
flag = True
if flag:
continue
res = []
index = 0
for candidate in candidates:
score = model_w2v.n_similarity(words, candidate)
res.append(ResultInfo(index, score, " ".join(candidate)))
index += 1
res.sort(key=lambda x:x.score, reverse=True)
for i in res:
print i.text # 输出相似度最高的语句

最后测试结果如下,在短文本的相似度测量上,基于词向量相似度度量的算法在计算速度和质量上均是比较满意的。

============体育=============
3 世界 锦标赛 中国队 胜出 0.42
4 中国 足球 失败 0.41
2 奥运会 中国 女排 夺冠 0.40
============农业=============
1 农民 在 江苏 种 水稻 0.55
0 人工智能 和 农业 怎么 结合 0.45
5 山东 苹果 丰收 0.42

Doc2vec语义相似度计算

Doc2vec的原理暂未深入研究,参照网上各路教程跑通后的代码如下。笔者用该doc2vec进行了语义相似度检测,但效果差强人意(具体来说,能捕捉到一定程度句子结构信息,但对语义很模糊)。可能跟语料库选取关系较大,此处用的不是一行行的短句,而是训练word2vec的语料,一行一段话…接下来若有文本分类等任务,再补上详细研究路线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- coding:utf-8 -*-

import gensim
import smart_open
import multiprocessing
import logging
from gensim.models.doc2vec import TaggedDocument, Doc2Vec

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

data_set = "pre0"

def read_corpus(fname, tokens_only=False):
with smart_open.smart_open(fname, encoding="utf-8") as f:
for i, line in enumerate(f):
if tokens_only:
yield gensim.utils.simple_preprocess(line)
else:
text = line.split()
yield TaggedDocument(text[:], [i])


train_data = list(read_corpus(data_set))
print len(train_data)

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model = Doc2Vec(size=100, min_count=1, iter=10, workers=multiprocessing.cpu_count())
model.build_vocab(train_data)
model.train(train_data, total_examples=model.corpus_count, epochs=100)
model.save('./model/model_new.doc2vec')

Ref:

LSTM 句子相似度分析
基于gensim的Doc2Vec简析