diff --git a/word2vec/README.md b/word2vec/README.md
index 87490ba4fdfe7d3dfdfc36edac6c3bd4bc38d309..171debe71a2f00999f7820ed54b1ba6a809a1bc8 100644
--- a/word2vec/README.md
+++ b/word2vec/README.md
@@ -11,22 +11,22 @@ 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)模型或神经元网络模型。在用神经网络求词向量之前,传统做法是统计一个word co-occurrence矩阵$X$。$X$是一个`|V|*|V|`大小的矩阵,$X_{ij}$表示在所有语料中,词汇表(vocabulary)中第i个词和第j个词同时出现的词数,`|V|`为词汇表的大小。对$X$做矩阵分解(如Singular Value Decomposition),即
+词向量模型可以是概率模型、共生矩阵(co-occurrence matrix)模型或神经元网络模型。在用神经网络求词向量之前,传统做法是统计一个词语的共生矩阵$X$。$X$是一个`|V|*|V|`大小的矩阵,$X_{ij}$表示在所有语料中,词汇表`V`(vocabulary)中第i个词和第j个词同时出现的词数,`|V|`为词汇表的大小。对$X$做矩阵分解(如奇异值分解,Singular Value Decomposition \[[5](#参考文献)\]),得到的$U$即视为所有词的词向量:
$$X = USV^T$$
-其中得到的$U$即视为所有词的word embedding. 这样做有很多问题:
+其中得到的$U$即视为所有词的词向量。但这样的传统做法有很多问题:
1) 很多词没有出现,导致矩阵极其稀疏,也需要对词频做额外tricks来达到好的SVD效果;
2) 矩阵非常大,维度太高(通常达到$10^6*10^6$的数量级);
-3) 需要手动去掉停用词(如although, a,...),不然这些频繁出现的词会影响SVD效果
+3) 需要手动去掉停用词(如although, a,...),也会影响矩阵分解的效果。
-而基于神经网络的模型就可以很好的解决以上问题,而不需要计算存储一个在全语料上统计的大表。在本章里,我们将展示基于神经网络训练词向量的细节,以及如何用PaddlePaddle训练一个词向量模型。
+基于神经网络的模型不需要计算存储一个在全语料上统计的大表,而是通过学习语义信息得到词向量,因此能很好地解决以上问题。在本章里,我们将展示基于神经网络训练词向量的细节,以及如何用PaddlePaddle训练一个词向量模型。
## 效果展示
-本章中,当词向量训练好后,我们可以用t-SNE\[[5](#参考文献)\]画出词语特征在二维上的投影(如下图所示)。从图中可以看出,语义相关的词语(如a, the, these; big, huge)在投影上距离很近,语意无关的词(如say, business; decision, japan)在投影上的距离很远。
+本章中,当词向量训练好后,我们可以用数据可视化算法t-SNE\[[4](#参考文献)\]画出词语特征在二维上的投影(如下图所示)。从图中可以看出,语义相关的词语(如a, the, these; big, huge)在投影上距离很近,语意无关的词(如say, business; decision, japan)在投影上的距离很远。
@@ -47,74 +47,79 @@ similarity: -0.0997506977351
## 模型概览
-在这里我们介绍3个训练词向量的模型,中心思想都是通过上下文得到一个词出现的概率。之后本章tutorial会带大家用PaddlePaddle实现N-gram neural model。
+在这里我们介绍三个训练词向量的模型:N-gram模型,CBOW模型和Skip-gram模型,它们的中心思想都是通过上下文得到一个词出现的概率。对于N-gram模型,我们会先介绍语言模型的概念,并在之后的[训练模型](#训练模型)中,带大家用PaddlePaddle实现它。而后两个模型,是近年来最有名的神经元词向量模型,由 Tomas Mikolov 在Google 研发\[[3](#参考文献)\],虽然它们很浅很简单,但训练效果很好。
-### N-gram neural model
-
-Word embedding 的研究从2000年开始。Yoshua Bengio等科学家于2003年发表了著名的论文 Neural Probabilistic Language Models \[[1](#参考文献)\] 介绍如何学习一个神经元网络表示的embedding model,文中neural network language model(NNLM)通过一个线性映射和一个非线性隐层连接,同时学习了语言模型和词向量。
- PS:由于“神经概率语言模型”说法较为泛泛,我们在这里不用其NNLM的本名,考虑到其具体做法,本文中称该模型为N-gram neural model。
-
-在介绍该模型之前,我们先来引入一个概念————语言模型。
+### 语言模型
+在介绍词向量模型之前,我们先来引入一个概念:语言模型。
语言模型旨在为语句的联合概率函数$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近似的,可能引起typo的词中,game会使该句生成的概率最大。
+这样的模型可以应用于很多领域,如机器翻译、语音识别、信息检索、词性标注、手写识别等,它们都希望能得到一个连续序列的概率。 以信息检索为例,当你在搜索“how long is a football bame”时(bame是一个医学名词),搜索引擎会提示你是否希望搜索"how long is a football game", 这是因为根据语言模型计算出“how long is a football bame”的概率很低,而与bame近似的,可能引起错误的词中,game会使该句生成的概率最大。
-在计算语言学中,n-gram表示一个文本中连续的n个项。基于具体的应用场景,每一项可以是一个字母、单词或者音节。 n-gram模型是统计语言模型中的一种重要方法,用n-gram训练语言模型时,一般用每个n-gram的历史n-1个词语组成的内容来预测第n个词。文\[[1](#参考文献)\] 中提出,可以同时训练一个语言模型和词向量模型,即通过学习大量语料得到词语的向量表达,通过这些向量得到整个句子的概率。用这种方法学习语言模型可以克服维度灾难(curse of dimensionality),即训练和测试数据不同导致的模型不准。在上文中我们已经讲到语言模型的目标是对$P(w_1, ..., w_T)$建模, 如果假设文本中每个词都是相互独立的,则整句话的联合概率可以表示为其中所有词语条件概率的乘积,即
+### 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) = \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`个词的影响,则有
+可是越远的词语其实对该词的影响越小,那么如果考虑一个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})$$
-给定了一些真实语料,这些语料中都是有意义的句子,语言模型的优化目标则是最大化
+给定一些真实语料,这些语料中都是有意义的句子,语言模型的优化目标则是最大化目标函数:
$$\frac{1}{T}\sum_t f(w_t, w_{t-1}, ..., w_{t-n+1};\theta) + R(\theta)$$
-其中$f(w_t, w_{t-1}, ..., w_{t-n+1})$, 表示根据历史n-1个词得到当前词$w_t$的条件概率,$R(\theta)$表示参数正则项。
-
+其中$f(w_t, w_{t-1}, ..., w_{t-n+1})$表示根据历史n-1个词得到当前词$w_t$的条件概率,$R(\theta)$表示参数正则项。
函数$f$的网络示意图如下:
图3. n-gram神经网络模型
-对于每个样本,模型输入$w_{t-n+1},...w_{t-1}$, 输出句子第t个词为字典中`|V|`个词的概率,`V`表示训练语料词汇表(vocabulary)。
+对于每个样本,模型输入$w_{t-n+1},...w_{t-1}$, 输出句子第t个词为字典中`|V|`个词的概率。
根据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为多类分类交叉熵,用公式表示为
+其中$g_i$为预测当前词的层中第$i$个输出词节点的值。具体来说,$g_i = \theta_i^Tx + b$, $x$为隐层特征(一个线性映射`embedding`通过全连接`fully connect`投影到的非线性隐层), $\theta$和$b$为隐层特征层到词预测层的全连接参数。
+
+整个网络的损失值(cost)为多类分类交叉熵,用公式表示为
$$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输出的概率。
+注意:由于“神经概率语言模型”说法较为泛泛,我们在这里不用其NNLM的本名,考虑到其具体做法,本文中称该模型为N-gram neural model。
### Continuous Bag-of-Words model(CBOW)
-近年来最有名的神经元网络 word embedding model 恐怕是 Tomas Mikolov 在Google 研发的 wordvec\[[4](#参考文献)\]。其中介绍了两个模型,Continuous Bag-of-Words model和Skip-Gram model,这两个网络很浅很简单,但训练效果非常好。和N-gram neural model 类似,这两个模型同样利用了上下文信息。 CBOW模型通过一个词的上下文(各N个词)预测当前词,而Skip-gram模型用一个词预测其上下文。
+近年来最有名的神经元网络 word embedding model 恐怕是 Tomas Mikolov 在Google 研发的 wordvec\[[3](#参考文献)\]。其中介绍了两个模型,Continuous Bag-of-Words model和Skip-Gram model,这两个网络很浅很简单,但训练效果非常好。和N-gram neural model 类似,这两个模型同样利用了上下文信息。 CBOW模型通过一个词的上下文(各N个词)预测当前词。当N=2时,模型如下图所示:
图4. CBOW模型
-N=2时,CBOW模型如上图所示,不考虑上下文的词语输入顺序,CBOW用上下文词语的词向量的均值来预测当前词,即
+
+具体来说,不考虑上下文的词语输入顺序,CBOW是用上下文词语的词向量的均值来预测当前词。即:
+
$$context = \frac{x_{t-1} + x_{t-2} + x_{t+1} + x_{t+2}}{4}$$
-其中$x_t$为第t个词的词向量,分类score向量 $z=U*context$,最终的分类依然用softmax, $y=softmax(z)$,loss同样采用多类分类交叉熵。
+
+其中$x_t$为第$t$个词的词向量,分类分数(score)向量 $z=U*context$,最终的分类$y$采用softmax,损失函数采用多类分类交叉熵。
### Skip-gram model
-CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去掉了噪声,因此在小数据集上很有效,而skip-gram的方法用一个词预测其上下文,得到了当前词上下文的很多样本,因此可用于更大的数据集。
+CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去掉了噪声,因此在小数据集上很有效,而Skip-gram的方法中,用一个词预测其上下文,得到了当前词上下文的很多样本,因此可用于更大的数据集。
- 图5. skip-gram模型
+ 图5. Skip-gram模型
-如上图所示,skip-gram模型的具体做法是,将一个词的词向量映射到$2n$个词的词向量(`2n`表示当前输入词的前后各n个词),分别通过softmax分别得到这2n个词。最终loss为所有`2n`个词的分类loss的和。在\[[4](#参考文献)\]的基础上,\[[2](#参考文献)\]在一些具体做法上对Skip-gram方法进行了进一步改进。
+如上图所示,Skip-gram模型的具体做法是,将一个词的词向量映射到$2n$个词的词向量($2n$表示当前输入词的前后各$n$个词),然后分别通过softmax得到这$2n$个词的分类损失值之和。
@@ -122,7 +127,7 @@ CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去
### 数据介绍与下载
-本教程使用Penn Tree Bank (PTB)数据集。PTB数据集较小,训练速度快,应用于Mikolov的公开语言模型训练工具[3]中。其统计情况如下:
+本教程使用Penn Tree Bank (PTB)数据集。PTB数据集较小,训练速度快,应用于Mikolov的公开语言模型训练工具\[[2](#参考文献)\]中。其统计情况如下:
@@ -144,7 +149,7 @@ CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去
-执行以下命令,可下载该数据集,并分别将训练数据和验证数据输入train.list和test.list文件中,供PaddlePaddle训练时使用。
+执行以下命令,可下载该数据集,并分别将训练数据和验证数据输入`train.list`和`test.list`文件中,供PaddlePaddle训练时使用。
```bash
./data/getdata.sh
@@ -221,7 +226,7 @@ CBOW的好处是对上下文词语的分布在词向量上进行了平滑,去
### 数据定义
-通过define_py_data_sources2函数从dataprovider中读入数据,其中args指定了训练文本(srcText)和词汇表(dictfile)。
+通过`define_py_data_sources2`函数从dataprovider中读入数据,其中args指定了训练文本(srcText)和词汇表(dictfile)。
```python
from paddle.trainer_config_helpers import *
@@ -263,7 +268,7 @@ settings(
nextword = data_layer(name = "fifthw", size = dictsize)
```
-2. 将$w_t$之前的$n-1$个词 $w_{t-n+1},...w_{t-1}$通过$|V|\times D$的矩阵映射到D维词向量(本例中取D=32)。
+2. 将$w_t$之前的$n-1$个词 $w_{t-n+1},...w_{t-1}$,通过$|V|\times D$的矩阵映射到D维词向量(本例中取D=32)。
```python
def wordemb(inlayer):
@@ -286,7 +291,7 @@ settings(
```python
contextemb = concat_layer(input = [Efirst, Esecond, Ethird, Efourth])
```
-4. 然后,将文本上文特征层经过一个全连接到文本隐层特征层
+4. 然后,将历史文本特征经过一个全连接得到文本隐层特征。
```python
hidden1 = fc_layer(
@@ -300,7 +305,7 @@ settings(
learning_rate = 1))
```
-5. 最后,将文本隐层特征层,再经过一个全连接,映射成一个`|V|`维向量,同时通过softmax归一化得到这`|V|`个词的生成概率。
+5. 最后,将文本隐层特征,再经过一个全连接,映射成一个`|V|`维向量,同时通过softmax归一化得到这`|V|`个词的生成概率。
```python
# use context embedding to predict nextword
@@ -311,7 +316,7 @@ settings(
act = SoftmaxActivation())
```
-6. 网络的损失函数为多分类交叉熵,可直接调用classification_cost函数。
+6. 网络的损失函数为多分类交叉熵,可直接调用`classification_cost`函数。
```python
cost = classification_cost(
@@ -323,7 +328,7 @@ settings(
##训练模型
-模型训练命令为./train.sh。脚本内容如下,其中指定了总共需要执行30个pass。
+模型训练命令为`./train.sh`。脚本内容如下,其中指定了总共需要执行30个pass。
```bash
paddle train \
@@ -369,16 +374,14 @@ PaddlePaddle训练出来的参数为二进制格式,存储在对应训练pass
```bash
python format_convert.py --b2t -i INPUT -o OUTPUT -d DIM
```
--i INPUT: 输入的(二进制)词向量模型名称
--o OUTPUT: 输出的文本模型名称
--d DIM: (词向量)参数维度
+其中,INPUT是输入的(二进制)词向量模型名称,OUTPUT是输出的文本模型名称,DIM是词向量参数维度。
用法如:
```bash
python format_convert.py --b2t -i model/pass-00029/_proj -o model/pass-00029/_proj.txt -d 32
```
-转换后得到的文本文件中,第一行为文件信息,之后每一行都按顺序表示字典里一个词的特征,用逗号分隔, 如:
+转换后得到的文本文件如下:
```text
0,4,62496
@@ -387,14 +390,15 @@ python format_convert.py --b2t -i model/pass-00029/_proj -o model/pass-00029/_pr
......
```
-其中,第一行是PaddlePaddle 输出文件的格式说明,包含3个属性:
-1. PaddlePaddle的版本号,本例中为0
-2. 浮点数占用的字节数,本例中为4
-3. 总计的参数个数, 本例中为62496(即1953*32)
+其中,第一行是PaddlePaddle 输出文件的格式说明,包含3个属性:
+1). PaddlePaddle的版本号,本例中为0;
+2). 浮点数占用的字节数,本例中为4;
+3). 总计的参数个数, 本例中为62496(即1953*32);
+第二行及之后的每一行都按顺序表示字典里一个词的特征,用逗号分隔。
### 修改词向量
-我们可以对词向量进行修改,并转换成paddle参数二进制格式,方法:
+我们可以对词向量进行修改,并转换成PaddlePaddle参数二进制格式,方法:
```bash
python format_convert.py --t2b -i INPUT -o OUTPUT
@@ -402,15 +406,13 @@ python format_convert.py --t2b -i INPUT -o OUTPUT
-i INPUT: 输入的文本词向量模型名称
-o OUTPUT: 输出的二进制词向量模型名称
-输入的文本格式如下:
+输入的文本格式如下(注意,不包含上面二进制转文本后第一行的格式说明):
```text
-0.7444070,-0.1846171,-1.5771370,0.7070392,2.1963732,-0.0091410, ......
-0.0721337,-0.2429973,-0.0606297,0.1882059,-0.2072131,-0.7661019, ......
......
```
-
-注意输入的文本特征,不包上面二进制转文本后第一行的格式说明。
@@ -436,7 +438,7 @@ python calculate_dis.py data/vocabulary.txt model/pass-00029/_proj.txt
## 参考文献
1. Bengio Y, Ducharme R, Vincent P, et al. [A neural probabilistic language model](http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf)[J]. journal of machine learning research, 2003, 3(Feb): 1137-1155.
-2. Mikolov T, Sutskever I, Chen K, et al. [Distributed representations of words and phrases and their compositionality](http://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf)[C]//Advances in neural information processing systems. 2013: 3111-3119.
-3. Mikolov T, Kombrink S, Deoras A, et al. [Rnnlm-recurrent neural network language modeling toolkit](http://www.fit.vutbr.cz/~imikolov/rnnlm/rnnlm-demo.pdf)[C]//Proc. of the 2011 ASRU Workshop. 2011: 196-201.
-4. Mikolov T, Chen K, Corrado G, et al. [Efficient estimation of word representations in vector space](https://arxiv.org/pdf/1301.3781.pdf)[J]. arXiv preprint arXiv:1301.3781, 2013.
-5. Maaten L, Hinton G. [Visualizing data using t-SNE](https://lvdmaaten.github.io/publications/papers/JMLR_2008.pdf)[J]. Journal of Machine Learning Research, 2008, 9(Nov): 2579-2605.
+2. Mikolov T, Kombrink S, Deoras A, et al. [Rnnlm-recurrent neural network language modeling toolkit](http://www.fit.vutbr.cz/~imikolov/rnnlm/rnnlm-demo.pdf)[C]//Proc. of the 2011 ASRU Workshop. 2011: 196-201.
+3. Mikolov T, Chen K, Corrado G, et al. [Efficient estimation of word representations in vector space](https://arxiv.org/pdf/1301.3781.pdf)[J]. arXiv preprint arXiv:1301.3781, 2013.
+4. Maaten L, Hinton G. [Visualizing data using t-SNE](https://lvdmaaten.github.io/publications/papers/JMLR_2008.pdf)[J]. Journal of Machine Learning Research, 2008, 9(Nov): 2579-2605.
+5. https://en.wikipedia.org/wiki/Singular_value_decomposition