[深度学习NPL]word2vector总结与理解

1. 目前成熟的Word2Vector

1.1. English Pre-trained word embeddings

  1. Google’s word2vec embedding:
    外网地址: [ Word2Vec] [ DownloadLink]
    300维英语词向量: [ 百度云]

  2. Glove word vectors:
    外网地址: [Glove]
    国内地址: [百度云]

  3. Facebook’s fastText embeddings:
    外网地址:[FastText]
    国内地址:[百度云]

  4. FastText Crawl:
    https://pan.baidu.com/s/1NPlqAOnX1k88VictTshVMQ
    [DeepMoji]: To understand how language is used to express emotions

1.2 Chinese Pre-trained word embeddings

目前最全的
https://github.com/Embedding/Chinese-Word-Vectors
https://github.com/to-shimo/chinese-word2vec

2. one_hot编码

首先,了解下什么是one_hot编码,直接举例子如下:
词库

我   从   哪   里   来   要   到   何   处  去
0    1    2    3   4    5   6    7    8   9

__one_hot编码__如下:

# 我从哪里来,要到何处去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 0 0 1]
]
 
# 我从何处来,要到哪里去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1]
]

one_hot编码后,一个句子可以用一个矩阵表示,出现在词库中的词对应在矩阵中位置为1

2.1. 简单对比

one_hot编码之前使用列表(一维)表达一个句子
one_hot编码之后使用矩阵(二维)表达一个句子

2.2.优势分析:

  1. 稀疏矩阵做矩阵计算的时候,只需要把1对应位置的数相乘求和就行,
  2. one-hot编码的优势就体现出来了,计算方便快捷、表达能力强

2.3. 缺点分析:

  1. 过于稀疏时,过度占用资源
    比如:中文大大小小简体繁体常用不常用有十几万,然后一篇文章100W字,要表达所有句子,需要100W X 10W的矩阵
  2. 每个向量之间相互正交的(内积为0)。向量正交意味着无相关性,这也正交意味着词与词之间是没有任何关系的。
  3. 每个词的向量维度和不同词的个数有关。比方说,在上面的这个句子里,有5个不同的词,所以向量的维度是5。然而往往实际应用中,一篇文章的中不同的词的个数是很多的。这样,向量的维度会非常的高

3. 什么是word2vector?

我们先来看一个问题,假如有一个句子 " the dog bark at the mailman"。
假如用向量来表示每个单词,我们最先想到的是用one hot 编码的方式来表达每个单词,具体来说。
the 可以表示为 [1,0,0,0,0]
dog 可以表示为 [0,1,0,0,0]
bark 可以表示为 [0,0,1,0,0]
at 可以表示为[0,0,0,1,0]
mailman可以表示为[0,0,0,0,1]

我们可以看到每个单词其实就用一个向量来表示。我们发现几个问题:
第一,每个向量之间相互正交的(内积为0)。也就是说词与词之间是没有任何关系的。
第二,每个词的向量维度和不同词的个数有关。比方说,在上面的这个句子里,有5个不同的词,所以向量的维度是5。然而往往现实中,一篇文章的中不同的词的个数是很多的。这样,向量的维度会非常的高。
这种对词的向量表示方法存在着以上的问题,忽略了词与词之间的关系(比如说,dog和cat都是动物,并非完全无关系)。维度太高的向量作为模型输入会导致模型变的复杂(模型复杂需要更多的训练样本才能够收敛)

那么是否存在一种更加合理的对词的用向量的表达方式呢?有的,其实就是word embedding。
word embedding说的简单一点其实就是将高维稀疏的向量降维成稠密的低维向量。(一种高维到低维的映射)

那么如和实现word embedding?
w2v其实就是一种高效实现word embedding的工具。
所以,如果用一句话来描述word2vector的话你会怎么描述?简单的说,我觉得可以这么说w2v其实是一种将单词转化向量的工具。这一种向量的其实是对单词更有效的表达

4. word2vector怎么做

下面总结一下word2vector主要的思想

