天天看點

gensim中doc2vec計算文本相似度

最近在做判斷兩個文本是否是描述的同一件事情,之前是采用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 計算相似度