index.html 24.6 KB
Newer Older
1

Y
Yu Yang 已提交
2 3 4 5
<html>
<head>
  <script type="text/x-mathjax-config">
  MathJax.Hub.Config({
Y
Yu Yang 已提交
6
    extensions: ["tex2jax.js", "TeX/AMSsymbols.js", "TeX/AMSmath.js"],
Y
Yu Yang 已提交
7 8
    jax: ["input/TeX", "output/HTML-CSS"],
    tex2jax: {
9 10
      inlineMath: [ ['$','$'] ],
      displayMath: [ ['$$','$$'] ],
Y
Yu Yang 已提交
11 12 13 14
      processEscapes: true
    },
    "HTML-CSS": { availableFonts: ["TeX"] }
  });
Y
Yi Wang 已提交
15 16
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js" async></script>
Y
Yu Yang 已提交
17
  <script type="text/javascript" src="../.tools/theme/marked.js">
Y
Yu Yang 已提交
18 19
  </script>
  <link href="http://cdn.bootcss.com/highlight.js/9.9.0/styles/darcula.min.css" rel="stylesheet">
Y
Yi Wang 已提交
20
  <script src="http://cdn.bootcss.com/highlight.js/9.9.0/highlight.min.js"></script>
Y
Yu Yang 已提交
21
  <link href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
Y
Yu Yang 已提交
22
  <link href="https://cdn.jsdelivr.net/perfect-scrollbar/0.6.14/css/perfect-scrollbar.min.css" rel="stylesheet">
Y
Yu Yang 已提交
23
  <link href="../.tools/theme/github-markdown.css" rel='stylesheet'>
Y
Yu Yang 已提交
24 25
</head>
<style type="text/css" >
Y
Yu Yang 已提交
26 27 28 29 30 31
.markdown-body {
    box-sizing: border-box;
    min-width: 200px;
    max-width: 980px;
    margin: 0 auto;
    padding: 45px;
Y
Yu Yang 已提交
32 33 34 35
}
</style>


Y
Yu Yang 已提交
36
<body>
Y
Yu Yang 已提交
37

Y
Yu Yang 已提交
38
<div id="context" class="container-fluid markdown-body">
Y
Yu Yang 已提交
39 40 41 42 43
</div>

<!-- This block will be replaced by each markdown file content. Please do not change lines below.-->
<div id="markdown" style='display:none'>
# 情感分析
Y
Yu Yang 已提交
44

