@@ -59,7 +59,7 @@ src_word_id = paddle.layer.data(
5959src_embedding = paddle.layer.embedding(
6060 input = src_word_id, size = word_vector_dim)
6161
62- # # bidierctional GRU as encoder
62+ # bidirectional GRU as encoder
6363encoded_vector = paddle.networks.bidirectional_gru(
6464 input = src_embedding,
6565 size = encoder_size,
@@ -85,7 +85,7 @@ encoded_vector = paddle.networks.bidirectional_gru(
8585
8686
8787### 无注意力机制的解码器
88- -PaddleBook中[ 机器翻译] ( https://github.com/PaddlePaddle/book/blob/develop/08.machine_translation/README.cn.md ) 的相关章节中,已介绍了带注意力机制(Attention Mechanism)的 Encoder-Decoder 结构,本例则介绍的是不带注意力机制的 Encoder-Decoder 结构。关于注意力机制,读者可进一步参考 PaddleBook 和参考文献\[ [ 3] ( #参考文献 )] 。
88+ - PaddleBook中[ 机器翻译] ( https://github.com/PaddlePaddle/book/blob/develop/08.machine_translation/README.cn.md ) 的相关章节中,已介绍了带注意力机制(Attention Mechanism)的 Encoder-Decoder 结构,本例介绍的则是不带注意力机制的 Encoder-Decoder 结构。关于注意力机制,读者可进一步参考 PaddleBook 和参考文献\[ [ 3] ( #参考文献 )] 。
8989
9090对于流行的RNN单元,PaddlePaddle 已有很好的实现均可直接调用。如果希望在 RNN 每一个时间步实现某些自定义操作,可使用 PaddlePaddle 中的` recurrent_layer_group ` 。首先,自定义单步逻辑函数,再利用函数 ` recurrent_group() ` 循环调用单步逻辑函数处理整个序列。本例中的无注意力机制的解码器便是使用` recurrent_layer_group ` 来实现,其中,单步逻辑函数` gru_decoder_without_attention() ` 相关代码如下:
9191
@@ -186,15 +186,14 @@ else:
186186
187187## 模型的训练与测试
188188
189- 在定义好网络结构后,就可以进行模型训练与测试了。根据用户运行时传递的参数是` --train ` 还是 ` --generate ` ,Python 脚本的 ` main() ` 函数分别调用函数` train() ` 和` generate() ` 来完成模型的训练与测试。
190-
191189### 模型训练
192- 模型训练阶段,函数 ` train() ` 依次完成了如下的逻辑:
190+
191+ 启动模型训练的十分简单,只需在命令行窗口中执行。模型训练阶段,` train.py ` 脚本中的 ` train() ` 函数依次完成了如下的逻辑:
193192
194193** a) 由网络定义,解析网络结构,初始化模型参数**
195194
196195``` python
197- # initialize model
196+ # define the network topolgy.
198197cost = seq2seq_net(source_dict_dim, target_dict_dim)
199198parameters = paddle.parameters.create(cost)
200199```
@@ -240,17 +239,11 @@ def event_handler(event):
240239** d) 开始训练**
241240
242241``` python
243- # start to train
242+ # start training
244243trainer.train(
245244 reader = wmt14_reader, event_handler = event_handler, num_passes = 2 )
246245```
247246
248- 启动模型训练的十分简单,只需在命令行窗口中执行
249-
250- ``` bash
251- python train.py
252- ```
253-
254247输出样例为
255248
256249``` text
@@ -265,60 +258,66 @@ Pass 0, Batch 30, Cost 153.633665, {'classification_error_evaluator': 0.86438035
265258Pass 0, Batch 40, Cost 168.170543, {'classification_error_evaluator': 0.8348183631896973}
266259```
267260
268-
269- ### 模型测试
270- 模型测试阶段,函数` generate() ` 执行了依次如下逻辑:
271-
272- ** a) 加载测试样本**
273-
274- ``` python
275- # load data samples for generation
276- gen_creator = paddle.dataset.wmt14.gen(source_dict_dim)
277- gen_data = []
278- for item in gen_creator():
279- gen_data.append((item[0 ], ))
280- ```
281-
282- ** b) 初始化模型,执行` infer() ` 为每个输入样本生成` beam search ` 的翻译结果**
283-
284- ``` python
285- beam_gen = seq2seq_net(source_dict_dim, target_dict_dim, True )
286- with gzip.open(init_models_path) as f:
287- parameters = paddle.parameters.Parameters.from_tar(f)
288- # prob is the prediction probabilities, and id is the prediction word.
289- beam_result = paddle.infer(
290- output_layer = beam_gen,
291- parameters = parameters,
292- input = gen_data,
293- field = [' prob' , ' id' ])
294- ```
295-
296- ** c) 加载源语言和目标语言词典,将` id ` 序列表示的句子转化成原语言并输出结果**
297-
298- ``` python
299- beam_result = inferer.infer(input = test_batch, field = [" prob" , " id" ])
300-
301- gen_sen_idx = np.where(beam_result[1 ] == - 1 )[0 ]
302- assert len (gen_sen_idx) == len (test_batch) * beam_size
303-
304- start_pos, end_pos = 1 , 0
305- for i, sample in enumerate (test_batch):
306- print (" " .join([
307- src_dict[w] for w in sample[0 ][1 :- 1 ]
308- ])) # skip the start and ending mark when print the source sentence
309- for j in xrange (beam_size):
310- end_pos = gen_sen_idx[i * beam_size + j]
311- print (" %.4f \t %s " % (beam_result[0 ][i][j], " " .join(
312- trg_dict[w] for w in beam_result[1 ][start_pos:end_pos])))
313- start_pos = end_pos + 2
314- print (" \n " )
315- ```
316-
317- 模型测试的执行与模型训练类似,只需执行
318-
319- ``` bash
320- python generate.py
321- ```
261+ ### 生成翻译结果
262+ 利用训练好的模型生成翻译文本也十分简单。
263+
264+ 1 . 首先请修改` generate.py ` 脚本中` main ` 中传递给` generate ` 函数的参数以指定使用哪一个保存的模型来生成,默认参数如下所示:
265+
266+ ``` python
267+ generate(
268+ source_dict_dim = 30000 ,
269+ target_dict_dim = 30000 ,
270+ batch_size = 20 ,
271+ beam_size = 3 ,
272+ model_path = " models/nmt_without_att_params_batch_00100.tar.gz" )
273+ ```
274+
275+ 2 . 在终端执行命令 `python generate.py` ,脚本中的`generate()` 执行了依次如下逻辑:
276+
277+ ** a) 加载测试样本**
278+
279+ ```python
280+ # load data samples for generation
281+ gen_creator = paddle.dataset.wmt14.gen(source_dict_dim)
282+ gen_data = []
283+ for item in gen_creator():
284+ gen_data.append((item[0 ], ))
285+ ```
286+
287+ ** b) 初始化模型,执行`infer()` 为每个输入样本生成`beam search` 的翻译结果**
288+
289+ ```python
290+ beam_gen = seq2seq_net(source_dict_dim, target_dict_dim, True )
291+ with gzip.open(init_models_path) as f:
292+ parameters = paddle.parameters.Parameters.from_tar(f)
293+ # prob is the prediction probabilities, and id is the prediction word.
294+ beam_result = paddle.infer(
295+ output_layer = beam_gen,
296+ parameters = parameters,
297+ input = gen_data,
298+ field = [' prob' , ' id' ])
299+ ```
300+
301+ ** c) 加载源语言和目标语言词典,将`id ` 序列表示的句子转化成原语言并输出结果**
302+
303+ ```python
304+ beam_result = inferer.infer(input = test_batch, field = [" prob" , " id" ])
305+
306+ gen_sen_idx = np.where(beam_result[1 ] == - 1 )[0 ]
307+ assert len (gen_sen_idx) == len (test_batch) * beam_size
308+
309+ start_pos, end_pos = 1 , 0
310+ for i, sample in enumerate (test_batch):
311+ print (" " .join([
312+ src_dict[w] for w in sample[0 ][1 :- 1 ]
313+ ])) # skip the start and ending mark when print the source sentence
314+ for j in xrange (beam_size):
315+ end_pos = gen_sen_idx[i * beam_size + j]
316+ print (" %.4f \t %s " % (beam_result[0 ][i][j], " " .join(
317+ trg_dict[w] for w in beam_result[1 ][start_pos:end_pos])))
318+ start_pos = end_pos + 2
319+ print (" \n " )
320+ ```
322321
323322设置beam search的宽度为3 ,输入为一个法文句子,则自动为测试数据生成对应的翻译结果,输出格式如下:
324323
@@ -330,9 +329,9 @@ Elles connaissent leur entreprise mieux que personne .
330329
331330```
332331- 第一行为输入的源语言句子。
333- - 第二 ~ ` beam_size + 1 ` 行是柱搜索生成的 ` beam_size ` 条翻译结果
334- - 一行之内以 “\t”分隔为两列,第一列是句子的log 概率,第二列是翻译结果的文本。
335- - ` <s> ` 表示句子的开始,` <e> ` 表示一个句子的结束,如果出现了在词典中未包含的词,则用` <unk> ` 替代。
332+ - 第二 ~ beam_size + 1 行是柱搜索生成的 ` beam_size ` 条翻译结果
333+ - 相同行的输出以 “\t”分隔为两列,第一列是句子的log 概率,第二列是翻译结果的文本。
334+ - 符号 ` <s> ` 表示句子的开始,符号 ` <e> ` 表示一个句子的结束,如果出现了在词典中未包含的词,则用` <unk> ` 替代。
336335
337336至此,我们在 PaddlePaddle 上实现了一个初步的机器翻译模型。我们可以看到,PaddlePaddle 提供了灵活丰富的API供大家选择和使用,使得我们能够很方便完成各种复杂网络的配置。机器翻译本身也是个快速发展的领域,各种新方法新思想在不断涌现。在学习完本例后,读者若有兴趣和余力,可基于 PaddlePaddle 平台实现更为复杂、性能更优的机器翻译模型。
338337
0 commit comments