Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
modify word2vec
Browse files Browse the repository at this point in the history
  • Loading branch information
Zrachel committed Dec 30, 2016
1 parent ec6b5ba commit a11e387
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 36 deletions.
79 changes: 43 additions & 36 deletions word2vec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ One-hot vector虽然自然,但是用处有限。比如,在互联网广告系

在机器学习领域里,各种“知识”被各种模型表示,词向量模型(word embedding model)就是其中的一类。通过词向量模型可将一个 one-hot vector映射到一个维度更低的实数向量(embedding vector),如$embedding(母亲节) = [0.3, 4.2, -1.5, ...], embedding(康乃馨) = [0.2, 5.6, -2.3, ...]$。在这个映射到的实数向量表示中,希望两个语义(或用法)上相似的词对应的词向量“更像”,这样如“母亲节”和“康乃馨”的对应词向量的余弦相似度就不再为零了。

词向量模型可以是概率模型、共生矩阵(co-occurrence matrix)模型或神经元网络模型。在用神经网络求词向量之前,传统做法是统计一个词语的共生矩阵$X$。$X$是一个`|V|*|V|`大小的矩阵,$X_{ij}$表示在所有语料中,词汇表`V`(vocabulary)中第i个词和第j个词同时出现的词数,`|V|`为词汇表的大小。对$X$做矩阵分解(如奇异值分解,Singular Value Decomposition \[[5](#参考文献)\]),得到的$U$即视为所有词的词向量:
词向量模型可以是概率模型、共生矩阵(co-occurrence matrix)模型或神经元网络模型。在用神经网络求词向量之前,传统做法是统计一个词语的共生矩阵$X$。$X$是一个$|V| \times |V|$ 大小的矩阵,$X_{ij}$表示在所有语料中,词汇表`V`(vocabulary)中第i个词和第j个词同时出现的词数,$|V|$为词汇表的大小。对$X$做矩阵分解(如奇异值分解,Singular Value Decomposition \[[5](#参考文献)\]),得到的$U$即视为所有词的词向量:

$$X = USV^T$$

其中得到的$U$即视为所有词的词向量。但这样的传统做法有很多问题:<br/>
1) 很多词没有出现,导致矩阵极其稀疏,也需要对词频做额外tricks来达到好的SVD效果;<br/>
但这样的传统做法有很多问题:<br/>
1) 由于很多词没有出现,导致矩阵极其稀疏,因此需要对词频做额外处理来达到好的矩阵分解效果;<br/>
2) 矩阵非常大,维度太高(通常达到$10^6*10^6$的数量级);<br/>
3) 需要手动去掉停用词(如although, a,...),也会影响矩阵分解的效果
3) 需要手动去掉停用词(如although, a,...),不然这些频繁出现的词也会影响矩阵分解的效果


基于神经网络的模型不需要计算存储一个在全语料上统计的大表,而是通过学习语义信息得到词向量,因此能很好地解决以上问题。在本章里,我们将展示基于神经网络训练词向量的细节,以及如何用PaddlePaddle训练一个词向量模型。
Expand Down Expand Up @@ -55,52 +55,52 @@ similarity: -0.0997506977351
语言模型旨在为语句的联合概率函数$P(w_1, ..., w_T)$建模, 其中$w_i$表示句子中的第i个词。语言模型的目标是,希望模型对有意义的句子赋予大概率,对没意义的句子赋予小概率。
这样的模型可以应用于很多领域,如机器翻译、语音识别、信息检索、词性标注、手写识别等,它们都希望能得到一个连续序列的概率。 以信息检索为例,当你在搜索“how long is a football bame”时(bame是一个医学名词),搜索引擎会提示你是否希望搜索"how long is a football game", 这是因为根据语言模型计算出“how long is a football bame”的概率很低,而与bame近似的,可能引起错误的词中,game会使该句生成的概率最大。


### N-gram neural model

在计算语言学中,n-gram是一种重要的文本表示方法,表示一个文本中连续的n个项。基于具体的应用场景,每一项可以是一个字母、单词或者音节。 n-gram模型也是统计语言模型中的一种重要方法,用n-gram训练语言模型时,一般用每个n-gram的历史n-1个词语组成的内容来预测第n个词。
Yoshua Bengio等科学家就于2003年在著名论文 Neural Probabilistic Language Models \[[1](#参考文献)\] 中介绍如何学习一个神经元网络表示的词向量模型。文中的神经概率语言模型(Neural Network Language Model,NNLM)通过一个线性映射和一个非线性隐层连接,同时学习了语言模型和词向量,即通过学习大量语料得到词语的向量表达,通过这些向量得到整个句子的概率。用这种方法学习语言模型可以克服维度灾难(curse of dimensionality),即训练和测试数据不同导致的模型不准。我们已经讲到语言模型的目标是对$P(w_1, ..., w_T)$建模, 如果假设文本中每个词都是相互独立的,则整句话的联合概率可以表示为其中所有词语条件概率的乘积,即:
对语言模型的目标概率$P(w_1, ..., w_T)$,如果假设文本中每个词都是相互独立的,则整句话的联合概率可以表示为其中所有词语条件概率的乘积,即:

$$P(w_1, ..., w_T) = \prod_{t=1}^TP(w_t)$$

然而我们知道语句中的每个词出现的概率都与其前面的词紧密相关,
然而我们知道语句中的每个词出现的概率都与其前面的词紧密相关, 所以实际上通常用条件概率表示语言模型

$$P(w_1, ..., w_T) = \prod_{t=1}^TP(w_t | w_1, ... , w_{t-1})$$

可是越远的词语其实对该词的影响越小,那么如果考虑一个n-gram, 每个词都只受其前面`n-1`个词的影响,则有:

$$P(w_1, ..., w_T) = \prod_{t=n}^TP(w_t|w_{t-1}, w_{t-2}, ..., w_{t-n+1})$$

给定一些真实语料,这些语料中都是有意义的句子,语言模型的优化目标则是最大化目标函数:
### N-gram neural model

$$\frac{1}{T}\sum_t f(w_t, w_{t-1}, ..., w_{t-n+1};\theta) + R(\theta)$$
在计算语言学中,n-gram是一种重要的文本表示方法,表示一个文本中连续的n个项。基于具体的应用场景,每一项可以是一个字母、单词或者音节。 n-gram模型也是统计语言模型中的一种重要方法,用n-gram训练语言模型时,一般用每个n-gram的历史n-1个词语组成的内容来预测第n个词。
Yoshua Bengio等科学家就于2003年在著名论文 Neural Probabilistic Language Models \[[1](#参考文献)\] 中介绍如何学习一个神经元网络表示的词向量模型。文中的神经概率语言模型(Neural Network Language Model,NNLM)通过一个线性映射和一个非线性隐层连接,同时学习了语言模型和词向量,即通过学习大量语料得到词语的向量表达,通过这些向量得到整个句子的概率。用这种方法学习语言模型可以克服维度灾难(curse of dimensionality),即训练和测试数据不同导致的模型不准。我们在上文中已经讲到用条件概率建模语言模型,即一句话中第$t$个词的概率和该句话的前$t-1$个词相关。可实际上越远的词语其实对该词的影响越小,那么如果考虑一个n-gram, 每个词都只受其前面`n-1`个词的影响,则有:

其中$f(w_t, w_{t-1}, ..., w_{t-n+1})$表示根据历史n-1个词得到当前词$w_t$的条件概率,$R(\theta)$表示参数正则项。
函数$f$的网络示意图如下:
<p align="center">
<img src="image/ngram.png"><br/>
图3. n-gram神经网络模型
</p>
对于每个样本,模型输入$w_{t-n+1},...w_{t-1}$, 输出句子第t个词为字典中`|V|`个词的概率。
$$P(w_1, ..., w_T) = \prod_{t=n}^TP(w_t|w_{t-1}, w_{t-2}, ..., w_{t-n+1})$$

- 给定一些真实语料,这些语料中都是有意义的句子,语言模型的优化目标则是最大化目标函数:

根据softmax的定义,生成目标词$w_t$的概率为:
$$\frac{1}{T}\sum_t f(w_t, w_{t-1}, ..., w_{t-n+1};\theta) + R(\theta)$$

$$P(w_t | w_1, ..., w_{t-n+1}) = \frac{e^{g_{w_t}}}{\sum_i^{|V|} e^{g_i}}$$
其中$f(w_t, w_{t-1}, ..., w_{t-n+1})$表示根据历史n-1个词得到当前词$w_t$的条件概率,$R(\theta)$表示参数正则项。 对于每个样本,模型输入$w_{t-n+1},...w_{t-1}$, 输出句子第t个词为字典中`|V|`个词的概率。

其中$g_i$为预测当前词的层中第$i$个输出词节点的值。具体来说,$g_i = \theta_i^Tx + b$, $x$为隐层特征(一个线性映射`embedding`通过全连接`fully connect`投影到的非线性隐层), $\theta$和$b$为隐层特征层到词预测层的全连接参数。
- 根据softmax的定义,生成目标词$w_t$的概率为:

$$P(w_t | w_1, ..., w_{t-n+1}) = \frac{e^{g_{w_t}}}{\sum_i^{|V|} e^{g_i}}$$

其中$g_i$为预测当前词的层中第$i$个输出词节点的值。具体来说,$g_i = \theta_i^Tx + b$, $x$为隐层特征(一个线性映射`embedding`通过全连接`fully connect`投影到的非线性隐层), $\theta$和$b$为隐层特征层到词预测层的全连接参数。

整个网络的损失值(cost)为多类分类交叉熵,用公式表示为
- 整个网络的损失值(cost)为多类分类交叉熵,用公式表示为

$$J(\theta) = -\sum_{i=1}^N\sum_{c=1}^{|V|}y_k^{i}log(softmax(g_k^i))$$
$$J(\theta) = -\sum_{i=1}^N\sum_{c=1}^{|V|}y_k^{i}log(softmax(g_k^i))$$

其中$y_k^i$表示第i个样本第k类的真实label(0或1),$softmax(g_k^i)$表示第i个样本第k类softmax输出的概率。
其中$y_k^i$表示第$i$个样本第$k$类的真实标签(0或1),$softmax(g_k^i)$表示第i个样本第k类softmax输出的概率。

整个网络示意图如下所示:
<p align="center">
<img src="image/nnlm.png"><br/>
图3. N-gram神经网络模型
</p>

注意:由于“神经概率语言模型”说法较为泛泛,我们在这里不用其NNLM的本名,考虑到其具体做法,本文中称该模型为N-gram neural model。

### Continuous Bag-of-Words model(CBOW)

近年来最有名的神经元网络 word embedding model 恐怕是 Tomas Mikolov 在Google 研发的 wordvec\[[3](#参考文献)\]。其中介绍了两个模型,Continuous Bag-of-Words model和Skip-Gram model,这两个网络很浅很简单,但训练效果非常好。和N-gram neural model 类似,这两个模型同样利用了上下文信息。 CBOW模型通过一个词的上下文(各N个词)预测当前词。当N=2时,模型如下图所示:
CBOW模型通过一个词的上下文(各N个词)预测当前词。当N=2时,模型如下图所示:
<p align="center">
<img src="image/cbow.png"><br/>
图4. CBOW模型
Expand All @@ -114,9 +114,9 @@ $$context = \frac{x_{t-1} + x_{t-2} + x_{t+1} + x_{t+2}}{4}$$

### Skip-gram model

CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去掉了噪声,因此在小数据集上很有效而Skip-gram的方法中,用一个词预测其上下文,得到了当前词上下文的很多样本,因此可用于更大的数据集。
CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去掉了噪声,因此在小数据集上很有效而Skip-gram的方法中,用一个词预测其上下文,得到了当前词上下文的很多样本,因此可用于更大的数据集。
<p align="center">
<img src="image/ngram.png"><br/>
<img src="image/skipgram.png"><br/>
图5. Skip-gram模型
</p>
如上图所示,Skip-gram模型的具体做法是,将一个词的词向量映射到$2n$个词的词向量($2n$表示当前输入词的前后各$n$个词),然后分别通过softmax得到这$2n$个词的分类损失值之和。
Expand Down Expand Up @@ -254,6 +254,13 @@ settings(

### 模型结构

本配置的模型结构如下图所示:

<p align="center">
<img src="image/ngram.png"><br/>
图3. 模型配置中的N-gram神经网络模型
</p>

1. 定义参数维度和和数据输入。

```python
Expand Down Expand Up @@ -305,7 +312,7 @@ settings(
learning_rate = 1))
```

5. 最后,将文本隐层特征,再经过一个全连接,映射成一个`|V|`维向量,同时通过softmax归一化得到这`|V|`个词的生成概率。
5. 最后,将文本隐层特征,再经过一个全连接,映射成一个$|V|$维向量,同时通过softmax归一化得到这`|V|`个词的生成概率。

```python
# use context embedding to predict nextword
Expand Down Expand Up @@ -391,9 +398,9 @@ python format_convert.py --b2t -i model/pass-00029/_proj -o model/pass-00029/_pr
```

其中,第一行是PaddlePaddle 输出文件的格式说明,包含3个属性:<br/>
1). PaddlePaddle的版本号,本例中为0;<br/>
2). 浮点数占用的字节数,本例中为4;<br/>
3). 总计的参数个数, 本例中为62496(即1953*32);<br/>
1) PaddlePaddle的版本号,本例中为0;<br/>
2) 浮点数占用的字节数,本例中为4;<br/>
3) 总计的参数个数, 本例中为62496(即1953*32);<br/>
第二行及之后的每一行都按顺序表示字典里一个词的特征,用逗号分隔。

### 修改词向量
Expand All @@ -403,8 +410,8 @@ python format_convert.py --b2t -i model/pass-00029/_proj -o model/pass-00029/_pr
```bash
python format_convert.py --t2b -i INPUT -o OUTPUT
```
-i INPUT: 输入的文本词向量模型名称
-o OUTPUT: 输出的二进制词向量模型名称

其中,INPUT是输入的输入的文本词向量模型名称,OUTPUT是输出的二进制词向量模型名称

输入的文本格式如下(注意,不包含上面二进制转文本后第一行的格式说明):

Expand Down
1 change: 1 addition & 0 deletions word2vec/data/getdata.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -e

wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
tar -zxf simple-examples.tgz
Expand Down
3 changes: 3 additions & 0 deletions word2vec/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data/train.list
data/test.list
data/simple-examples*
Binary file added word2vec/image/nnlm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions word2vec/train.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -e

paddle train \
--config ngram.py \
Expand Down

0 comments on commit a11e387

Please sign in to comment.