基于doc2vec计算文本相似度

时光总嘲笑我的痴心妄想 提交于 2020-08-09 17:07:56

@基于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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!