基于doc2vec计算文本相似度
Doc2vec
Doc2vec又被称作Paragraph Vector是由Tomas Mikolov基于word2vec模型提出的一种方法。它具有一些优势,例如无需固定句子长度,它能够处理不同长度的句子作为训练样本。 Doc2vec作为一个无监督学习算法,该方法旨在生成代表不同文档的一个向量,其核心架构本质上弥补了词袋模型在捕捉语义信息方面的不足。
该模型借鉴了word2vec的技术,在其算法设计中采用了上下文预测的方式生成词语表示。具体而言,在word2vec算法中,通过预测上下文来生成词语向量时所体现出的意义完整性。例如,在之前讨论的例子中,像‘powerful’这样的词语与‘Paris’之间的距离比‘strong’更为接近。该方法通过引入段落级别的表示来捕捉语义信息,并且相较于仅基于词袋模型的Word2Vec模型而言,在处理语义层次上具有显著的优势。该过程的具体实现包括两个主要阶段:第一种是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 参量
TaggedDocument类型的迭代容器被用作输入语料库——这可以是简单的元素列表。但对于较大的语料库来说,请考虑直接从磁盘或网络中流式传输文档的迭代器。若不提供文档(或corpus_file),则模型未初始化;若希望以其他方式进行初始化,则需使用本模型。
corpus_path
该算法基于参数集{1,0}进行配置,并采用任选策略。若dm变量等于1,则采用分布式内存模型;否则,则选用分布式单词袋模型。
dimension(整型变量 ,可选参数)–特征向量的维数
window(int ,可选)–句子中当前单词和预测单词之间的最大距离。
alpha(float ,可选)–初始学习率。
min_alpha(float ,可选)– 随着训练的进行,学习率将线性下降至min_alpha。
指定整数类型的可选参数——随机数生成器——用于初始化哈希表。该参数允许用户指定一个起始值或种子以帮助算法产生一致的结果。所有单词在构建初始向量时都会采用单词与指定seed值连接后计算得到的哈希值作为基础。特别注意的是,在希望实现完全确定性和可重现性的运行环境中,请确保模型仅使用单个工作线程(worker = 1),以此来避免操作系统的线程调度带来的顺序抖动影响结果的一致性。需要注意的是,在Python 3环境中,默认情况下解释程序之间的启动不可重复;为了控制哈希随机化的不可重复性并确保结果的一致性,在运行时应设置PYTHONHASHSEED环境变量。
min_count(int ,optional)–忽略总频率低于此频率的所有单词。
max_vocab_size(int ,optional)–限制词汇建立期间所需的内存空间;如果有比这更多的唯一词汇,则移除频率较高的词汇。每个 million tokens typically require about 1 GB of RAM. 若设置为无限,则移除此限制。
参数(float类型、可选)用于设置对高频词汇进行随机抽样降维的阈值范围。其取值范围限定在(0, 1e-5)之间。
worker参数(int类型且可选)表示模型使用的大量Worker线程数量,并通过多核心处理器实现高效的模型训练。
epochs(int ,optional)–语料库上的迭代次数(epoch)。
若设HS参数组分为{1, 0}类型且可选参数,则该方法将采用分层SOFTMAX进行模型训练;若设为{1, 0}类型并指定非零数值,则该方法将采用负数采样。
指定为负整数时,默认会启用去噪词生成。具体而言,该参数决定了绘制多少个"噪声词"(一般设在5至20之间).若设为零,则放弃此采样方法.
ns_exponent(一个可选浮点数)被定义为调整负采样分布形态的关键参数,并且在模型初始化阶段通常被设定为空间维度的数量,默认情况下取值范围在[−1, 1]之间以避免数值溢出问题。该参数通过调节不同类型的语料数据来实现更好的语义表示效果,在实际应用中发现其取值范围通常在[−1, 1]之间能够获得较好的实验效果,并且这种设定能够有效平衡高频词和低频词的信息提取能力。
dm_mean({0, 1} ,可选的) -当参数设置为0时,计算并返回上下文向量之和;若参数设置为1,则计算并返回所有输入序列的时间加权平均值。此方法仅在非连接模式下适用。
dm\_concat(\{1, 0\}, optional) -当第一个参数为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()
