Skip to content

Commit 16ea66e

Browse files
committed
Merge branch 'develop' of github.com:baidu/Paddle into feature/mnist_train_api
2 parents 5a68584 + 4490bf9 commit 16ea66e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2229
-822
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ before_install:
5656
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo paddle/scripts/travis/before_install.linux.sh; fi
5757
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then paddle/scripts/travis/before_install.osx.sh; fi
5858
- if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi
59-
- pip install wheel protobuf sphinx recommonmark virtualenv numpy sphinx_rtd_theme pre-commit
59+
- pip install wheel protobuf sphinx recommonmark virtualenv numpy sphinx_rtd_theme pre-commit requests==2.9.2 LinkChecker
6060
script:
6161
- paddle/scripts/travis/main.sh
6262
notifications:

cmake/util.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ function(link_paddle_exe TARGET_NAME)
9696
target_circle_link_libraries(${TARGET_NAME}
9797
ARCHIVE_START
9898
paddle_gserver
99+
paddle_function
99100
${METRIC_LIBS}
100101
ARCHIVE_END
101102
paddle_pserver
@@ -106,6 +107,7 @@ function(link_paddle_exe TARGET_NAME)
106107
paddle_parameter
107108
paddle_proto
108109
paddle_cuda
110+
paddle_test_main
109111
${METRIC_LIBS}
110112
${PROTOBUF_LIBRARY}
111113
${LIBGLOG_LIBRARY}

demo/semantic_role_labeling/dataprovider.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def get_batch_size(yeild_data):
4343
init_hook=hook,
4444
should_shuffle=True,
4545
calc_batch_size=get_batch_size,
46-
can_over_batch_size=False,
46+
can_over_batch_size=True,
4747
cache=CacheType.CACHE_PASS_IN_MEM)
4848
def process(settings, file_name):
4949
with open(file_name, 'r') as fdata:

doc/getstarted/build_and_install/docker_install_en.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,20 @@ The general development workflow with Docker and Bazel is as follows:
3939
code. This image contains all the development tools and
4040
dependencies of PaddlePaddle.
4141

42-
4342
.. code-block:: bash
4443
4544
cd paddle
4645
docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile .
4746
47+
Sometimes docker build might suffer from a slow network connection to the official Ubuntu apt-source servers. In such case, we can specify an apt-source mirror server that is geologically nearer to us. In the following example, we specified an apt-source server that responds fast in China.You can specify the UBUNTU MIRROR with :code:`--build-arg UBUNTU_MIRROR` like the example below.
48+
49+
.. code-block:: bash
50+
51+
docker build \
52+
--build-arg UBUNTU_MIRROR="http://mirrors.163.com" \
53+
-t paddle:dev \
54+
-f paddle/scripts/docker/Dockerfile .
55+
4856
4957
3. Run the image as a container and mounting local source code
5058
directory into the container. This allows us to change the code on

