什么是Word2Vec?
Word2Vec是从巨大量文本中以无监督学习(从无标注数据中学习预测模型)的方式,被大量广泛的用于自然语言处理的算法技术。Word2Vec本质是通过用词向量的方式来表征词的语义信息来学习文本,通过创立一个嵌入空间使得语义上相似的单词在该空间内距离也相近。而Embedding其实就是映射空间,将文本中的词从原先所属的空间内映射到新的多维空间中,就是把原先的词所在的空间嵌入到新的空间之中。
直观的考虑一个实例,比如:girl woman 的词义非常的接近,所以在映射空间中这两个词的距离也非常近。
两种主要的模型Skip-Gram和CBOW(Continuous Bag of Words)
Skip-Gram是给定(输入)input word来预测上下文的内容,而CBOW刚好相反,是给定上下文的内容来预测(输入)input word。
Skip-Gram模型实际上分为两个部分,第一个部分是模型的建立,而第二个部分就是通过模型来获得嵌入词向量。首先基于训练的数据来构建一个神经网络,当这个模型训练好以后,我们并不需要用这个模型去处理新的数据,而是需要通过这个模型搭建除的训练参数,比如隐层的权重矩阵。这些权重就是我们在Skip-Gram中取学习的词向量,基于训练数据搭建模型的过程就是FM(Fake Model)
关于Skip-Gram训练神经网络的方方面面
例如我们有一个这样的句子“The girl walked on the street”
首先我们选择一个句子中间的词来作为我们的输入(input word),我们选择girl
有了输入之后我们还有一个skip_window参数,它代表着从输入词往前或者往后选取的词的数量。如果我们设置skip_window = 2,那么我们最终得到的词(包括input word在内的所有词汇),就是【“The”,“girl”,“walked”,“on”】。skip_window选为2,即左边两个,右边两个,所以整个窗口的大小为2×2。另一个参数是num_skip,它代表着我们从整个窗口中选取几个词来作为我们的输出(output word),如果我们将两个参数都设置为2,我们就会得到两组(input word,output word)这样的数据,即(“girl”,“the”),(“gril”,“walked”)。
神经网络基于这样的训练数据会输出一个概率的分布,这个概率代表着我们词典中的每个词作为output word的可能性。就比如我们将(“girl”,“the”)来作为训练数据,那么神经网络就是告诉我们每一个词典中是the的可能性。
实例:我们选定句子
“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(skip_window),下图中,蓝色代表input word,方框内代表窗口内的词。
我们的模型会从这样的数据集中学习并且得到统计结果。例如,我们的神经网络得到了很多(“A”,“B”)这样的训练样本,而(“A”,“C”)这样的训练样本却较为少,那么在当A在作为输入的时候B的概率就比C要大很多。
具体的模型设计
由于神经网络只能接受数值的输入,我们不能把单词作为字符串输入进去,因此我们需要将训练的单词文档构建成我们自己的词汇表,再对单词进行one-hot编码。
假设我们对一个训练文档有1000个的不同词汇,那么每一个词汇都将得到一个1000维度的向量,每一维度的数值只能是0或者1。就比如在1000个词汇中的第4个词汇,表示为向量就是:【0,0,0,1,0,...,0】
不管模型的输入是多少维度的向量,模型的输出也将会是多少维的向量。并且每一维度代表一个概率,代表着当前词汇出现成output work的概率有多大。
神经网络的具体结构:
隐藏层没有使用任何的激活函数,但是输出层的结果使用了softmax。
我们利用成对的单词来训练神经网络,最后得出的是一个概率的分布。
隐藏层的设计
如果我们想用500个特征来表示一个单词(即每个词被表示成500维的向量),那么隐藏层的权重矩阵应该是1000行,500列。
我们最终学习的目标,就是这个权重矩阵。由于我们对每个词都进行了one-hot编码,我们词汇所形成的的矩阵大多数的列都是0,相当稀疏,如果真正的去做矩阵运算,那么消耗的计算资源会非常的大,我们可以仅仅选择矩阵中对应的向量维度为1的索引行去乘以权重矩阵中相同的索引行。
输出层
经过神经网络的计算,输入词会从一个1×1000的向量,变成一个1×300的向量,然后被输出到输出层。而输出层有一个softmax回归分类器,它的每一个节点都会输出一个0-1之间的概率数值,并且所有神经元节点的概率之和为1。
如果有两个不同的单词所处的环境非常的相似,即拥有着相似的上下文,那我通过我们训练的模型,这两个单词的嵌入向量将非常的相似。
这种方法可以有效的帮助去除词缀得到词根。
问题:
上边我们讨论了Skip-Gram的输入层、隐层、输出层,那么如何让我们的模型更加的高效呢?
如果我们有10000个单词的词汇表,我们想嵌入300维的词向量,那我们的输入-隐层权重矩阵和隐隐层-输出层的权重矩阵就会有10000×300个权重,这样的权重矩阵在进行梯度下降的时候是非常慢的。
优化:
1.将常见的词组或者一起使用的词进行拆分。
注意:在拆分一些词语的时候,一些组合在一起的词语在分开以后可能完全有了两个不同的意思,比如New York,拆开的意思和原本不一样。所以在拆分的时候需要注意
2.对高频词出现的单词进行抽样来减少样本的个数。
在这样的样本中,如果有太多的“the”,那么我们的训练集中就会有很多的(the,...)大量的the甚至会超过我们通过样本学习the这个词向量的样本数。
因此我们可以改变窗口大小或者删除the来解决带给我们的问题。