4.1. Skip-Gram& CBOW

在介绍w2v模型之前,先介绍两个模型。一个是Skip-Gram和CBOW(Continuous Bag-of-Words)。首先看CBOW,它的做法是,将一个词所在的上下文中的词作为输入,而那个词本身作为输出。
在这里插入图片描述
来看Skip-Gram,它的做法和CBOW相反,将一个词所在的上下文中的词作为输出,而词本身作为输入。

在这里插入图片描述
(下面有例子说明)另外,我们介绍这两个模型都会涉及到的一个重要参数。

window_size:窗口大小。举一个例子,还是上面那句话:" the dog bark at the mailman"。假设window_size取1时,利用CBOW模型可以得到:

([the,bark],dog)

([dog,at],bark)

([bark,the],at)

([at,mailman],the)

一共4组数据。同样的,假设window_size还是1,利用Skip-Gram模型可以得到:

(dog,[the,bark])

(bark,[dog,at])

(at,[bark,the])

(the,[at,mailman])

对于每组数据会稍微做一下处理。比如对于第一组 (dog,[the,bark])一般处理成

(dog,the),(dog,bark)。

类似有:

(bark,dog),(bark,at),(at,bark),(at,the),(the,at),(the,mailman)共8组数据。

下面的图中给出了一些我们的训练样本的例子。我们选定句子“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(window_size=2),也就是说我们仅选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。
在这里插入图片描述
我们的模型将会从每对单词出现的次数中习得统计结果。例如,我们的神经网络可能会得到更多类似(“Soviet“,”Union“)这样的训练样本对,而对于(”Soviet“,”Sasquatch“)这样的组合却看到的很少。因此,当我们的模型完成训练后,给定一个单词”Soviet“作为输入,输出的结果中”Union“或者”Russia“要比”Sasquatch“被赋予更高的概率。

4.2. word2vector

下面就可以直接介绍如何进行w2v,上面提到w2v可以看作是一个将高维空间映射到低维空间的过程,用一个单层神经网络就可以实现这种功能(和自编码器有点类似其实)。对于CBOW,假如还是上面的句子" the dog bark at the mailman",训练数据是([the,brak],dog)那么网络的输入输出如下图所示:
在这里插入图片描述
这里有几个细节:

(1).上面介绍CBOW模型的时有一个模型的结构图,其中的SUM意思其实就是把各个上下文的词one-hot后的向量相加。比如对于the的向量是[1,0,0,0,0]。bark向量是[0,0,1,0,0],SUM之后就是[1,0,1,0,0]这就是网络的输入。输出就是[0,1,0,0,0],对应-dog

(2).我们所谓的embedding vetcor其实就第二个红框里的线,每一根线其实就是一个权值。

(3).第二个框里的红线其实就是dog这个单词的embedding结果(由5维变成3维)

(4).这个单层NN训练完毕之后有用的部分就是embedding martrix这部分,其大小为 输入个数(词汇表长度)×embedding后的维度。

类似对于Skip-Gram模型有:

在这里插入图片描述
当取训练数据(dog,bark)时,网络结构如上图,对比上面的CBOW最大的不同其实就是在于输入数据。

4.3. 模型细节

我们如何来表示这些单词呢?首先,我们都知道神经网络只能接受数值输入,我们不可能把一个单词字符串作为输入,因此我们得想个办法来表示这些单词。最常用的办法就是基于训练文档来构建我们自己的词汇表(vocabulary)再对单词进行one-hot编码。

假设从我们的训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants=[0, 0, 1, 0, …, 0])。

还是上面的例子,“The dog barked at the mailman”,那么我们基于这个句子,可以构建一个大小为5的词汇表(忽略大小写和标点符号):(“the”, “dog”, “barked”, “at”, “mailman”),我们对这个词汇表的单词进行编号0-4。那么”dog“就可以被表示为一个5维向量[0, 1, 0, 0, 0]。

模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。