doc/howto/deep_model/rnn/rnn_cn.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
RNN 配置
2+
=================
3+
4+
本教程将指导你如何在 PaddlePaddle 中配置循环神经网络(RNN)。PaddlePaddle 高度支持灵活和高效的循环神经网络配置。 在本教程中,您将了解如何:
5+
6+
- 准备用来学习循环神经网络的序列数据。
7+
- 配置循环神经网络架构。
8+
- 使用学习完成的循环神经网络模型生成序列。
9+
10+
我们将使用 vanilla 循环神经网络和 sequence to sequence 模型来指导你完成这些步骤。sequence to sequence 模型的代码可以在`demo / seqToseq`找到。
11+
12+
准备序列数据
13+
---------------------
14+
15+
PaddlePaddle 不需要对序列数据进行任何预处理,例如填充。唯一需要做的是将相应类型设置为输入。例如,以下代码段定义了三个输入。 它们都是序列,它们的大小是`src_dict``trg_dict``trg_dict`
16+
17+
``` sourceCode
18+
settings.input_types = [
19+
integer_value_sequence(len(settings.src_dict)),
20+
integer_value_sequence(len(settings.trg_dict)),
21+
integer_value_sequence(len(settings.trg_dict))]
22+
```
23+
24+
`process`函数中,每个`yield`函数将返回三个整数列表。每个整数列表被视为一个整数序列:
25+
26+
``` sourceCode
27+
yield src_ids, trg_ids, trg_ids_next
28+
```
29+
30+
有关如何编写数据提供程序的更多细节描述,请参考 [PyDataProvider2](../../ui/data_provider/index.html)。完整的数据提供文件在 `demo/seqToseq/dataprovider.py`
31+
32+
配置循环神经网络架构
33+
-----------------------------------------------
34+
35+
### 简单门控循环神经网络(Gated Recurrent Neural Network)
36+
37+
循环神经网络在每个时间步骤顺序地处理序列。下面列出了 LSTM 的架构的示例。
38+
39+
![image](../../../tutorials/sentiment_analysis/bi_lstm.jpg)
40+
41+
一般来说,循环网络从 *t* = 1 到 *t* = *T* 或者反向地从 *t* = *T**t* = 1 执行以下操作。
42+
43+
*x*<sub>*t* + 1</sub> = *f*<sub>*x*</sub>(*x*<sub>*t*</sub>),*y*<sub>*t*</sub> = *f*<sub>*y*</sub>(*x*<sub>*t*</sub>)
44+
45+
其中 *f*<sub>*x*</sub>(.) 称为**单步函数**(即单时间步执行的函数,step function),而 *f*<sub>*y*</sub>(.) 称为**输出函数**。在 vanilla 循环神经网络中,单步函数和输出函数都非常简单。然而,PaddlePaddle 可以通过修改这两个函数来实现复杂的网络配置。我们将使用 sequence to sequence 模型演示如何配置复杂的循环神经网络模型。在本节中,我们将使用简单的 vanilla 循环神经网络作为使用`recurrent_group`配置简单循环神经网络的例子。 注意,如果你只需要使用简单的RNN,GRU或LSTM,那么推荐使用`grumemory``lstmemory`,因为它们的计算效率比`recurrent_group`更高。
46+
47+
对于 vanilla RNN,在每个时间步长,**单步函数**为:
48+
49+
*x*<sub>*t* + 1</sub> = *W*<sub>*x*</sub>*x*<sub>*t*</sub> + *W*<sub>*i*</sub>*I*<sub>*t*</sub> + *b*
50+
51+
其中 *x*<sub>*t*</sub> 是RNN状态,并且 *I*<sub>*t*</sub> 是输入,*W*<sub>*x*</sub> 和 *W*<sub>*i*</sub> 分别是RNN状态和输入的变换矩阵。*b* 是偏差。它的**输出函数**只需要*x*<sub>*t*</sub>作为输出。
52+
53+
`recurrent_group`是构建循环神经网络的最重要的工具。 它定义了**单步函数****输出函数**和循环神经网络的输入。注意,这个函数的`step`参数需要实现`step function`(单步函数)和`output function`(输出函数):
54+
55+
56+
``` sourceCode
57+
def simple_rnn(input,
58+
size=None,
59+
name=None,
60+
reverse=False,
61+
rnn_bias_attr=None,
62+
act=None,
63+
rnn_layer_attr=None):
64+
def __rnn_step__(ipt):
65+
out_mem = memory(name=name, size=size)
66+
rnn_out = mixed_layer(input = [full_matrix_projection(ipt),
67+
full_matrix_projection(out_mem)],
68+
name = name,
69+
bias_attr = rnn_bias_attr,
70+
act = act,
71+
layer_attr = rnn_layer_attr,
72+
size = size)
73+
return rnn_out
74+
return recurrent_group(name='%s_recurrent_group' % name,
75+
step=__rnn_step__,
76+
reverse=reverse,
77+
input=input)
78+
```
79+
80+
PaddlePaddle 使用“Memory”(记忆模块)实现单步函数。**Memory**是在PaddlePaddle中构造循环神经网络时最重要的概念。 Memory是在单步函数中循环使用的状态,例如*x*<sub>*t* + 1</sub> = *f*<sub>*x*</sub>(*x*<sub>*t*</sub>)。 一个Memory包含**输出****输入**。当前时间步处的Memory的输出作为下一时间步Memory的输入。Memory也可以具有**boot layer(引导层)**,其输出被用作Memory的初始值。 在我们的例子中,门控循环单元的输出被用作输出Memory。请注意,`rnn_out`层的名称与`out_mem`的名称相同。这意味着`rnn_out` (*x*<sub>*t* + 1</sub>)的输出被用作`out_mem`Memory的**输出**
81+
82+
Memory也可以是序列。在这种情况下,在每个时间步中,我们有一个序列作为循环神经网络的状态。这在构造非常复杂的循环神经网络时是有用的。 其他高级功能包括定义多个Memory,以及使用子序列来定义分级循环神经网络架构。
83+
84+
我们在函数的结尾返回`rnn_out`。 这意味着 `rnn_out` 层的输出被用作门控循环神经网络的**输出**函数。
85+
86+
### Sequence to Sequence Model with Attention
87+
88+
我们将使用 sequence to sequence model with attention 作为例子演示如何配置复杂的循环神经网络模型。该模型的说明如下图所示。
89+
90+
![image](../../../tutorials/text_generation/encoder-decoder-attention-model.png)
91+
92+
在这个模型中,源序列 *S* = {*s*<sub>1</sub>, …, *s*<sub>*T*</sub>} 用双向门控循环神经网络编码。双向门控循环神经网络的隐藏状态 *H*<sub>*S*</sub> = {*H*<sub>1</sub>, …, *H*<sub>*T*</sub>} 被称为 *编码向量*。解码器是门控循环神经网络。当解读每一个*y*<sub>*t*</sub>时, 这个门控循环神经网络生成一系列权重 *W*<sub>*S*</sub><sup>*t*</sup> = {*W*<sub>1</sub><sup>*t*</sup>, …, *W*<sub>*T*</sub><sup>*t*</sup>}, 用于计算编码向量的加权和。加权和用来生成*y*<sub>*t*</sub>。
93+
94+
模型的编码器部分如下所示。它叫做`grumemory`来表示门控循环神经网络。如果网络架构简单,那么推荐使用循环神经网络的方法,因为它比 `recurrent_group` 更快。我们已经实现了大多数常用的循环神经网络架构,可以参考 [Layers](../../ui/api/trainer_config_helpers/layers_index.html) 了解更多细节。
95+
96+
我们还将编码向量投射到 `decoder_size` 维空间。这通过获得反向循环网络的第一个实例,并将其投射到 `decoder_size` 维空间完成:
97+
98+
``` sourceCode
99+
# 定义源语句的数据层
100+
src_word_id = data_layer(name='source_language_word', size=source_dict_dim)
101+
# 计算每个词的词向量
102+
src_embedding = embedding_layer(
103+
input=src_word_id,
104+
size=word_vector_dim,
105+
param_attr=ParamAttr(name='_source_language_embedding'))
106+
# 应用前向循环神经网络
107+
src_forward = grumemory(input=src_embedding, size=encoder_size)
108+
# 应用反向递归神经网络(reverse=True表示反向循环神经网络)
109+
src_backward = grumemory(input=src_embedding,
110+
size=encoder_size,
111+
reverse=True)
112+
# 将循环神经网络的前向和反向部分混合在一起
113+
encoded_vector = concat_layer(input=[src_forward, src_backward])
114+
115+
# 投射编码向量到 decoder_size
116+
encoder_proj = mixed_layer(input = [full_matrix_projection(encoded_vector)],
117+
size = decoder_size)
118+
119+
# 计算反向RNN的第一个实例
120+
backward_first = first_seq(input=src_backward)
121+
122+
# 投射反向RNN的第一个实例到 decoder size
123+
decoder_boot = mixed_layer(input=[full_matrix_projection(backward_first)], size=decoder_size, act=TanhActivation())
124+
```
125+
126+
解码器使用 `recurrent_group` 来定义循环神经网络。单步函数和输出函数在 `gru_decoder_with_attention` 中定义:
127+
128+
``` sourceCode
129+
group_inputs=[StaticInput(input=encoded_vector,is_seq=True),
130+
StaticInput(input=encoded_proj,is_seq=True)]
131+
trg_embedding = embedding_layer(
132+
input=data_layer(name='target_language_word',
133+
size=target_dict_dim),
134+
size=word_vector_dim,
135+
param_attr=ParamAttr(name='_target_language_embedding'))
136+
group_inputs.append(trg_embedding)
137+
138+
# 对于配备有注意力机制的解码器,在训练中,
139+
# 目标向量(groudtruth)是数据输入,
140+
# 而源序列的编码向量可以被无边界的memory访问
141+
# StaticInput 意味着不同时间步的输入都是相同的值,
142+
# 否则它以一个序列输入,不同时间步的输入是不同的。
143+
# 所有输入序列应该有相同的长度。
144+
decoder = recurrent_group(name=decoder_group_name,
145+
step=gru_decoder_with_attention,
146+
input=group_inputs)
147+
```
148+
149+
单步函数的实现如下所示。首先,它定义解码网络的**Memory**。然后定义 attention,门控循环单元单步函数和输出函数:
150+
151+
``` sourceCode
152+
def gru_decoder_with_attention(enc_vec, enc_proj, current_word):
153+
# 定义解码器的Memory
154+
# Memory的输出定义在 gru_step 内
155+
# 注意 gru_step 应该与它的Memory名字相同
156+
decoder_mem = memory(name='gru_decoder',
157+
size=decoder_size,
158+
boot_layer=decoder_boot)
159+
# 计算 attention 加权编码向量
160+
context = simple_attention(encoded_sequence=enc_vec,
161+
encoded_proj=enc_proj,
162+
decoder_state=decoder_mem)
163+
# 混合当前词向量和attention加权编码向量
164+
decoder_inputs = mixed_layer(inputs = [full_matrix_projection(context),
165+
full_matrix_projection(current_word)],
166+
size = decoder_size * 3)
167+
# 定义门控循环单元循环神经网络单步函数
168+
gru_step = gru_step_layer(name='gru_decoder',
169+
input=decoder_inputs,
170+
output_mem=decoder_mem,
171+
size=decoder_size)
172+
# 定义输出函数
173+
out = mixed_layer(input=[full_matrix_projection(input=gru_step)],
174+
size=target_dict_dim,
175+
bias_attr=True,
176+
act=SoftmaxActivation())
177+
return out
178+
```
179+
180+
生成序列
181+
-----------------
182+
183+
训练模型后,我们可以使用它来生成序列。通常的做法是使用**beam search** 生成序列。以下代码片段定义 beam search 算法。注意,`beam_search` 函数假设 `step` 的输出函数返回的是下一个时刻输出词的 softmax 归一化概率向量。我们对模型进行了以下更改。
184+
185+
- 使用 `GeneratedInput` 来表示 trg\_embedding。 `GeneratedInput` 将上一时间步所生成的词的向量来作为当前时间步的输入。
186+
- 使用 `beam_search` 函数。这个函数需要设置:
187+
- `bos_id`: 开始标记。每个句子都以开始标记开头。
188+
- `eos_id`: 结束标记。每个句子都以结束标记结尾。
189+
- `beam_size`: beam search 算法中的beam大小。
190+
- `max_length`: 生成序列的最大长度。
191+
- 使用 `seqtext_printer_evaluator` 根据索引矩阵和字典打印文本。这个函数需要设置:
192+
- `id_input`: 数据的整数ID,用于标识生成的文件中的相应输出。
193+
- `dict_file`: 用于将词ID转换为词的字典文件。
194+
- `result_file`: 生成结果文件的路径。
195+
196+
代码如下:
197+
198+
``` sourceCode
199+
group_inputs=[StaticInput(input=encoded_vector,is_seq=True),
200+
StaticInput(input=encoded_proj,is_seq=True)]
201+
# 在生成时,解码器基于编码源序列和最后生成的目标词预测下一目标词。
202+
# 编码源序列(编码器输出)必须由只读Memory的 StaticInput 指定。
203+
# 这里, GeneratedInputs 自动获取上一个生成的词,并在最开始初始化为起始词,如 <s>。
204+
trg_embedding = GeneratedInput(
205+
size=target_dict_dim,
206+
embedding_name='_target_language_embedding',
207+
embedding_size=word_vector_dim)
208+
group_inputs.append(trg_embedding)
209+
beam_gen = beam_search(name=decoder_group_name,
210+
step=gru_decoder_with_attention,
211+
input=group_inputs,
212+
bos_id=0, # Beginnning token.
213+
eos_id=1, # End of sentence token.
214+
beam_size=beam_size,
215+
max_length=max_length)
216+
217+
seqtext_printer_evaluator(input=beam_gen,
218+
id_input=data_layer(name="sent_id", size=1),
219+
dict_file=trg_dict_path,
220+
result_file=gen_trans_file)
221+
outputs(beam_gen)
222+
```
223+
224+
注意,这种生成技术只用于类似解码器的生成过程。如果你正在处理序列标记任务,请参阅 [Semantic Role Labeling Demo](../../demo/semantic_role_labeling/index.html) 了解更多详细信息。
225+
226+
完整的配置文件在`demo/seqToseq/seqToseq_net.py`

0 commit comments

Comments
 (0)