NLP学习(九)文本向量化doc2vec及案例实现-Python3实现
发布日期:2021-05-15 21:32:15 浏览次数:41 分类:技术文章

本文共 4654 字,大约阅读时间需要 15 分钟。

doc2vec基本原理

  1. A distributed memory model

训练句向量的方法和词向量的方法非常类似。训练词向量的核心思想就是说可以根据每个单词的上下文预测,也就是说上下文的单词对是有影响的。那么同理,可以用同样的方法训练doc2vec。例如对于一个句子i want to drink water,如果要去预测句子中的单词want,那么不仅可以根据其他单词生成feature, 也可以根据其他单词和句子来生成feature进行预测。因此doc2vec的框架如下所示:

在这里插入图片描述
每个段落/句子都被映射到向量空间中,可以用矩阵的一列来表示。每个单词同样被映射到向量空间,可以用矩阵的一列来表示。然后将段落向量和词向量级联或者求平均得到特征,预测句子中的下一个单词。

这个段落向量/句向量也可以认为是一个单词,它的作用相当于是上下文的记忆单元或者是这个段落的主题,所以我们一般叫这种训练方法为Distributed Memory Model of Paragraph Vectors(PV-DM)

在训练的时候我们固定上下文的长度,用滑动窗口的方法产生训练集。段落向量/句向量 在该上下文中共享。

总结doc2vec的过程, 主要有两步:

A. 训练模型,在已知的训练数据中得到词向量, softmax的参数和,以及段落向量/句向量

B. 推断过程(inference stage),对于新的段落,得到其向量表达。具体地,在矩阵中添加更多的列,在固定,的情况下,利用上述方法进行训练,使用梯度下降的方法得到新的D,从而得到新段落的向量表达

  1. Paragraph Vector without word ordering: Distributed bag of words

还有一种训练方法是忽略输入的上下文,让模型去预测段落中的随机一个单词。就是在每次迭代的时候,从文本中采样得到一个窗口,再从这个窗口中随机采样一个单词作为预测任务,让模型去预测,输入就是段落向量。如下所示:

在这里插入图片描述
我们称这种模型为 Distributed Bag of Words version of Paragraph Vector(PV-DBOW)

在上述两种方法中,我们可以使用PV-DM或者PV-DBOW得到段落向量/句向量。对于大多数任务,PV-DM的方法表现很好,但我们也强烈推荐两种方法相结合。

  1. 基于gensim的doc2vec实践

我们使用第三方库gensim进行doc2vec模型的训练

# -*- coding: utf-8 -*-import sysimport loggingimport osimport gensim# 引入doc2vecfrom gensim.models import Doc2VeccurPath = os.path.abspath(os.path.dirname(__file__))rootPath = os.path.split(curPath)[0]sys.path.append(rootPath)from utilties import ko_title2words # 引入日志配置logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) # 加载数据documents = []# 使用count当做每个句子的“标签”,标签和每个句子是一一对应的count = 0with open('../data/titles/ko.video.corpus','r') as f:    for line in f:        title = unicode(line, 'utf-8')        # 切词,返回的结果是列表类型        words = ko_title2words(title)        # 这里documents里的每个元素是二元组,具体可以查看函数文档        documents.append(gensim.models.doc2vec.TaggedDocument(words, [str(count)]))        count += 1        if count % 10000 == 0:            logging.info('{} has loaded...'.format(count)) # 模型训练model = Doc2Vec(documents, dm=1, size=100, window=8, min_count=5, workers=4)# 保存模型model.save('models/ko_d2v.model')

接下来看看训练好的模型可以做什么

def test_doc2vec():    # 加载模型    model = doc2vec.Doc2Vec.load('models/ko_d2v.model')    # 与标签‘0’最相似的    print(model.docvecs.most_similar('0'))    # 进行相关性比较    print(model.docvecs.similarity('0','1'))    # 输出标签为‘10’句子的向量    print(model.docvecs['10'])    # 也可以推断一个句向量(未出现在语料中)    words = u"여기 나오는 팀 다 가슴"    print(model.infer_vector(words.split()))    # 也可以输出词向量    print(model[u'가슴'])

实战:网页文本向量化

语料:下载地址是https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2,或者在这里找https://dumps.wikimedia.org/zhwiki/。这个文件只包含了标题和正文,不包含词条之间的链接信息,大小约为1.3G

1、段落向量的训练

与训练词向量不同的是无需再对文档进行分词,直接将简体文本保留。doc2vec在训练时能够采用Tag信息更好地辅助训练(表明是同一类doc)输入文档多了一个tag属性。

