word2vec原理及gensim中word2vec的使用

概述

在NLP中,对于一个词,我们用一个词向量来表示,最常见的一个方式是one hot representation,这种词向量的编码方式就是用一个很长的向量来表示一个词,向量的长度为词典的大小N,向量的分量只有一个1,其他全为0,1的位置对应该词在词典中的索引。这种表示方法不需要繁琐的计算,简单易得,但是缺点也不少:

  • 我们的词汇表一般都非常大,比如达到百万级别,这样每个词都用百万维的向量来表示,简直是内存的灾难
  • 这样表示数据,数据非常稀疏,稀疏数据的训练效率比较低,我们通常需要更多地数据来训练
  • 维度很高,很容易造成维数灾难
  • 无法体现出词之间的关系,比如“面条”和“方便面”显然有非常紧密的关系,但转化成向量[1,0,0]和[0,1,0]以后,就看不出两者有什么关系了,因为这两个向量相互正交
  • 这样的向量其实除了一个位置是1,其余的位置全部都是0,表达的效率不高

另一个方式是分布式表示(Distributed Representation),基本思想是将每个词表达成一个固定长度的稠密连续的实数短向量此时向量长度可以自由选择,与词典规模无关。与之相对的one-hot encoding向量空间只有一个维度是1,其余都是0。分布式表示最大的优点是具备非常powerful的特征表达能力,比如 n 维向量每维 k 个值,可以表征 \(k^n\)概念

向量空间模型(Vector Space Models)可以将字词转化为连续值的向量表示,并且其中意思相近的词将被映射到向量空间中相近的位置。向量空间模型在NLP中主要依赖的假设为Distributional Hypothesis,即在相同语境中出现的词其语义也相近。向量空间模型可以分为两类,

  • 一类是计数模型,比如LSA;计数模型统计在语料库中,相邻出现的词的频率再把这些计数统计结果转为小而稠密的矩阵
  • 另一类是预测模型(比如Neural Probabilisitc Language Models)。而预测模型则根据一个词周围相邻的词推测出这个词,以及它的向量空间

我们今天要要介绍的word2vec和Bengio在2003年发表的论文A neural probabilistic language model中提出的模型很相似,可以看做是在此基础上的改进,下图是Bengio在论文中提出的网络结构:
image
这篇文章提出的神经网络语言模型(NNLM,Neural Probabilistic Language Model)采用的是文本分布式表示,即每个词表示为稠密的实数向量。NNLM模型的目标是构建语言模型:

\[p(w_i|w_1,w_2,...,w_{t-1}) \approx f(w_i, w_{t-1}, ..., w_{t-n+1}) = g(w_i, C(w_{t-n+1}), ..., C(w_{t-1})) \]

词的分布式表示即word embedding,是训练语言模型的一个附加产物,即图中的Matrix C。

尽管Bengio 2003年便提出了NNLM,但是由于它的局限性,word embedding真正火起来是google Mikolov 2013年发表的两篇word2vec的文章 Efficient Estimation of Word Representations in Vector SpaceDistributed Representations of Words and Phrases and their Compositionality,更重要的是发布了简单好用的word2vec工具包。值得说明的一点是,word2vec是一个获得word embeding的工具,该工具得到的训练结果——word embedding,可以很好地度量词与词之间的相似性,挖掘词之间的联系。里面的模型只是很浅的神经网络,算不得深度学习算法,除了word2vec之外,我们还有其他的获得word embeding的方法,如bert等。

下面我们会详细的介绍word2vec中的两个主要语言模型训练方案:CBOW和Skip-Gram,以及Hierarchical Softmax和Negative Sampling这两个两个提速手段这两个方法很好的解决了计算有效性,事实上这两个方法都没有严格的理论证明,有些trick之处,非常的实用主义。然后我们利用gensim的python版来介绍word2vec的使用。

word2vec原理

CBOW模型和Skip-gram模型是神经概率语言模型的两种变形形式,下面我们将会一一介绍。

CBOW模型

CBOW(Continuous Bag-of-Words)的意思就是用上下文来预测当前词,如下图所示:
image
在上图中,通过词\(w_t\)的前后词\(w_{t-2}\)\(w_{t-1}\)\(w_{t+1}\)\(w_{t+2}\)来预测当前词\(w_t\)。此处的窗口的大小window为2。

其中,在CBOW模型中包含三层,即输入层,映射层和输出层。输入层是当前词周围每个词对应的词向量,在映射层将这些词的词向量相加求平均,在输出层求出为当前词的概率。
:
如何根据一个词的one-hot编码,得到它对应的词向量,可以看下图所示:
image
在word2vec实际的实现的网络里,上式中左边的式子是输入词的one-hot编码和隐藏层参数矩阵的乘积,在做这个乘法时是不会进行矩阵的运算的,而是直接通过输入值中1的位置索引来寻找隐藏层中的参数矩阵中对应的索引的行word2vec训练的目的就是得到这个隐藏层参数矩阵,这个矩阵也可以叫做embeding 矩阵,由于这一步很简单,我们上面的讲解里忽略掉这个隐藏层,输入层已经是之后词得到它所对应的词向量了,当然这个输入的词向量也是要求解的参数,下面的Skip-gram模型里面也按照这个设定,不再详述。