45
本教程源代码目录在[book/understand_sentiment](https://github.com/PaddlePaddle/book/tree/develop/05.understand_sentiment), 初次使用请参考PaddlePaddle[安装教程](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/getstarted/build_and_install/docker_install_cn.rst)。
Y
Yu Yang 已提交
46

Y
Yu Yang 已提交
47
## 背景介绍
L
fix bug  
livc 已提交
48

Y
Yu Yang 已提交
49 50 51 52 53 54 55 56 57 58 59
在自然语言处理中,情感分析一般是指判断一段文本所表达的情绪状态。其中,一段文本可以是一个句子,一个段落或一个文档。情绪状态可以是两类,如(正面,负面),(高兴,悲伤);也可以是三类,如(积极,消极,中性)等等。情感分析的应用场景十分广泛,如把用户在购物网站(亚马逊、天猫、淘宝等)、旅游网站、电影评论网站上发表的评论分成正面评论和负面评论;或为了分析用户对于某一产品的整体使用感受,抓取产品的用户评论并进行情感分析等等。表格1展示了对电影评论进行情感分析的例子:

| 电影评论       | 类别  |
| --------     | -----  |
| 在冯小刚这几年的电影里,算最好的一部的了| 正面 |
| 很不好看,好像一个地方台的电视剧     | 负面 |
| 圆方镜头全程炫技,色调背景美则美矣,但剧情拖沓,口音不伦不类,一直努力却始终无法入戏| 负面|
|剧情四星。但是圆镜视角加上婺源的风景整个非常有中国写意山水画的感觉,看得实在太舒服了。。|正面|

<p align="center">表格 1 电影评论情感分析</p>

Y
Update  
Yi Wang 已提交
60
在自然语言处理中,情感分析属于典型的**文本分类**问题,即把需要进行情感分析的文本划分为其所属类别。文本分类涉及文本表示和分类方法两个问题。在深度学习的方法出现之前,主流的文本表示方法为词袋模型BOW(bag of words),话题模型等等;分类方法有SVM(support vector machine), LR(logistic regression)等等。  
Y
Yu Yang 已提交
61

Y
Update  
Yi Wang 已提交
62
对于一段文本,BOW表示会忽略其词顺序、语法和句法,将这段文本仅仅看做是一个词集合,因此BOW方法并不能充分表示文本的语义信息。例如,句子“这部电影糟糕透了”和“一个乏味,空洞,没有内涵的作品”在情感分析中具有很高的语义相似度,但是它们的BOW表示的相似度为0。又如,句子“一个空洞,没有内涵的作品”和“一个不空洞而且有内涵的作品”的BOW相似度很高,但实际上它们的意思很不一样。  
Y
Yu Yang 已提交
63 64

本章我们所要介绍的深度学习模型克服了BOW表示的上述缺陷,它在考虑词顺序的基础上把文本映射到低维度的语义空间,并且以端对端(end to end)的方式进行文本表示及分类,其性能相对于传统方法有显著的提升\[[1](#参考文献)\]。
L
fix bug  
livc 已提交
65

Y
Yu Yang 已提交
66
## 模型概览
L
fix bug  
livc 已提交
67

Y
Yu Yang 已提交
68
本章所使用的文本表示模型为卷积神经网络(Convolutional Neural Networks)和循环神经网络(Recurrent Neural Networks)及其扩展。下面依次介绍这几个模型。
L
fix bug  
livc 已提交
69

Y
Yu Yang 已提交
70
### 文本卷积神经网络(CNN)
L
fix bug  
livc 已提交
71

Y
Update  
Yi Wang 已提交
72
卷积神经网络经常用来处理具有类似网格拓扑结构(grid-like topology)的数据。例如,图像可以视为二维网格的像素点,自然语言可以视为一维的词序列。卷积神经网络可以提取多种局部特征,并对其进行组合抽象得到更高级的特征表示。实验表明,卷积神经网络能高效地对图像及文本问题进行建模处理。  
Y
Yu Yang 已提交
73 74

卷积神经网络主要由卷积(convolution)和池化(pooling)操作构成,其应用及组合方式灵活多变,种类繁多。本小结我们以一种简单的文本分类卷积神经网络为例进行讲解\[[1](#参考文献)\],如图1所示:
L
fix bug  
livc 已提交
75

Y
Yu Yang 已提交
76 77 78 79
<p align="center">
<img src="image/text_cnn.png" width = "80%" align="center"/><br/>
图1. 卷积神经网络文本分类模型
</p>
L
fix bug  
livc 已提交
80

Y
Update  
Yi Wang 已提交
81
假设待处理句子的长度为$n$,其中第$i$个词的词向量(word embedding)为$x_i\in\mathbb{R}^k$,$k$为维度大小。  
Y
Yu Yang 已提交
82

Y
Update  
Yi Wang 已提交
83
首先,进行词向量的拼接操作:将每$h$个词拼接起来形成一个大小为$h$的词窗口,记为$x_{i:i+h-1}$,它表示词序列$x_{i},x_{i+1},\ldots,x_{i+h-1}$的拼接,其中,$i$表示词窗口中第一个词在整个句子中的位置,取值范围从$1$到$n-h+1$,$x_{i:i+h-1}\in\mathbb{R}^{hk}$。  
Y
Yu Yang 已提交
84 85 86 87 88 89 90 91 92

其次,进行卷积操作:把卷积核(kernel)$w\in\mathbb{R}^{hk}$应用于包含$h$个词的窗口$x_{i:i+h-1}$,得到特征$c_i=f(w\cdot x_{i:i+h-1}+b)$,其中$b\in\mathbb{R}$为偏置项(bias),$f$为非线性激活函数,如$sigmoid$。将卷积核应用于句子中所有的词窗口${x_{1:h},x_{2:h+1},\ldots,x_{n-h+1:n}}$,产生一个特征图(feature map):

$$c=[c_1,c_2,\ldots,c_{n-h+1}], c \in \mathbb{R}^{n-h+1}$$

接下来,对特征图采用时间维度上的最大池化(max pooling over time)操作得到此卷积核对应的整句话的特征$\hat c$,它是特征图中所有元素的最大值:

$$\hat c=max(c)$$

Y
Update  
Yi Wang 已提交
93
在实际应用中,我们会使用多个卷积核来处理句子,窗口大小相同的卷积核堆叠起来形成一个矩阵(上文中的单个卷积核参数$w$相当于矩阵的某一行),这样可以更高效的完成运算。另外,我们也可使用窗口大小不同的卷积核来处理句子(图1作为示意画了四个卷积核,不同颜色表示不同大小的卷积核操作)。  
Y
Yu Yang 已提交
94 95 96 97

最后,将所有卷积核得到的特征拼接起来即为文本的定长向量表示,对于文本分类问题,将其连接至softmax即构建出完整的模型。

对于一般的短文本分类问题,上文所述的简单的文本卷积网络即可达到很高的正确率\[[1](#参考文献)\]。若想得到更抽象更高级的文本特征表示,可以构建深层文本卷积神经网络\[[2](#参考文献),[3](#参考文献)\]。
L
fix bug  
livc 已提交
98

Y
Yu Yang 已提交
99
### 循环神经网络(RNN)
L
fix bug  
livc 已提交
100

Y
Yu Yang 已提交
101
循环神经网络是一种能对序列数据进行精确建模的有力工具。实际上,循环神经网络的理论计算能力是图灵完备的\[[4](#参考文献)\]。自然语言是一种典型的序列数据(词序列),近年来,循环神经网络及其变体(如long short term memory\[[5](#参考文献)\]等)在自然语言处理的多个领域,如语言模型、句法解析、语义角色标注(或一般的序列标注)、语义表示、图文生成、对话、机器翻译等任务上均表现优异甚至成为目前效果最好的方法。
L
fix bug  
livc 已提交
102

Y
Yu Yang 已提交
103 104 105 106
<p align="center">
<img src="image/rnn.png" width = "60%" align="center"/><br/>
图2. 循环神经网络按时间展开的示意图
</p>
L
fix bug  
livc 已提交
107

Y
Yu Yang 已提交
108 109 110 111
循环神经网络按时间展开后如图2所示:在第$t$时刻,网络读入第$t$个输入$x_t$(向量表示)及前一时刻隐层的状态值$h_{t-1}$(向量表示,$h_0$一般初始化为$0$向量),计算得出本时刻隐层的状态值$h_t$,重复这一步骤直至读完所有输入。如果将循环神经网络所表示的函数记为$f$,则其公式可表示为:

$$h_t=f(x_t,h_{t-1})=\sigma(W_{xh}x_t+W_{hh}h_{h-1}+b_h)$$

Y
Update  
Yi Wang 已提交
112
其中$W_{xh}$是输入到隐层的矩阵参数,$W_{hh}$是隐层到隐层的矩阵参数,$b_h$为隐层的偏置向量(bias)参数,$\sigma$为$sigmoid$函数。  
113

Y
Update  
Yi Wang 已提交
114
在处理自然语言时,一般会先将词(one-hot表示)映射为其词向量(word embedding)表示,然后再作为循环神经网络每一时刻的输入$x_t$。此外,可以根据实际需要的不同在循环神经网络的隐层上连接其它层。如,可以把一个循环神经网络的隐层输出连接至下一个循环神经网络的输入构建深层(deep or stacked)循环神经网络,或者提取最后一个时刻的隐层状态作为句子表示进而使用分类模型等等。  
Y
Yu Yang 已提交
115 116

### 长短期记忆网络(LSTM)
L
fix bug  
livc 已提交
117

Y
Update  
Yi Wang 已提交
118
对于较长的序列数据,循环神经网络的训练过程中容易出现梯度消失或爆炸现象\[[6](#参考文献)\]。为了解决这一问题,Hochreiter S, Schmidhuber J. (1997)提出了LSTM(long short term memory\[[5](#参考文献)\])。  
Y
Yu Yang 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132

相比于简单的循环神经网络,LSTM增加了记忆单元$c$、输入门$i$、遗忘门$f$及输出门$o$。这些门及记忆单元组合起来大大提升了循环神经网络处理长序列数据的能力。若将基于LSTM的循环神经网络表示的函数记为$F$,则其公式为:

$$ h_t=F(x_t,h_{t-1})$$

$F$由下列公式组合而成\[[7](#参考文献)\]:
\begin{align}
i_t & = \sigma(W_{xi}x_t+W_{hi}h_{h-1}+W_{ci}c_{t-1}+b_i)\\\\
f_t & = \sigma(W_{xf}x_t+W_{hf}h_{h-1}+W_{cf}c_{t-1}+b_f)\\\\
c_t & = f_t\odot c_{t-1}+i_t\odot tanh(W_{xc}x_t+W_{hc}h_{h-1}+b_c)\\\\
o_t & = \sigma(W_{xo}x_t+W_{ho}h_{h-1}+W_{co}c_{t}+b_o)\\\\
h_t & = o_t\odot tanh(c_t)\\\\
\end{align}
其中,$i_t, f_t, c_t, o_t$分别表示输入门,遗忘门,记忆单元及输出门的向量值,带角标的$W$及$b$为模型参数,$tanh$为双曲正切函数,$\odot$表示逐元素(elementwise)的乘法操作。输入门控制着新输入进入记忆单元$c$的强度,遗忘门控制着记忆单元维持上一时刻值的强度,输出门控制着输出记忆单元的强度。三种门的计算方式类似,但有着完全不同的参数,它们各自以不同的方式控制着记忆单元$c$,如图3所示:
L
fix bug  
livc 已提交
133

Y
Yu Yang 已提交
134
<p align="center">
Y
Yu Yang 已提交
135
<img src="image/lstm.png" width = "65%" align="center"/><br/>
Y
Yu Yang 已提交
136 137
图3. 时刻$t$的LSTM [7]
</p>
L
fix bug  
livc 已提交
138

Y
Yu Yang 已提交
139 140 141 142 143
LSTM通过给简单的循环神经网络增加记忆及控制门的方式,增强了其处理远距离依赖问题的能力。类似原理的改进还有Gated Recurrent Unit (GRU)\[[8](#参考文献)\],其设计更为简洁一些。**这些改进虽然各有不同,但是它们的宏观描述却与简单的循环神经网络一样(如图2所示),即隐状态依据当前输入及前一时刻的隐状态来改变,不断地循环这一过程直至输入处理完毕:**

$$ h_t=Recrurent(x_t,h_{t-1})$$

其中,$Recrurent$可以表示简单的循环神经网络、GRU或LSTM。
L
fix bug  
livc 已提交
144

Y
Yu Yang 已提交
145
### 栈式双向LSTM(Stacked Bidirectional LSTM)
L
fix bug  
livc 已提交
146

Y
Update  
Yi Wang 已提交
147
对于正常顺序的循环神经网络,$h_t$包含了$t$时刻之前的输入信息,也就是上文信息。同样,为了得到下文信息,我们可以使用反方向(将输入逆序处理)的循环神经网络。结合构建深层循环神经网络的方法(深层神经网络往往能得到更抽象和高级的特征表示),我们可以通过构建更加强有力的基于LSTM的栈式双向循环神经网络\[[9](#参考文献)\],来对时序数据进行建模。  
Y
Yu Yang 已提交
148 149

如图4所示(以三层为例),奇数层LSTM正向,偶数层LSTM反向,高一层的LSTM使用低一层LSTM及之前所有层的信息作为输入,对最高层LSTM序列使用时间维度上的最大池化即可得到文本的定长向量表示(这一表示充分融合了文本的上下文信息,并且对文本进行了深层次抽象),最后我们将文本表示连接至softmax构建分类模型。
L
fix bug  
livc 已提交
150

Y
Yu Yang 已提交
151 152 153 154 155
<p align="center">
<img src="image/stacked_lstm.jpg" width=450><br/>
图4. 栈式双向LSTM用于文本分类
</p>

L
Luo Tao 已提交
156
## 示例程序
L
fix bug  
livc 已提交
157

L
Luo Tao 已提交
158
### 数据集介绍
L
fix bug  
livc 已提交
159

L
Luo Tao 已提交
160 161 162 163 164 165 166 167 168
我们以[IMDB情感分析数据集](http://ai.stanford.edu/%7Eamaas/data/sentiment/)为例进行介绍。IMDB数据集的训练集和测试集分别包含25000个已标注过的电影评论。其中,负面评论的得分小于等于4,正面评论的得分大于等于7,满分10分。
```text
aclImdb
|- test
   |-- neg
   |-- pos
|- train
   |-- neg
   |-- pos
Y
Yu Yang 已提交
169
```
L
Luo Tao 已提交
170
Paddle在`dataset/imdb.py`中提实现了imdb数据集的自动下载和读取,并提供了读取字典、训练数据、测试数据等API。
Y
Yu Yang 已提交
171

H
hedaoyuan 已提交
172
```python
L
Luo Tao 已提交
173 174
import sys
import paddle.v2 as paddle
Y
Yu Yang 已提交
175
```
L
Luo Tao 已提交
176
## 配置模型
L
fix bug  
livc 已提交
177

L
Luo Tao 已提交
178
在该示例中,我们实现了两种文本分类算法,分别基于上文所述的[文本卷积神经网络](#文本卷积神经网络(CNN))和[栈式双向LSTM](#栈式双向LSTM(Stacked Bidirectional LSTM))。
L
fix bug  
livc 已提交
179

L
Luo Tao 已提交
180
### 文本卷积神经网络
L
fix bug  
livc 已提交
181

H
hedaoyuan 已提交
182
```python
Y
Yu Yang 已提交
183 184 185
def convolution_net(input_dim,
                    class_dim=2,
                    emb_dim=128,
L
Luo Tao 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
                    hid_dim=128):
    data = paddle.layer.data("word",
                             paddle.data_type.integer_value_sequence(input_dim))
    emb = paddle.layer.embedding(input=data, size=emb_dim)
    conv_3 = paddle.networks.sequence_conv_pool(
        input=emb, context_len=3, hidden_size=hid_dim)
    conv_4 = paddle.networks.sequence_conv_pool(
        input=emb, context_len=4, hidden_size=hid_dim)
    output = paddle.layer.fc(input=[conv_3, conv_4],
                             size=class_dim,
                             act=paddle.activation.Softmax())
    lbl = paddle.layer.data("label", paddle.data_type.integer_value(2))
    cost = paddle.layer.classification_cost(input=output, label=lbl)
    return cost
```
网络的输入`input_dim`表示的是词典的大小,`class_dim`表示类别数。这里,我们使用[`sequence_conv_pool`](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/trainer_config_helpers/networks.py) API实现了卷积和池化操作。
L
fix bug  
livc 已提交
202

L
Luo Tao 已提交
203
### 栈式双向LSTM
L
fix bug  
livc 已提交
204

H
hedaoyuan 已提交
205
```python
Y
Yu Yang 已提交
206 207 208 209
def stacked_lstm_net(input_dim,
                     class_dim=2,
                     emb_dim=128,
                     hid_dim=512,
L
Luo Tao 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223
                     stacked_num=3):
    """
    A Wrapper for sentiment classification task.
    This network uses bi-directional recurrent network,
    consisting three LSTM layers. This configure is referred to
    the paper as following url, but use fewer layrs.
        http://www.aclweb.org/anthology/P15-1109

    input_dim: here is word dictionary dimension.
    class_dim: number of categories.
    emb_dim: dimension of word embedding.
    hid_dim: dimension of hidden layer.
    stacked_num: number of stacked lstm-hidden layer.
    """
Y
Yu Yang 已提交
224 225
    assert stacked_num % 2 == 1

H
hedaoyuan 已提交
226 227 228
    layer_attr = paddle.attr.Extra(drop_rate=0.5)
    fc_para_attr = paddle.attr.Param(learning_rate=1e-3)
    lstm_para_attr = paddle.attr.Param(initial_std=0., learning_rate=1.)
L
Luo Tao 已提交
229
    para_attr = [fc_para_attr, lstm_para_attr]
H
hedaoyuan 已提交
230
    bias_attr = paddle.attr.Param(initial_std=0., l2_rate=0.)
L
Luo Tao 已提交
231 232 233 234 235 236 237 238 239 240 241 242
    relu = paddle.activation.Relu()
    linear = paddle.activation.Linear()

    data = paddle.layer.data("word",
                             paddle.data_type.integer_value_sequence(input_dim))
    emb = paddle.layer.embedding(input=data, size=emb_dim)

    fc1 = paddle.layer.fc(input=emb,
                          size=hid_dim,
                          act=linear,
                          bias_attr=bias_attr)
    lstm1 = paddle.layer.lstmemory(
Y
Yu Yang 已提交
243 244 245 246
        input=fc1, act=relu, bias_attr=bias_attr, layer_attr=layer_attr)

    inputs = [fc1, lstm1]
    for i in range(2, stacked_num + 1):
L
Luo Tao 已提交
247 248 249 250 251 252
        fc = paddle.layer.fc(input=inputs,
                             size=hid_dim,
                             act=linear,
                             param_attr=para_attr,
                             bias_attr=bias_attr)
        lstm = paddle.layer.lstmemory(
Y
Yu Yang 已提交
253 254 255 256 257 258 259
            input=fc,
            reverse=(i % 2) == 0,
            act=relu,
            bias_attr=bias_attr,
            layer_attr=layer_attr)
        inputs = [fc, lstm]

H
hedaoyuan 已提交
260 261
    fc_last = paddle.layer.pooling(input=inputs[0], pooling_type=paddle.pooling.Max())
    lstm_last = paddle.layer.pooling(input=inputs[1], pooling_type=paddle.pooling.Max())
L
Luo Tao 已提交
262 263 264 265 266 267 268 269 270
    output = paddle.layer.fc(input=[fc_last, lstm_last],
                             size=class_dim,
                             act=paddle.activation.Softmax(),
                             bias_attr=bias_attr,
                             param_attr=para_attr)

    lbl = paddle.layer.data("label", paddle.data_type.integer_value(2))
    cost = paddle.layer.classification_cost(input=output, label=lbl)
    return cost
Y
Yu Yang 已提交
271
```
L
Luo Tao 已提交
272
网络的输入`stacked_num`表示的是LSTM的层数,需要是奇数,确保最高层LSTM正向。Paddle里面是通过一个fc和一个lstmemory来实现基于LSTM的循环神经网络。
L
fix bug  
livc 已提交
273

Y
Yu Yang 已提交
274
## 训练模型
L
fix bug  
livc 已提交
275

H
hedaoyuan 已提交
276
```python
L
Luo Tao 已提交
277 278 279
if __name__ == '__main__':
    # init
    paddle.init(use_gpu=False)
Y
Yu Yang 已提交
280
```
L
Luo Tao 已提交
281
启动paddle程序,use_gpu=False表示用CPU训练,如果系统支持GPU也可以修改成True使用GPU训练。
L
fix bug  
livc 已提交
282

L
Luo Tao 已提交
283
### 训练数据
L
fix bug  
livc 已提交
284

L
Luo Tao 已提交
285
使用Paddle提供的数据集`dataset.imdb`中的API来读取训练数据。
H
hedaoyuan 已提交
286
```python
L
Luo Tao 已提交
287 288 289 290
    print 'load dictionary...'
    word_dict = paddle.dataset.imdb.word_dict()
    dict_dim = len(word_dict)
    class_dim = 2
Y
Yu Yang 已提交
291
```
L
Luo Tao 已提交
292
加载数据字典,这里通过`word_dict()`API可以直接构造字典。`class_dim`是指样本类别数,该示例中样本只有正负两类。
H
hedaoyuan 已提交
293
```python
L
Luo Tao 已提交
294 295 296 297 298 299 300
    train_reader = paddle.batch(
        paddle.reader.shuffle(
            lambda: paddle.dataset.imdb.train(word_dict), buf_size=1000),
        batch_size=100)
    test_reader = paddle.batch(
        lambda: paddle.dataset.imdb.test(word_dict),
        batch_size=100)
Y
Yu Yang 已提交
301
```
L
Luo Tao 已提交
302
这里,`dataset.imdb.train()`和`dataset.imdb.test()`分别是`dataset.imdb`中的训练数据和测试数据API。`train_reader`在训练时使用,意义是将读取的训练数据进行shuffle后,组成一个batch数据。同理,`test_reader`是在测试的时候使用,将读取的测试数据组成一个batch。
H
hedaoyuan 已提交
303
```python
H
hedaoyuan 已提交
304
    feeding={'word': 0, 'label': 1}
Y
Yu Yang 已提交
305
```
H
hedaoyuan 已提交
306
`feeding`用来指定`train_reader`和`test_reader`返回的数据与模型配置中data_layer的对应关系。这里表示reader返回的第0列数据对应`word`层,第1列数据对应`label`层。
L
fix bug  
livc 已提交
307

L
Luo Tao 已提交
308
### 构造模型
L
fix bug  
livc 已提交
309

H
hedaoyuan 已提交
310
```python
L
Luo Tao 已提交
311 312 313 314
    # Please choose the way to build the network
    # by uncommenting the corresponding line.
    cost = convolution_net(dict_dim, class_dim=class_dim)
    # cost = stacked_lstm_net(dict_dim, class_dim=class_dim, stacked_num=3)
Y
Yu Yang 已提交
315
```
L
Luo Tao 已提交
316
该示例中默认使用`convolution_net`网络,如果使用`stacked_lstm_net`网络,注释相应的行即可。其中cost是网络的优化目标,同时cost包含了整个网络的拓扑信息。
L
fix bug  
livc 已提交
317

L
Luo Tao 已提交
318
### 网络参数
L
fix bug  
livc 已提交
319

H
hedaoyuan 已提交
320
```python
L
Luo Tao 已提交
321 322
    # create parameters
    parameters = paddle.parameters.create(cost)
Y
Yu Yang 已提交
323
```
L
Luo Tao 已提交
324
根据网络的拓扑构造网络参数。这里parameters是整个网络的参数集。
L
fix bug  
livc 已提交
325

L
Luo Tao 已提交
326
### 优化算法
L
fix bug  
livc 已提交
327

H
hedaoyuan 已提交
328
```python
L
Luo Tao 已提交
329 330 331 332 333 334 335
    # create optimizer
    adam_optimizer = paddle.optimizer.Adam(
        learning_rate=2e-3,
        regularization=paddle.optimizer.L2Regularization(rate=8e-4),
        model_average=paddle.optimizer.ModelAverage(average_window=0.5))
```
Paddle中提供了一系列优化算法的API,这里使用Adam优化算法。
L
fix bug  
livc 已提交
336

L
Luo Tao 已提交
337
### 训练
L
fix bug  
livc 已提交
338

L
Luo Tao 已提交
339
可以通过`paddle.trainer.SGD`构造一个sgd trainer,并调用`trainer.train`来训练模型。
H
hedaoyuan 已提交
340
```python
L
Luo Tao 已提交
341 342 343 344 345 346 347 348 349 350
    # End batch and end pass event handler
    def event_handler(event):
        if isinstance(event, paddle.event.EndIteration):
            if event.batch_id % 100 == 0:
                print "\nPass %d, Batch %d, Cost %f, %s" % (
                    event.pass_id, event.batch_id, event.cost, event.metrics)
            else:
                sys.stdout.write('.')
                sys.stdout.flush()
        if isinstance(event, paddle.event.EndPass):
H
hedaoyuan 已提交
351
            result = trainer.test(reader=test_reader, feeding=feeding)
L
Luo Tao 已提交
352 353 354
            print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
```
可以通过给train函数传递一个`event_handler`来获取每个batch和每个pass结束的状态。比如构造如下一个`event_handler`可以在每100个batch结束后输出cost和error;在每个pass结束后调用`trainer.test`计算一遍测试集并获得当前模型在测试集上的error。
H
hedaoyuan 已提交
355
```python
L
Luo Tao 已提交
356 357 358 359 360 361 362 363
    # create trainer
    trainer = paddle.trainer.SGD(cost=cost,
                                 parameters=parameters,
                                 update_equation=adam_optimizer)

    trainer.train(
        reader=train_reader,
        event_handler=event_handler,
H
hedaoyuan 已提交
364
        feeding=feeding,
L
Luo Tao 已提交
365 366 367
        num_passes=2)
```
程序运行之后的输出如下。
H
hedaoyuan 已提交
368
```text
L
Luo Tao 已提交
369 370 371 372 373
Pass 0, Batch 0, Cost 0.693721, {'classification_error_evaluator': 0.5546875}
...................................................................................................
Pass 0, Batch 100, Cost 0.294321, {'classification_error_evaluator': 0.1015625}
...............................................................................................
Test with Pass 0, {'classification_error_evaluator': 0.11432000249624252}
Y
Yu Yang 已提交
374 375 376
```

## 总结
L
fix bug  
livc 已提交
377

Y
Yu Yang 已提交
378
本章我们以情感分析为例,介绍了使用深度学习的方法进行端对端的短文本分类,并且使用PaddlePaddle完成了全部相关实验。同时,我们简要介绍了两种文本处理模型:卷积神经网络和循环神经网络。在后续的章节中我们会看到这两种基本的深度学习模型在其它任务上的应用。
L
fix bug  
livc 已提交
379

Y
Yu Yang 已提交
380
## 参考文献
L
fix bug  
livc 已提交
381

Y
Yu Yang 已提交
382 383 384 385 386 387 388 389 390 391 392 393
1. Kim Y. [Convolutional neural networks for sentence classification](http://arxiv.org/pdf/1408.5882)[J]. arXiv preprint arXiv:1408.5882, 2014.
2. Kalchbrenner N, Grefenstette E, Blunsom P. [A convolutional neural network for modelling sentences](http://arxiv.org/pdf/1404.2188.pdf?utm_medium=App.net&utm_source=PourOver)[J]. arXiv preprint arXiv:1404.2188, 2014.
3. Yann N. Dauphin, et al. [Language Modeling with Gated Convolutional Networks](https://arxiv.org/pdf/1612.08083v1.pdf)[J] arXiv preprint arXiv:1612.08083, 2016.
4. Siegelmann H T, Sontag E D. [On the computational power of neural nets](http://research.cs.queensu.ca/home/akl/cisc879/papers/SELECTED_PAPERS_FROM_VARIOUS_SOURCES/05070215382317071.pdf)[C]//Proceedings of the fifth annual workshop on Computational learning theory. ACM, 1992: 440-449.
5. Hochreiter S, Schmidhuber J. [Long short-term memory](http://web.eecs.utk.edu/~itamar/courses/ECE-692/Bobby_paper1.pdf)[J]. Neural computation, 1997, 9(8): 1735-1780.
6. Bengio Y, Simard P, Frasconi P. [Learning long-term dependencies with gradient descent is difficult](http://www-dsi.ing.unifi.it/~paolo/ps/tnn-94-gradient.pdf)[J]. IEEE transactions on neural networks, 1994, 5(2): 157-166.
7. Graves A. [Generating sequences with recurrent neural networks](http://arxiv.org/pdf/1308.0850)[J]. arXiv preprint arXiv:1308.0850, 2013.
8. Cho K, Van Merriënboer B, Gulcehre C, et al. [Learning phrase representations using RNN encoder-decoder for statistical machine translation](http://arxiv.org/pdf/1406.1078)[J]. arXiv preprint arXiv:1406.1078, 2014.
9. Zhou J, Xu W. [End-to-end learning of semantic role labeling using recurrent neural networks](http://www.aclweb.org/anthology/P/P15/P15-1109.pdf)[C]//Proceedings of the Annual Meeting of the Association for Computational Linguistics. 2015.

<br/>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/Text" property="dct:title" rel="dct:type">本教程</span><a xmlns:cc="http://creativecommons.org/ns#" href="http://book.paddlepaddle.org" property="cc:attributionName" rel="cc:attributionURL">PaddlePaddle</a> 创作,采用 <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议</a>进行许可。
394

Y
Yu Yang 已提交
395 396 397 398 399 400 401
</div>
<!-- You can change the lines below now. -->

<script type="text/javascript">
marked.setOptions({
  renderer: new marked.Renderer(),
  gfm: true,
Y
Yu Yang 已提交
402 403 404
  breaks: false,
  smartypants: true,
  highlight: function(code, lang) {
Y
Yu Yang 已提交
405
    code = code.replace(/&amp;/g, "&")
Y
Yu Yang 已提交
406 407
    code = code.replace(/&gt;/g, ">")
    code = code.replace(/&lt;/g, "<")
408
    code = code.replace(/&nbsp;/g, " ")
Y
Yu Yang 已提交
409
    return hljs.highlightAuto(code, [lang]).value;
Y
Yu Yang 已提交
410 411 412
  }
});
document.getElementById("context").innerHTML = marked(
413
        document.getElementById("markdown").innerHTML)
Y
Yu Yang 已提交
414 415
</script>
</body>