本文原载于微信公众号「磐创AI」,作者荔枝boy,编辑磐石,出品磐创AI技术团队,AI研习社获其授权转载。
Doc2vec 原理
代码实现
总结
前文总结了 Word2vec 训练词向量的细节,讲解了一个词是如何通过 word2vec 模型训练出唯一的向量来表示的。那接着可能就会想到,有没有什么办法能够将一个句子甚至一篇短文也用一个向量来表示呢?答案是肯定有的,构建一个句子向量有很多种方法,今天我们接着 word2vec 来介绍下 Doc2vec,看下 Doc2vec 是怎么训练一个句子向量的。
许多机器学习算法需要的输入是一个固定长度的向量,当涉及到短文时,最常用的固定长度的向量方法是词袋模型(bag-of-words)。尽管它很流行,但是词袋模型存在两个主要的缺点:一个是词袋模型忽略词序,如果两个不同的句子由相同的词但是顺序不同组成,词袋模型会将这两句话定义为同一个表达;另一个是词袋模型忽略了句法,这样训练出来的模型会造成类似「powerful」,「strong」和「Paris」的距离是相同的,而其实「powerful」应该相对于「Paris」距离「strong」更近才对。
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 模型,如图二:
图二
在 Doc2vec 中,每一句话用唯一的向量来表示,用矩阵 D 的某一列来代表。每一个词也用唯一的向量来表示,用矩阵W的某一列来表示。以 PV-DM 模型为例,如图三:
图三
每次从一句话中滑动采样固定长度的词,取其中一个词作预测词,其他的作输入词。输入词对应的词向量 word vector 和本句话对应的句子向量 Paragraph vector 作为输入层的输入,将本句话的向量和本次采样的词向量相加求平均或者累加构成一个新的向量 X,进而使用这个向量X预测此次窗口内的预测词。
Doc2vec 相对于 word2vec 不同之处在于,在输入层,增添了一个新句子向量Paragraph vector,Paragraph vector 可以被看作是另一个词向量,它扮演了一个记忆,词袋模型中,因为每次训练只会截取句子中一小部分词训练,而忽略了除了本次训练词以外该句子中的其他词,这样仅仅训练出来每个词的向量表达,句子只是每个词的向量累加在一起表达的。正如上文所说的词袋模型的缺点,忽略了文本的词序问题。而 Doc2vec 中的 Paragraph vector 则弥补了这方面的不足,它每次训练也是滑动截取句子中一小部分词来训练,Paragraph Vector 在同一个句子的若干次训练中是共享的,所以同一句话会有多次训练,每次训练中输入都包含 Paragraph vector。它可以被看作是句子的主旨,有了它,该句子的主旨每次都会被放入作为输入的一部分来训练。这样每次训练过程中,不光是训练了词,得到了词向量。同时随着一句话每次滑动取若干词训练的过程中,作为每次训练的输入层一部分的共享 Paragraph vector,该向量表达的主旨会越来越准确。Doc2vec 中 PV-DM 模型具体的训练过程和 word2vec 中的 CBOW 模型训练方式相同,在之前我写的基于 Word2vec 训练词向量(一)里有详细介绍,这里就不在重复。
训练完了以后,就会得到训练样本中所有的词向量和每句话对应的句子向量,那么 Doc2vec 是怎么预测新的句子 Paragraph vector 呢?其实在预测新的句子的时候,还是会将该 Paragraph vector 随机初始化,放入模型中再重新根据随机梯度下降不断迭代求得最终稳定下来的句子向量。不过在预测过程中,模型里的词向量还有投影层到输出层的 softmax weights 参数是不会变的,这样在不断迭代中只会更新 Paragraph vector,其他参数均已固定,只需很少的时间就能计算出带预测的 Paragraph vector。
在 python 中使用 gensim 包调用 Doc2vec 方便快捷,在这简单演示下,gensim 下 Doc2vec 详细的参数不在此详细阐述。本次的数据是之前比赛中公开的旅游数据集,里边每一条都是游客对于景点的评价。具体的 Doc2vec 训练 Paragraph vector 步骤如下:
1)导包:导入必要的包,其中的 jieba 是为了给文本进行分词。
2)导入数据集,提取Discuss列(该列是用户评价的内容)。
3)将提取好的 Discuss 列中的内容进行分词,并去除停用词。
4)改变成 Doc2vec 所需要的输入样本格式,由于 gensim 里 Doc2vec 模型需要的输入为固定格式,输入样本为:[句子,句子序号],这里需要用 gensim 中 Doc2vec 里的 TaggedDocument 来包装输入的句子。
5)加载Doc2vec模型,并开始训练。
6)模型训练完毕以后,就可以预测新的句子的向量 Paragraph vector 了,这里用 gensim 里 Doc2Vec.infer_vector() 预测新的句子,这里根据经验,alpha(学习步长)设置小一些,迭代次数设置大一些。找到训练样本中与这个句子最相近的10个句子。可以看到训练出来的结果与测试的新句子是有关联的。
Doc2vec 是基于 Word2vec 基础上构建的,相比于 Word2vec,Doc2vec 不仅能训练处词向量还能训练处句子向量并预测新的句子向量。Doc2vec 模型结构相对于 Word2vec,不同点在于在输入层上多增加了一个 Paragraph vector 句子向量,该向量在同一句下的不同的训练中是权值共享的,这样训练出来的 Paragraph vector 就会逐渐在每句子中的几次训练中不断稳定下来,形成该句子的主旨。这样就训练出来了我们需要的句子向量。在预测新的句子向量时,是需要重新训练的,此时该模型的词向量和投影层到输出层的 soft weights 参数固定,只剩下 Paragraph vector 用梯度下降法求得,所以预测新句子时虽然也要放入模型中不断迭代求出,相比于训练时,速度会快得多。本次使用的数据集为情感分析,且大多数样本偏向于好评,样本内容比较单一,所以训练出来的结果都是偏向于哪里好玩,好不好这类的意思,对于一些特定的问题之类的句子准确性还没有验证,目前用于情感分析还是可以的。下次会尝试使用新的数据集,调试参数看是否会取得更好的结果。
从Python入门-如何成为AI工程师
BAT资深算法工程师独家研发课程
最贴近生活与工作的好玩实操项目
班级管理助学搭配专业的助教答疑
学以致用拿offer,学完即推荐就业
新人福利
关注 AI 研习社(okweiwu),回复 1 领取
【超过 1000G 神经网络 / AI / 大数据资料】
一文详解 Word2vec 之 Skip-Gram 模型(训练篇)
▼▼▼