前言:
在对word2vec学习之后又对doc2vec进行了学习,这是谷歌大神Tomas Mikolov在2013年推出word2vec之后在word2vec的基础之上2014年推出的Paragraph vector,旨在解决对于句子和长文本的表示。其模式也是在word2vec的基础上进行的。对于doc2vec的详细介绍在下面的连接中有详细介绍。
借鉴学习链接:
详解链接:https://www.jianshu.com/p/62516dcca2c2
简单实现代码链接:https://blog.csdn.net/juanjuan1314/article/details/75124046/
改进:
1:上述代码实验中使用对于句子的存储使用了txt文件,虽然每一句文字结束都有回车进行分行,但实际实验中还是会出现句子与句子分割不清的问题。
2:本文对数据的存储使用csv文件解决了上述问题。
代码目的:
有两个文件A和B,A是训练集,B是测试集;A中有很多数据,B中有很多数据,我要在A中找出与B中数据最相似的前1个或前10个,然后保存结果。
代码:
# -*- coding: utf-8 -*-
import gensim
import jieba
import pandas as pd
import time
import utils as util
from gensim.models.doc2vec import Doc2Vec, LabeledSentence
TaggededDocument = gensim.models.doc2vec.TaggedDocument
def get_datasest(filepath):
'''
:param filepath:trainfile.csv文件路径
:return: 训练成document的对象数据
'''
x_train=[]
data = pd.read_csv(filepath)
print("原数据长度:",len(data))
dataDescrip = data.ix[:,2]
for i,senten in enumerate(dataDescrip):
sentence_seged = ' '.join(jieba.cut(senten, cut_all=False)).replace(',', '').replace('。', '')#分词
word_list = sentence_seged.split(' ')#根据空格切片
document = TaggededDocument(word_list, tags=[i])
x_train.append(document)
print('Tagged数据长度:', len(x_train))
return x_train
def train(x_train):
'''
训练
:param x_train: 处理好的数据
:return: doc2vec model
'''
model_dm = Doc2Vec(x_train, min_count=1, window=3, vector_size=100, sample=1e-3, negative=5, workers=4)
model_dm.train(x_train, total_examples=model_dm.corpus_count, epochs=70)
model_dm.save('model/doc2vec.model')
print('模型生成成功')
return model_dm
def getSimsAndSaveInCsv(testfile,trainfile,resultfile,):
'''
:param testfile: 测试文件未执行
:param trainfile: 训练文件库
:param resultfile: 得到的计算结果文件
:return:
'''
model_dm = Doc2Vec.load('model/doc2vec.model')
list=[]
testdata = pd.read_csv(testfile)
traindata = pd.read_csv(trainfile)
testdatadescrip = testdata.ix[:,2]
for i,senten in enumerate(testdatadescrip):# 这里的i是从0开始
text = ' '.join(jieba.cut(senten, cut_all=False)).replace(',', '').replace('。', '') # 分词
test_text = text.split(' ')
inferred_vector = model_dm.infer_vector(test_text)
sims = model_dm.docvecs.most_similar([inferred_vector], topn=1)#topn是设定相似的前几个
for count,sim in sims:
# print('count:',count,"sentence:",x_tain[count])#和他相识的句子的编号 +1 因为从0开始
list.append([i+1,count+1,sim,testdata.loc[i,'classs'],senten,traindata.loc[count,'class'],traindata.loc[count,'describe']])
# [test标号,train相似标号,cos, test类别, test句子, 训练集类别, 训练集句子]
dataframe = pd.DataFrame(list)
util.setCscHead(resultfile, ['teindex', 'trindex', 'cos', 'teclass', 'tedescribe', 'trclass', 'trdescribe'])
dataframe.to_csv(resultfile, mode='a', index=False, encoding='utf-8', header=False)
print('doc2vec测试集保存完成')
def resultAnalyse():
util.rightRateForMax('result/Result1.csv')
if __name__ == '__main__':
x_tain = get_datasest('F:\train.csv')
model_dm = train(x_tain)
#--以上两个函数是训练数据形成model------------
getSimsAndSaveInCsv('data/test.csv','F:\train.csv','result/Result1.csv')
resultAnalyse()
注意:
1.训练时 句子是以TaggededDocument的对象形式输入的。在get_datasest()函数中有体现。
总结:
在使用doc2vec计算短文本相似度时,效果并不理想。可能是自己的数据集不好,也可能是doc2vec面对长文本效果更佳。