下图是我们神经网络的结构:
在这里插入图片描述
隐层没有使用任何激活函数,但是输出层使用了sotfmax。

我们基于成对的单词来对神经网络进行训练,训练样本是 ( input word, output word ) 这样的单词对,input word和output word都是one-hot编码的向量。最终模型的输出是一个概率分布。

4.4. 隐层

说完单词的编码和训练样本的选取,我们来看下我们的隐层。如果我们现在想用300个特征来表示一个单词(即每个词可以被表示为300维的向量)。那么隐层的权重矩阵应该为10000行,300列(隐层有300个结点)。

Google在最新发布的基于Google news数据集训练的模型中使用的就是300个特征的词向量。词向量的维度是一个可以调节的超参数(在Python的gensim包中封装的Word2Vec接口默认的词向量大小为100, window_size为5)。

看下面的图片,左右两张图分别从不同角度代表了输入层-隐层的权重矩阵。左图中每一列代表一个10000维的词向量和隐层单个神经元连接的权重向量。从右边的图来看,每一行实际上代表了每个单词的词向量。
在这里插入图片描述
所以我们最终的目标就是学习这个隐层的权重矩阵。

我们现在回来接着通过模型的定义来训练我们的这个模型。

上面我们提到,input word和output word都会被我们进行one-hot编码。仔细想一下,我们的输入被one-hot编码以后大多数维度上都是0(实际上仅有一个位置为1),所以这个向量相当稀疏,那么会造成什么结果呢。如果我们将一个1 x 10000的向量和10000 x 300的矩阵相乘,它会消耗相当大的计算资源,为了高效计算,它仅仅会选择矩阵中对应的向量中维度值为1的索引行(这句话很绕),看图就明白。
在这里插入图片描述
我们来看一下上图中的矩阵运算,左边分别是1 x 5和5 x 3的矩阵,结果应该是1 x 3的矩阵,按照矩阵乘法的规则,结果的第一行第一列元素为0 x 17 + 0 x 23 + 0 x 4 + 1 x 10 + 0 x 11 = 10,同理可得其余两个元素为12,19。如果10000个维度的矩阵采用这样的计算方式是十分低效的。

为了有效地进行计算,这种稀疏状态下不会进行矩阵乘法计算,可以看到矩阵的计算的结果实际上是矩阵对应的向量中值为1的索引,上面的例子中,左边向量中取值为1的对应维度为3(下标从0开始),那么计算结果就是矩阵的第3行(下标从0开始)—— [10, 12, 19],这样模型中的隐层权重矩阵便成了一个”查找表“(lookup table),进行矩阵计算时,直接去查输入向量中取值为1的维度下对应的那些权重值。隐层的输出就是每个输入单词的“嵌入词向量”

4.5. 输出层

经过神经网络隐层的计算,ants这个词会从一个1 x 10000的向量变成1 x 300的向量,再被输入到输出层。输出层是一个softmax回归分类器,它的每个结点将会输出一个0-1之间的值(概率),这些所有输出层神经元结点的概率之和为1。

下面是一个例子,训练样本为 (input word: “ants”, output word: “car”) 的计算示意图。
在这里插入图片描述

5. 直觉上的理解

下面我们将通过直觉来进行一些思考。

如果两个不同的单词有着非常相似的“上下文”(也就是窗口单词很相似,比如“Kitty climbed the tree”和“Cat climbed the tree”),那么通过我们的模型训练,这两个单词的嵌入向量将非常相似。

那么两个单词拥有相似的“上下文”到底是什么含义呢?比如对于同义词“intelligent”和“smart”,我们觉得这两个单词应该拥有相同的“上下文”。而例如”engine“和”transmission“这样相关的词语,可能也拥有着相似的上下文

实际上,这种方法实际上也可以帮助你进行词干化(stemming),例如,神经网络对”ant“和”ants”两个单词会习得相似的词向量。

词干化(stemming)就是去除词缀得到词根的过程。

6. 参考资料

https://www.leiphone.com/news/201706/PamWKpfRFEI42McI.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章