从数学上看,CBOW模型等价于一个词袋模型的向量乘以一个embedding矩阵,从而得到一个连续的embedding向量。这也是CBOW模型名称的由来

Skip-gram模型

而Skip-gram(Continuous Skip-gram)模型则与CBOW模型正好相反,在Skip-gram模型中,是用当前词来预测上下文,如下图所示:
image
在上图中,通过词\(w_t\)来预测它的前后词\(w_{t-2}\)\(w_{t-1}\)\(w_{t+1}\)\(w_{t+2}\)。此处的窗口的大小window为2。

这里输入层是当前词对应的词向量,映射层什么也不做,在输出层求出当前词上下文窗口中词的概率。

Skip-gram名称来源于该模型在训练时对上下文环境里的word进行采样,然后预测我们选到这个附近词的概率.

gensim中word2vec的使用

首先我们先介绍一下gensim中的word2vec API,官方API介绍如下:

class gensim.models.word2vec.Word2Vec(sentences=None, 
corpus_file=None, vector_size=100, alpha=0.025, 
window=5, min_count=5, max_vocab_size=None, sample=0.001, 
seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, 
ns_exponent=0.75, cbow_mean=1, hashfxn=<built-in function hash>, 
epochs=5, null_word=0, trim_rule=None, sorted_vocab=1, 
batch_words=10000, compute_loss=False, callbacks=(), 
comment=None, max_final_vocab=None)

gensim中,word2vec相关的API都在包gensim.models.word2vec中。和算法有关的参数都在类gensim.models.word2vec.Word2Vec中。算法需要注意的参数有:

  • sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出(通过word2vec提供的LineSentence类来读文件,word2vec.LineSentence(filename))。
  • vector_size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。
  • window:即词向量上下文最大距离,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。如果是小语料则这个值可以设的更小。对于一般的语料这个值推荐在[5,10]之间。
  • sg: 即我们的word2vec两个模型的选择了。如果是0, 则是CBOW模型,是1,则是Skip-Gram模型,默认是0,即CBOW模型。
  • hs: 即我们的word2vec两个解法的选择了,如果是1, 则是Hierarchical Softmax,是0的话并且负采样个数negative大于0, 则是Negative Sampling。默认是0Negative Sampling
  • negative:即使用Negative Sampling时负采样的个数,默认是5。推荐在[3,10]之间。
  • cbow_mean: 仅用于CBOW在做投影的时候,为0,则算法中的\(x_w\)为上下文的词向量之和,为1则为上下文的词向量的平均值。在我们的原理篇中,是按照词向量的平均值来描述的。个人比较喜欢用平均值来表示\(x_w\),默认值也是1,不推荐修改默认值。
  • min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。
  • iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
  • alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为η,默认是0.025
  • min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。这部分由于不是word2vec算法的核心内容,因此在原理篇我们没有提到。对于大语料,需要对alpha, min_alpha,iter一起调参,来选择合适的三个值。

常用的导入中文训练数据的方式,有以下几种:
使用Python的内置列表,

# 导入gensim库
from gensim.models import word2vec
# 第一种输入方式:Python内置列表
sentences = [['第', '一', '个', '句子'], ['第', '二', '个', '句子']]
# 调用函数训练模型
model = word2vec.Word2Vec(sentences)

sentences是一个列表的列表,它的每个元素是一个句子所构成的列表。
当数据集特别大的时候,使用上述第一种方法就需要消耗特别多的内存,gensim还支持使用迭代生成器的方式输入,

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname
 
    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()
 
sentences = MySentences('/some/directory') # 第二种输入方式:占用内存少的迭代器
model = Word2Vec(sentences)

这个输入方式会依次打开“/some/directory”文件夹中的每个数据文件,对于每个文件一行一行的读取数据进模型,这样就避免了一次性读入而占用太多内存。注意这里的每个文件里的每一行都是经过分词的一个句子,单词之间用空格分隔。

对于一个语料文件,里面的每一行都是经过分词的一个句子,单词之间用空格分隔,那么我们还可以使用
sentences = word2vec.LineSentence('corpus.txt')的方式进行读取,而sentences = word2vec.PathLineSentences(dir_name)则是针对dir_name文件夹下的所有的这样的文件进行读取。

from gensim.models import word2vec
#训练
model = word2vec.Word2Vec(sentences, hs=1,min_count=1,window=3,size=100)
model.save('model')  # 保存模型
model = word2vec.Word2Vec.load('model')  # 加载模型
model.wv['man']# 得到词的词向量
#找出某一个词向量最相近的词集合
for val in model.wv.similar_by_word("酒店", topn=10):
    print(val[0], val[1])

image
#查看两个词的相似性
image

#找出不同类的词
image

参考

word2vec前世今生
Word2Vec Tutorial - The Skip-Gram Model
word2vec原理(二) 基于Hierarchical Softmax的模型
用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践
word2vector的原理,结构,训练过程
Word2vec 入门(skip-gram部分)
源码解析——word2vec源码解析

posted on 2021-08-21 23:43  朴素贝叶斯  阅读(6919)  评论(0编辑  收藏  举报

导航