@基于doc2vec计算文本相似度
Doc2vec
Doc2vec又叫Paragraph Vector是Tomas Mikolov基于word2vec模型提出的,其具有一些优点,比如不用固定句子长度,接受不同长度的句子做训练样本,Doc2vec是一个无监督学习算法,该算法用于预测一个向量来表示不同的文档,该模型的结构潜在的克服了词袋模型的缺点。
Doc2vec模型是受到了word2vec模型的启发,word2vec里预测词向量时,预测出来的词是含有词义的,比如上文提到的词向量’powerful’会相对于’Paris’离’strong’距离更近,在Doc2vec中也构建了相同的结构。所以Doc2vec克服了词袋模型中没有语义的去缺点。假设现在存在训练样本,每个句子是训练样本。和word2vec一样,Doc2vec也有两种训练方式,一种是PV-DM(Distributed Memory Model of paragraphvectors)类似于word2vec中的CBOW模型,另一种是PV-DBOW(Distributed Bag of Words of paragraph vector)类似于word2vec中的skip-gram模型
最近空闲之余,正好公司也有相应的业务需求,分享一下我最新的作品,一起体会一下nlp世界的魅力,希望各位能喜欢,哈哈哈哈,好了废话不多说,直接上重点!!!
获取文本句子向量(短文本)
import pandas as pd
import jieba.posseg as psg
import gensim
from gensim.models.doc2vec import Doc2Vec,TaggedDocument
import numpy as np
import os
import pkuseg
os.environ['CUDA_VISIBLE_DEVICES']='4'
#获取句子向量:
def get_sentence_vec(excel_path):
df = pd.read_excel(excel_path, index=False)
documents =[]
#选择需要处理成向量的列并转成列表
questions = df["questions"].tolist()
count = 0
#保留一个原始列
need_questions = []
#分词并去除掉停用词
for question in questions:
need_questions.append(question)
documents.append(TaggedDocument(pseg.cut(question), ["word{}".format(count)]))
count+=1
#设置相应参数并训练
model = Doc2Vec(documents, size=100, window=3,min_count=1, workers=4)
model
result_vec =[]
for i in range(count):
result_vec.append(model["word{}".format(i)])
return need_questions,np.array(result_vec)
Doc2Vec 参量
文档(列表的iterable TaggedDocument,可选的)–输入语料库可以只是元素列表,但对于较大的语料库,请考虑直接从磁盘/网络流式传输文档的iterable。如果不提供文档(或corpus_file),则模型未初始化-如果计划以其他方式对其进行初始化,请使用该模型。
corpus_file(str ,可选)– LineSentence格式的语料库文件的路径。您可以使用此参数而不是文档来提高性能。仅需要传递一个文档或 corpus_file参数(或者都不传递它们,在这种情况下,模型将保持未初始化状态)。文档标签是自动分配的,并且等于行号,如中所示 TaggedLineDocument。
DM({1 ,0} ,任选的) -定义的训练算法。如果dm = 1,则使用“分布式内存”(PV-DM)。否则,将使用分布式单词袋(PV-DBOW)。
vector_size(int ,optional)–特征向量的维数。
window(int ,可选)–句子中当前单词和预测单词之间的最大距离。
alpha(float ,可选)–初始学习率。
min_alpha(float ,可选)– 随着训练的进行,学习率将线性下降至min_alpha。
seed(int ,可选)–随机数生成器的种子。每个单词的初始向量都以单词+ str(seed)的连接的哈希值作为种子。请注意,对于完全确定性可重现的运行,还必须将模型限制为单个工作线程(worker = 1),以消除OS线程调度中的排序抖动。在Python 3中,解释程序启动之间的可重复性还需要使用PYTHONHASHSEED 环境变量来控制哈希随机化。
min_count(int ,optional)–忽略总频率低于此频率的所有单词。
max_vocab_size(int ,optional)–限制词汇建立期间的RAM;如果有比这更多的独特词,则修剪不常用的词。每1000万个字类型需要大约1GB的RAM。无限设置为无。
样本(float ,可选)–用于配置对哪些高频词进行随机下采样的阈值,有用范围是(0,1e-5)。
worker(int ,可选)–使用这些许多worker线程来训练模型(=使用多核计算机进行更快的训练)。
epochs(int ,optional)–语料库上的迭代次数(epoch)。
HS({1 ,0} ,任选的) -如果为1,分层SOFTMAX将用于模型训练。如果设置为0,并且负数为非零,则将使用负数采样。
负数(int ,可选)–如果> 0,将使用负数采样,负数的int指定应绘制多少个“噪声词”(通常在5到20之间)。如果设置为0,则不使用负采样。
ns_exponent(float ,可选)–用于塑造负采样分布的指数。值1.0与频率成正比地采样,0.0则对所有单词均等地采样,而负值对低频单词的采样比高频单词的采样多。最初的Word2Vec文件选择了流行的默认值0.75。最近,Caselleles-Dupré,Lesaint和Royo-Letelier 在https://arxiv.org/abs/1804.04212中建议,其他值对于推荐应用程序可能会表现更好。
dm_mean({1 ,0} ,任选的) -如果为0,使用上下文字矢量的总和。如果为1,请使用均值。仅在非连接模式下使用dm时适用。
dm_concat({1 ,0} ,任选的) -如果为1,上下文矢量而不是总和/平均值的使用级联; 请注意,级联会产生更大的模型,因为输入不再是一个(采样或算术组合)单词向量的大小,而是标签和上下文中所有单词的大小串在一起。
dm_tag_count(int ,可选)–使用dm_concat模式时,每个文档的预期文档标签数恒定。
dbow_words({1 ,0} ,任选的) -如果设置为1对列车字向量(在跳过克的方式)同时与DBOW DOC-矢量训练; 如果为0,则仅训练doc矢量(更快)。
trim_rule(函数,可选)–
文档对比并计算相似度,匹配最优相似度文本
#通过空间向量计算句子的分类:
def calculat_sentence_similarity():
#导入对照文档
label_df = pd.read_excel(standard_excel_path,index=False)
#导入需要对比的文档
excel_path = r""
df = pd.read_excel(excel_path, index=False)
#分词处理
questions = [que for que in df["questions"].tolist() if len(que)>5 and len(que)<25]
questions_doc = [TaggedDocument(pseg.cut(que), ["{}".format(index) ])
for index,que in enumerate(questions)]
keys = list(label_df.keys())
keys.remove("questions")
label_dic ={}
doc_tags =[]
label_documents=[]
total_labels = []
for key in keys:
label = key.split(":")[0]
total_labels.append(label)
values = label_df[~label_df[key].isnull()]["questions"].to_list()
documents =[
TaggedDocument(pseg.cut(question), ["{}:{}".format(label,index)])
for index,question in enumerate(values)]
label_dic[label] = len(documents)
doc_tags.extend(["{}:{}".format(label,index) for index in range(len(values))])
label_documents.extend(documents)
questions_doc.extend(label_documents)
model = Doc2Vec(questions_doc, size=100, window=3)
result = []
#相似度对比并选择最大相似度文本,并给出阈值
for index,ques in enumerate(questions):
tag = "{}".format(index)
most_match = model.docvecs.most_similar_to_given(tag,doc_tags)
percent = model.docvecs.similarity(tag,most_match)
result.append({"question":ques,most_match.split(":")[0]:percent})
#保存并输出结果
total_labels.append("question")
re_df = pd.DataFrame(result,columns=total_labels)
re_df.to_excel()