#!/usr/bin/env python# -*- coding: utf-8 -*- import gensim.models as gfrom gensim.corpora import WikiCorpusimport loggingfrom langconv import * #enable logginglogging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) docvec_size=192class TaggedWikiDocument(object):    def __init__(self, wiki):        self.wiki = wiki        self.wiki.metadata = True    def __iter__(self):        import jieba        for content, (page_id, title) in self.wiki.get_texts():            yield g.doc2vec.LabeledSentence(words=[w for c in content for w in jieba.cut(Converter('zh-hans').convert(c))], tags=[title]) def my_function():    zhwiki_name = './data/zhwiki-latest-pages-articles.xml.bz2'    wiki = WikiCorpus(zhwiki_name, lemmatize=False, dictionary={})    documents = TaggedWikiDocument(wiki)     model = g.Doc2Vec(documents, dm=0, dbow_words=1, size=docvec_size, window=8, min_count=19, iter=5, workers=8)    model.save('data/zhiwiki_news.doc2vec') if __name__ == '__main__':    my_function()

2、 doc2vec计算网页相似度

三步走:预处理->文档向量化->.计算文本相似

import gensim.models as gimport codecsimport numpyimport numpy as np model_path = './data/zhiwiki_news.doc2vec'start_alpha = 0.01infer_epoch = 1000docvec_size = 192  def simlarityCalu(vector1, vector2):    vector1Mod = np.sqrt(vector1.dot(vector1))    vector2Mod = np.sqrt(vector2.dot(vector2))    if vector2Mod != 0 and vector1Mod != 0:        simlarity = (vector1.dot(vector2)) / (vector1Mod * vector2Mod)    else:        simlarity = 0    return simlarity  def doc2vec(file_name, model):    import jieba    doc = [w for x in codecs.open(file_name, 'r', 'utf-8').readlines() for w in jieba.cut(x.strip())]    doc_vec_all = model.infer_vector(doc, alpha=start_alpha, steps=infer_epoch)    return doc_vec_all  if __name__ == '__main__':    model = g.Doc2Vec.load(model_path)    p1 = './data/P1.txt'    p2 = './data/P2.txt'    P1_doc2vec = doc2vec(p1, model)    P2_doc2vec = doc2vec(p2, model)    print(simlarityCalu(P1_doc2vec, P2_doc2vec))

转载地址:https://blog.csdn.net/qq_30868737/article/details/108283725 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:因子分析-python3实现
下一篇:NLP学习(八)文本向量化word2vec及案例实现-Python3实现

发表评论

最新留言

很好
[***.229.124.182]2024年03月27日 04时53分29秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

java factory用法_怎样使用Java实现Factory设计模式 2019-04-21
java窗口内容如何复制_求助Java窗口菜单如何实现复制粘贴剪切等功能(内附源代码)... 2019-04-21
盾神与砝码称重java_[蓝桥杯][算法提高VIP]盾神与砝码称重 2019-04-21
java输出狗的各类信息_第九章Java输入输出操作 2019-04-21
java notify怎么用_java 如何使用notify() 2019-04-21
java加载指定文件为当前文本,java:如何使用bufferedreader读取特定的行 2019-04-21
java metrics 怎么样,Java metrics 2019-04-21
在vscode中php语言配置,Visual Studio Code C / C++ 语言环境配置 2019-04-21
php怎么翻译数据库中的中文,javascript – 如何将翻译后的文本插入数据库php 2019-04-21
普朗克公式matlab,用MATLAB实现普朗克函数积分的快捷计算.pdf 2019-04-21
swoolec+%3c?php,PHP+Swoole并发编程的魅力 2019-04-21
php 404配置,phpcms如何配置404 2019-04-21
matlab wash矩阵产生,洗衣机净衣效能与衣损程度的关系分析 2019-04-21
php中如何调用sql server,php调用SQL SERVER 2008及以上版本的方法 2019-04-21
python多线程实现kmeans,3种方式实现python多线程并发处理 2019-04-21
matlab 变量不存在,matlab程序运行时提示变量未定义 2019-04-21
php编码函数 base58,1. Base58可逆加密 2019-04-21
oracle 在需要下列之一,Oracle存储过程中PLS-00103:出现符号“/”在需要下列之一时:(... 2019-04-21
oracle10g dblink优化,Oracle10g通过dblink访问数据异常 2019-04-21
linux安装时的iso文件,直接用ISO文件在linux上安装新系统 2019-04-21