最近在做判斷兩個文本是否是描述的同一件事情,之前是采用gensim中的TF-IDF進行計算的,TF-IDF這種方法沒有考慮到文字背後的語義關聯,可能在兩個文檔共同出現的單詞很少甚至沒有相同的單詞,但兩個文檔是相似的情況下,就需要考慮到文檔的語義。我們都知道word2vec是可以分析語義的,那麼doc2vec是不是也可以分析出語義呢?于是試了一下gensim中的doc2vec。
Doc2Vec 也可叫做 paragraph2vec, sentence embeddings,是一種非監督式算法,可以獲得 sentences/paragraphs/documents 的向量表達,是 word2vec 的拓展。學出來的向量可以通過計算距離來找 sentences/paragraphs/documents 之間的相似性,可以用于文本聚類,對于有标簽的資料,還可以用監督學習的方法進行文本分類,例如經典的情感分析問題。
Doc2Vec的目的是獲得文檔的一個固定長度的向量表達
資料:多個文檔,以及它們的标簽,可以用标題作為标簽(這個标簽的意思沒有明白是什麼意思)
影響模型準确率的因素:語料的大小,文檔的數量,越多越好;文檔的相似性,越相似越好
參考網址:https://blog.csdn.net/juanjuan1314/article/details/75124046/#commentsedit
doc2vec還可以細分為:DM模型、DBOW模型,在訓練模型中的dm參數進行控制
具體的代碼如下所示:
- 1、相關包的導入
# coding:utf-8
import sys
import gensim
import sklearn
import numpy as np
import jieba
from gensim.models.doc2vec import Doc2Vec, LabeledSentence
from jieba import analyse
TaggededDocument = gensim.models.doc2vec.TaggedDocument
- 2、讀取訓練資料
def get_datasest(path_qisu):
with open(path_qisu, 'r') as cf:
docs = cf.readlines()
x_train = []
for i, text in enumerate(docs):
word_list = ' '.join(jieba.cut(text)).split(' ') ##保證讀入的檔案是進行分過詞的,我選用的是jieba進行分的詞
l = len(word_list)
word_list[l - 1] = word_list[l - 1].strip()
document = TaggededDocument(word_list, tags=[i])
x_train.append(document)
return x_train
- 3、進行訓練模型
def train(x_train, size=200, epoch_num=1):
model_dm = Doc2Vec(x_train, min_count=1, window=3, size=size, sample=1e-3, negative=5, workers=4)
model_dm.train(x_train, total_examples=model_dm.corpus_count, epochs=70)
model_dm.save('./model_wenjian/model_sim')
return model_dm
- 4、給定文檔進行測試,并計算相似度
def ceshi(test_text):
model_dm = Doc2Vec.load('./model_wenjian/model_sim')
# test_text = ' '.join(jieba.cut(str1)).split(' ')
inferred_vector_dm = model_dm.infer_vector(test_text.split(' '))
# print inferred_vector_dm
# Gensim 中有内置的 most_similar,得到向量後,可以計算相似性
sims = model_dm.docvecs.most_similar([inferred_vector_dm], topn=10)
return sims
- 5、對待計算相似度的文檔進行關鍵資訊的抽取
def extract(line):
##引用TF-IDF關鍵詞抽取接口
tfidf = analyse.extract_tags
##結巴分詞
str1_fenci = ' '.join(jieba.cut(line))
##停用詞的去除
stop_word = []
with open('stop_word.txt') as fp:
for line in fp.readlines():
line = line.strip()
if line == '':
continue
stop_word.append(line.decode('utf-8'))
str1_rv_stop_word = ''
str1_rv_stop_word_fenci = ''
for each in str1_fenci.split(' '):
if each not in stop_word:
if str1_rv_stop_word == '':
str1_rv_stop_word = each
str1_rv_stop_word_fenci = each
else:
str1_rv_stop_word = str1_rv_stop_word + each
str1_rv_stop_word_fenci = str1_rv_stop_word_fenci + ' ' + each
##關鍵資訊的抽取
guanjian = tfidf(str1_rv_stop_word)
guanjian_result = ''
linshi = []
for each in str1_rv_stop_word.split(' '):
if each in guanjian:
if guanjian_result == '':
guanjian_result = each
else:
guanjian_result = guanjian_result + ' ' + each
linshi.append(each)
return guanjian_result
- 6、主程式代碼
if __name__ == '__main__':
path_qisu = './qisu_yijianshu/qisu_0.txt'
path_xunwen = './xunwen_bilu/xunwen_0.txt'
path_write = './similarity_result/doc/' + 'sim_' + path_qisu.split('_')[-1].split('.')[0] + '.txt'
##此處放入起訴意見書的内容
x_train = get_datasest(path_qisu)
model_dm = train(x_train)
ceshi_list = []
with open(path_xunwen) as fp:
for line in fp.readlines():
line = line.strip()
if line == '':
continue
ceshi_list.append(line)
f1 = open(path_write,'w')
for line in ceshi_list:
f1.write(line+'\n')
line = extract(line) ##關鍵資訊的抽取
sims = ceshi(line)
for count, sim in sims:
sentence = x_train[count]
words = ''
for word in sentence[0]:
words = words + word + u' '
print words, sim, len(sentence[0])
f1.write(str(sim)+'\n')
f1.write(words.encode('utf-8'))
f1.write('\n')
f1.write('\n')
f1.close()
doc2vec算法是基于word2vec算法
代碼中模型的使用:
model_dm = Doc2Vec(x_train, min_count=1, window=3, size=size, sample=1e-3, negative=5, workers=4)
x_train:是訓練文檔,訓練文檔必須是一行一個文本,并且進行過分詞
size:表示生成的向量的次元,一般為100維
windows:表示訓練視窗的大小,也就是訓練資料周圍讀取了幾個資料
min_count:是參與訓練的詞語的最小詞頻
用到的Doc2vec的功能主要有三個:
1.TaggedDocument語料預處理
2.train訓練模型,save 和 load 加載訓練好的模型
3.docvecs.most_similar 計算相似度