From 55b96287aeb08305b90d3351c602c207d9c38290 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 23 Feb 2017 22:45:51 +0800 Subject: [PATCH 001/153] support rnn --- python/paddle/v2/layer.py | 87 +++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 507725ee4ff71..bebe7c6690ca7 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -73,6 +73,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default +import activation import data_type __all__ = [ @@ -97,10 +98,11 @@ def __real_func__(): class Layer(object): - def __init__(self, name, parent_layers): + def __init__(self, name, parent_layers, step_input=None): assert isinstance(parent_layers, dict) assert isinstance(name, basestring) self.name = name + self.step_input = step_input self.__parent_layers__ = parent_layers def to_proto(self, context): @@ -116,8 +118,14 @@ def to_proto(self, context): else: v1_layer = map(lambda x: x.to_proto(context=context), self.__parent_layers__[layer_name]) + if layer_name == "input" and self.step_input is not None: + v1_layer.insert(0, self.step_input) kwargs[layer_name] = v1_layer + # memory may have the same name with some layer + if isinstance(self, MemoryV2): + return self.to_proto_impl(**kwargs) + if self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) return context[self.name] @@ -133,7 +141,7 @@ def __convert_to_v2__(method_name, name_prefix, parent_names): wrapper = None class V2LayerImpl(Layer): - def __init__(self, name=None, **kwargs): + def __init__(self, name=None, step_input=None, **kwargs): parent_layers = dict() other_kwargs = dict() for pname in parent_names: @@ -143,7 +151,7 @@ def __init__(self, name=None, **kwargs): if key not in parent_names: other_kwargs[key] = kwargs[key] - super(V2LayerImpl, self).__init__(name, parent_layers) + super(V2LayerImpl, self).__init__(name, parent_layers, step_input) self.__other_kwargs__ = other_kwargs if wrapper is not None: @@ -186,6 +194,22 @@ def to_proto_impl(self, **kwargs): return getattr(conf_helps, self.__method_name__)(name=self.name, **args) +class MemoryV2(Layer): + def __init__(self, name, size, **kwargs): + self.name = name + self.size = size + self.__kwargs__ = kwargs + super(MemoryV2, self).__init__(name=name, parent_layers=dict()) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__kwargs__: + args[each] = self.__kwargs__[each] + return conf_helps.memory(name=self.name, size=self.size, **args) + + data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( @@ -198,6 +222,13 @@ def to_proto_impl(self, **kwargs): 'cross_entropy', name_prefix='cross_entropy', parent_names=['input', 'label']) +embedding = __convert_to_v2__( + 'embedding_layer', name_prefix='embedding', parent_names=['input']) +last_seq = __convert_to_v2__( + 'last_seq', name_prefix='last_seq', parent_names=['input']) +recurrent_group = __convert_to_v2__( + 'recurrent_group', name_prefix='recurrent_layer', parent_names=['input']) +memory = MemoryV2 if __name__ == '__main__': pixel = data(name='pixel', type=data_type.dense_vector(784)) @@ -208,8 +239,48 @@ def to_proto_impl(self, **kwargs): cost1 = classification_cost(input=inference, label=label) cost2 = cross_entropy_cost(input=inference, label=label) - print parse_network(cost1) - print parse_network(cost2) - print parse_network(cost1, cost2) - print parse_network(cost2) - print parse_network(inference, maxid) + mem = memory(name="rnn_state", size=10) + + # print parse_network(cost1) + # print parse_network(cost2) + # print parse_network(cost1, cost2) + # print parse_network(cost2) + # print parse_network(inference, maxid) + + dict_dim = 10 + word_dim = 8 + hidden_dim = 8 + label_dim = 3 + + def step(y): + mem = conf_helps.memory(name="rnn_state", size=hidden_dim) + out = conf_helps.fc_layer( + input=[y, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + def test(): + data1 = conf_helps.data_layer(name="word", size=dict_dim) + embd = conf_helps.embedding_layer(input=data1, size=word_dim) + conf_helps.recurrent_group(name="rnn", step=step, input=embd) + + # print __parse__(test) + + # yyyyyyyy + def new_step(y): + mem = memory(name="rnn_state", size=hidden_dim) + out = fc(input=[mem], + step_input=y, + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out.to_proto(dict()) + + data1 = data(name="word", type=data_type.integer_value(dict_dim)) + embd = embedding(input=data1, size=word_dim) + aaa = recurrent_group(name="rnn", step=new_step, input=embd) + print parse_network(aaa) From 92f52e3bb7a1a203a01d3641887c6bdfd03dce67 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 13:46:59 +0800 Subject: [PATCH 002/153] add rnn test --- demo/mnist/api_train_v2.py | 3 ++ python/paddle/v2/layer.py | 43 +---------------- python/paddle/v2/tests/layer_test.py | 72 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 41 deletions(-) create mode 100644 python/paddle/v2/tests/layer_test.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6fc01ce58be57..5e66b7399ad52 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -3,6 +3,9 @@ import mnist_util +import pudb +pudb.set_trace() + def train_reader(): train_file = './data/raw_data/train' diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 44ebebcaeab53..e1952ce747d10 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -73,16 +73,15 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import activation -import data_type import activation import attr +import data_type __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', 'multi_binary_label_cross_entropy_cost', 'rank_cost', 'lambda_cost', - 'sum_cost', 'huber_cost' + 'sum_cost', 'huber_cost', 'memory', 'embedding', 'recurrent_group' ] @@ -294,41 +293,3 @@ def to_proto_impl(self, **kwargs): print parse_network(cost5, cost6) print parse_network(cost7, cost8, cost9, cost10, cost11) print parse_network(inference, maxid) - - dict_dim = 10 - word_dim = 8 - hidden_dim = 8 - label_dim = 3 - - def step(y): - mem = conf_helps.memory(name="rnn_state", size=hidden_dim) - out = conf_helps.fc_layer( - input=[y, mem], - size=hidden_dim, - act=activation.Tanh(), - bias_attr=True, - name="rnn_state") - return out - - def test(): - data1 = conf_helps.data_layer(name="word", size=dict_dim) - embd = conf_helps.embedding_layer(input=data1, size=word_dim) - conf_helps.recurrent_group(name="rnn", step=step, input=embd) - - # print __parse__(test) - - # yyyyyyyy - def new_step(y): - mem = memory(name="rnn_state", size=hidden_dim) - out = fc(input=[mem], - step_input=y, - size=hidden_dim, - act=activation.Tanh(), - bias_attr=True, - name="rnn_state") - return out.to_proto(dict()) - - data1 = data(name="word", type=data_type.integer_value(dict_dim)) - embd = embedding(input=data1, size=word_dim) - aaa = recurrent_group(name="rnn", step=new_step, input=embd) - print parse_network(aaa) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/layer_test.py new file mode 100644 index 0000000000000..87e601a60abc5 --- /dev/null +++ b/python/paddle/v2/tests/layer_test.py @@ -0,0 +1,72 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import difflib +import unittest + +import paddle.trainer_config_helpers as conf_helps +import paddle.v2.activation as activation +import paddle.v2.data_type as data_type +import paddle.v2.layer as layer +from paddle.trainer_config_helpers.config_parser_utils import \ + parse_network_config as parse_network + + +class RNNTest(unittest.TestCase): + def test_simple_rnn(self): + dict_dim = 10 + word_dim = 8 + hidden_dim = 8 + + def test_old_rnn(): + def step(y): + mem = conf_helps.memory(name="rnn_state", size=hidden_dim) + out = conf_helps.fc_layer( + input=[y, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + def test(): + data1 = conf_helps.data_layer(name="word", size=dict_dim) + embd = conf_helps.embedding_layer(input=data1, size=word_dim) + conf_helps.recurrent_group(name="rnn", step=step, input=embd) + + return str(parse_network(test)) + + def test_new_rnn(): + def new_step(y): + mem = layer.memory(name="rnn_state", size=hidden_dim) + out = layer.fc(input=[mem], + step_input=y, + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out.to_proto(dict()) + + data1 = layer.data( + name="word", type=data_type.integer_value(dict_dim)) + embd = layer.embedding(input=data1, size=word_dim) + aaa = layer.recurrent_group(name="rnn", step=new_step, input=embd) + return str(layer.parse_network(aaa)) + + diff = difflib.unified_diff(test_old_rnn().splitlines(1), + test_new_rnn().splitlines(1)) + print ''.join(diff) + + +if __name__ == '__main__': + unittest.main() From 6b80c2b4f9a626efa911f715dcb45bee99d80729 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 15:29:11 +0800 Subject: [PATCH 003/153] add cost test --- python/paddle/v2/layer.py | 2 -- python/paddle/v2/tests/layer_test.py | 35 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index e1952ce747d10..f333c0af964bf 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -281,8 +281,6 @@ def to_proto_impl(self, **kwargs): cost10 = sum_cost(input=inference) cost11 = huber_cost(input=score, label=label) - mem = memory(name="rnn_state", size=10) - # print parse_network(cost1) # print parse_network(cost2) # print parse_network(cost1, cost2) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/layer_test.py index 87e601a60abc5..6c4b458914701 100644 --- a/python/paddle/v2/tests/layer_test.py +++ b/python/paddle/v2/tests/layer_test.py @@ -18,10 +18,45 @@ import paddle.v2.activation as activation import paddle.v2.data_type as data_type import paddle.v2.layer as layer +import paddle.v2.attr as attr from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as parse_network +class CostLyaerTest(unittest.TestCase): + def test_cost_layer(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + weight = layer.data(name='weight', type=data_type.dense_vector(10)) + score = layer.data(name='score', type=data_type.dense_vector(1)) + hidden = layer.fc(input=pixel, + size=100, + act=activation.Sigmoid(), + param_attr=attr.Param(name='hidden')) + inference = layer.fc(input=hidden, size=10, act=activation.Softmax()) + + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.classification_cost( + input=inference, label=label, weight=weight) + cost3 = layer.cross_entropy_cost(input=inference, label=label) + cost4 = layer.cross_entropy_with_selfnorm_cost( + input=inference, label=label) + cost5 = layer.regression_cost(input=inference, label=label) + cost6 = layer.regression_cost( + input=inference, label=label, weight=weight) + cost7 = layer.multi_binary_label_cross_entropy_cost( + input=inference, label=label) + cost8 = layer.rank_cost(left=score, right=score, label=score) + cost9 = layer.lambda_cost(input=inference, score=score) + cost10 = layer.sum_cost(input=inference) + cost11 = layer.huber_cost(input=score, label=label) + + print layer.parse_network(cost1, cost2) + print layer.parse_network(cost3, cost4) + print layer.parse_network(cost5, cost6) + print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + + class RNNTest(unittest.TestCase): def test_simple_rnn(self): dict_dim = 10 From db92e3c884a586d0f28dcc7c7e3be99c1e6203f6 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:04:59 +0800 Subject: [PATCH 004/153] refine code --- python/paddle/v2/layer.py | 35 ---------------------------- python/paddle/v2/tests/layer_test.py | 7 +++--- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index f333c0af964bf..5ecc96c685650 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -256,38 +256,3 @@ def to_proto_impl(self, **kwargs): 'sum_cost', name_prefix='sum_cost', parent_names=['input']) huber_cost = __convert_to_v2__( 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) - -if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(784)) - label = data(name='label', type=data_type.integer_value(10)) - weight = data(name='weight', type=data_type.dense_vector(10)) - score = data(name='score', type=data_type.dense_vector(1)) - - hidden = fc(input=pixel, - size=100, - act=activation.Sigmoid(), - param_attr=attr.Param(name='hidden')) - inference = fc(input=hidden, size=10, act=activation.Softmax()) - maxid = max_id(input=inference) - cost1 = classification_cost(input=inference, label=label) - cost2 = classification_cost(input=inference, label=label, weight=weight) - cost3 = cross_entropy_cost(input=inference, label=label) - cost4 = cross_entropy_with_selfnorm_cost(input=inference, label=label) - cost5 = regression_cost(input=inference, label=label) - cost6 = regression_cost(input=inference, label=label, weight=weight) - cost7 = multi_binary_label_cross_entropy_cost(input=inference, label=label) - cost8 = rank_cost(left=score, right=score, label=score) - cost9 = lambda_cost(input=inference, score=score) - cost10 = sum_cost(input=inference) - cost11 = huber_cost(input=score, label=label) - - # print parse_network(cost1) - # print parse_network(cost2) - # print parse_network(cost1, cost2) - # print parse_network(cost2) - # print parse_network(inference, maxid) - print parse_network(cost1, cost2) - print parse_network(cost3, cost4) - print parse_network(cost5, cost6) - print parse_network(cost7, cost8, cost9, cost10, cost11) - print parse_network(inference, maxid) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/layer_test.py index 6c4b458914701..2958cbd9ebd0c 100644 --- a/python/paddle/v2/tests/layer_test.py +++ b/python/paddle/v2/tests/layer_test.py @@ -16,9 +16,9 @@ import paddle.trainer_config_helpers as conf_helps import paddle.v2.activation as activation +import paddle.v2.attr as attr import paddle.v2.data_type as data_type import paddle.v2.layer as layer -import paddle.v2.attr as attr from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as parse_network @@ -95,8 +95,9 @@ def new_step(y): data1 = layer.data( name="word", type=data_type.integer_value(dict_dim)) embd = layer.embedding(input=data1, size=word_dim) - aaa = layer.recurrent_group(name="rnn", step=new_step, input=embd) - return str(layer.parse_network(aaa)) + rnn_layer = layer.recurrent_group( + name="rnn", step=new_step, input=embd) + return str(layer.parse_network(rnn_layer)) diff = difflib.unified_diff(test_old_rnn().splitlines(1), test_new_rnn().splitlines(1)) From e4327a7cd9408839900c0f82b4aedf2ce6672cbd Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:11:02 +0800 Subject: [PATCH 005/153] add CMakeLists.txt --- python/paddle/v2/tests/CMakeLists.txt | 4 ++++ python/paddle/v2/tests/layer_test.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/tests/CMakeLists.txt diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt new file mode 100644 index 0000000000000..dc5efdab6a997 --- /dev/null +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_test(NAME layer_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/layer_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/layer_test.py b/python/paddle/v2/tests/layer_test.py index 2958cbd9ebd0c..83c8c26d6b654 100644 --- a/python/paddle/v2/tests/layer_test.py +++ b/python/paddle/v2/tests/layer_test.py @@ -23,7 +23,7 @@ parse_network_config as parse_network -class CostLyaerTest(unittest.TestCase): +class CostLayerTest(unittest.TestCase): def test_cost_layer(self): pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) label = layer.data(name='label', type=data_type.integer_value(10)) From f13f1f1ce5cfe428c272e90f85dc9a9c1ed55f6b Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 17:37:38 +0800 Subject: [PATCH 006/153] use test_layer instead of layer_test --- python/paddle/v2/tests/test_layer.py | 57 +++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index b600e8cf76512..73d769a358244 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -51,12 +51,57 @@ def test_cost_layer(self): cost10 = layer.sum_cost(input=inference) cost11 = layer.huber_cost(input=score, label=label) - print dir(layer) - layer.parse_network(cost1, cost2) - print dir(layer) - #print layer.parse_network(cost3, cost4) - #print layer.parse_network(cost5, cost6) - #print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + print layer.parse_network(cost1, cost2) + print layer.parse_network(cost3, cost4) + print layer.parse_network(cost5, cost6) + print layer.parse_network(cost7, cost8, cost9, cost10, cost11) + + +class RNNTest(unittest.TestCase): + def test_simple_rnn(self): + dict_dim = 10 + word_dim = 8 + hidden_dim = 8 + + def test_old_rnn(): + def step(y): + mem = conf_helps.memory(name="rnn_state", size=hidden_dim) + out = conf_helps.fc_layer( + input=[y, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + def test(): + data1 = conf_helps.data_layer(name="word", size=dict_dim) + embd = conf_helps.embedding_layer(input=data1, size=word_dim) + conf_helps.recurrent_group(name="rnn", step=step, input=embd) + + return str(parse_network(test)) + + def test_new_rnn(): + def new_step(y): + mem = layer.memory(name="rnn_state", size=hidden_dim) + out = layer.fc(input=[mem], + step_input=y, + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out.to_proto(dict()) + + data1 = layer.data( + name="word", type=data_type.integer_value(dict_dim)) + embd = layer.embedding(input=data1, size=word_dim) + rnn_layer = layer.recurrent_group( + name="rnn", step=new_step, input=embd) + return str(layer.parse_network(rnn_layer)) + + diff = difflib.unified_diff(test_old_rnn().splitlines(1), + test_new_rnn().splitlines(1)) + print ''.join(diff) if __name__ == '__main__': From ad4ab5ac811d90dd2bbb661ad34ba5ee3aa510a1 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Sun, 26 Feb 2017 16:29:02 +0800 Subject: [PATCH 007/153] remove step_input in recurrent_group step_input --- .../paddle/trainer_config_helpers/layers.py | 8 ++- python/paddle/v2/layer.py | 61 +++++++++++++++---- python/paddle/v2/tests/test_layer.py | 13 ++-- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 00aef80691fba..4e200517fc4bc 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -3042,7 +3042,8 @@ def recurrent_group(step, reverse=False, name=None, targetInlink=None, - is_generating=False): + is_generating=False, + in_args_converter=None): """ Recurrent layer group is an extremely flexible recurrent unit in PaddlePaddle. As long as the user defines the calculation done within a @@ -3185,7 +3186,10 @@ def map_in_links(x): assert (is_generating != has_LayerOutput) - layer_outs = step(*in_args) + if in_args_converter is None: + layer_outs = step(*in_args) + else: + layer_outs = step(*in_args_converter(*in_args)).to_proto(dict()) if isinstance(layer_outs, LayerOutput): layer_outs = [layer_outs] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 5ecc96c685650..44c7661b2463f 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -73,8 +73,6 @@ class for each layer creation function in paddle.trainer_config_helpers.layers. parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import activation -import attr import data_type __all__ = [ @@ -101,11 +99,10 @@ def __real_func__(): class Layer(object): - def __init__(self, name, parent_layers, step_input=None): + def __init__(self, name, parent_layers): assert isinstance(parent_layers, dict) assert isinstance(name, basestring) self.name = name - self.step_input = step_input self.__parent_layers__ = parent_layers def to_proto(self, context): @@ -121,12 +118,13 @@ def to_proto(self, context): else: v1_layer = map(lambda x: x.to_proto(context=context), self.__parent_layers__[layer_name]) - if layer_name == "input" and self.step_input is not None: - v1_layer.insert(0, self.step_input) kwargs[layer_name] = v1_layer + if self.name is None: + return self.to_proto_impl(**kwargs) + # memory may have the same name with some layer - if isinstance(self, MemoryV2): + if isinstance(self, MemoryV2) or isinstance(self, LayerOutputV2): return self.to_proto_impl(**kwargs) if self.name not in context: @@ -144,7 +142,7 @@ def __convert_to_v2__(method_name, name_prefix, parent_names): wrapper = None class V2LayerImpl(Layer): - def __init__(self, name=None, step_input=None, **kwargs): + def __init__(self, name=None, **kwargs): parent_layers = dict() other_kwargs = dict() for pname in parent_names: @@ -155,7 +153,7 @@ def __init__(self, name=None, step_input=None, **kwargs): if key not in parent_names: other_kwargs[key] = kwargs[key] - super(V2LayerImpl, self).__init__(name, parent_layers, step_input) + super(V2LayerImpl, self).__init__(name, parent_layers) self.__other_kwargs__ = other_kwargs if wrapper is not None: @@ -214,6 +212,48 @@ def to_proto_impl(self, **kwargs): return conf_helps.memory(name=self.name, size=self.size, **args) +class LayerOutputV2(Layer): + def __init__(self, layer_output): + assert isinstance(layer_output, conf_helps.LayerOutput) + self.layer_output = layer_output + super(LayerOutputV2, self).__init__( + name=layer_output.name, parent_layers=dict()) + + def to_proto_impl(self): + return self.layer_output + + +class RecurrentGroupV2(Layer): + def __init__(self, name, **kwargs): + self.__parent_names__ = ['input'] + other_kwargs = dict() + parent_layers = dict() + for pname in self.__parent_names__: + if kwargs.has_key(pname): + parent_layers[pname] = kwargs[pname] + for key in kwargs.keys(): + if key not in self.__parent_names__: + other_kwargs[key] = kwargs[key] + self.__kwargs__ = other_kwargs + + super(RecurrentGroupV2, self).__init__( + name=name, parent_layers=parent_layers) + + def to_proto_impl(self, **kwargs): + def in_args_converter(in_args): + if not isinstance(in_args, collections.Sequence): + in_args = [in_args] + return [LayerOutputV2(input) for input in in_args] + + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__kwargs__: + args[each] = self.__kwargs__[each] + return conf_helps.recurrent_group( + name=self.name, in_args_converter=in_args_converter, **args) + + data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( @@ -234,8 +274,7 @@ def to_proto_impl(self, **kwargs): 'embedding_layer', name_prefix='embedding', parent_names=['input']) last_seq = __convert_to_v2__( 'last_seq', name_prefix='last_seq', parent_names=['input']) -recurrent_group = __convert_to_v2__( - 'recurrent_group', name_prefix='recurrent_layer', parent_names=['input']) +recurrent_group = RecurrentGroupV2 memory = MemoryV2 cross_entropy_with_selfnorm_cost = __convert_to_v2__( diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 73d769a358244..04c0fc7cb0bf1 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -63,7 +63,7 @@ def test_simple_rnn(self): word_dim = 8 hidden_dim = 8 - def test_old_rnn(): + def parse_old_rnn(): def step(y): mem = conf_helps.memory(name="rnn_state", size=hidden_dim) out = conf_helps.fc_layer( @@ -81,16 +81,15 @@ def test(): return str(parse_network(test)) - def test_new_rnn(): + def parse_new_rnn(): def new_step(y): mem = layer.memory(name="rnn_state", size=hidden_dim) - out = layer.fc(input=[mem], - step_input=y, + out = layer.fc(input=[y, mem], size=hidden_dim, act=activation.Tanh(), bias_attr=True, name="rnn_state") - return out.to_proto(dict()) + return out data1 = layer.data( name="word", type=data_type.integer_value(dict_dim)) @@ -99,8 +98,8 @@ def new_step(y): name="rnn", step=new_step, input=embd) return str(layer.parse_network(rnn_layer)) - diff = difflib.unified_diff(test_old_rnn().splitlines(1), - test_new_rnn().splitlines(1)) + diff = difflib.unified_diff(parse_old_rnn().splitlines(1), + parse_new_rnn().splitlines(1)) print ''.join(diff) From 632ad5c9e25c906b0189be308ecf22c2409abb2c Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 27 Feb 2017 19:59:38 +0800 Subject: [PATCH 008/153] support sequence_rnn_multi_input --- demo/mnist/api_train_v2.py | 3 - python/paddle/trainer/config_parser.py | 6 +- python/paddle/v2/layer.py | 30 ++++- python/paddle/v2/tests/CMakeLists.txt | 6 +- python/paddle/v2/tests/test_layer.py | 50 -------- python/paddle/v2/tests/test_rnn_layer.py | 143 +++++++++++++++++++++++ 6 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 python/paddle/v2/tests/test_rnn_layer.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 5e66b7399ad52..6fc01ce58be57 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -3,9 +3,6 @@ import mnist_util -import pudb -pudb.set_trace() - def train_reader(): train_file = './data/raw_data/train' diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py index da937152ee0ce..487d4dfd5b1b8 100644 --- a/python/paddle/trainer/config_parser.py +++ b/python/paddle/trainer/config_parser.py @@ -3474,6 +3474,8 @@ def update_g_config(): for name in g_config.model_config.output_layer_names: assert name in g_layer_map, \ 'input name "%s" does not correspond to a layer name' % name + for hook in _parse_config_hooks: + hook() return g_config @@ -3485,8 +3487,8 @@ def parse_config(trainer_config, config_arg_str): passed to config script as a dictionary CONFIG_ARGS ''' init_config_environment() - for hook in _parse_config_hooks: - hook() + # for hook in _parse_config_hooks: + # hook() config_args = {} diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 44c7661b2463f..5328070456ef1 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -124,11 +124,13 @@ def to_proto(self, context): return self.to_proto_impl(**kwargs) # memory may have the same name with some layer - if isinstance(self, MemoryV2) or isinstance(self, LayerOutputV2): + if isinstance(self, MemoryV2): return self.to_proto_impl(**kwargs) + # store v1 API's layer_output in context with the key of it's name. if self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) + return context[self.name] def to_proto_impl(self, **kwargs): @@ -200,8 +202,19 @@ class MemoryV2(Layer): def __init__(self, name, size, **kwargs): self.name = name self.size = size - self.__kwargs__ = kwargs - super(MemoryV2, self).__init__(name=name, parent_layers=dict()) + + parent_names = ['boot_layer'] + parent_layers = dict() + other_kwargs = dict() + for pname in parent_names: + if kwargs.has_key(pname): + parent_layers[pname] = kwargs[pname] + + for key in kwargs.keys(): + if key not in parent_names: + other_kwargs[key] = kwargs[key] + super(MemoryV2, self).__init__(name=name, parent_layers=parent_layers) + self.__kwargs__ = other_kwargs def to_proto_impl(self, **kwargs): args = dict() @@ -209,10 +222,16 @@ def to_proto_impl(self, **kwargs): args[each] = kwargs[each] for each in self.__kwargs__: args[each] = self.__kwargs__[each] + return conf_helps.memory(name=self.name, size=self.size, **args) class LayerOutputV2(Layer): + """ + LayerOutputV2 is used to store the result of LayerOutput in v1 api. + It will not store it's parents because layer_output has been parsed already. + """ + def __init__(self, layer_output): assert isinstance(layer_output, conf_helps.LayerOutput) self.layer_output = layer_output @@ -239,8 +258,11 @@ def __init__(self, name, **kwargs): super(RecurrentGroupV2, self).__init__( name=name, parent_layers=parent_layers) + wrapper = wrap_name_default(name_prefix='recurrent_group') + __init__ = wrapper(__init__) + def to_proto_impl(self, **kwargs): - def in_args_converter(in_args): + def in_args_converter(*in_args): if not isinstance(in_args, collections.Sequence): in_args = [in_args] return [LayerOutputV2(input) for input in in_args] diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index ceb71c1454b2b..bc0f24792796b 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -1,3 +1,7 @@ add_test(NAME test_v2_layer COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_layer.py + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_layer.py) + +add_test(NAME test_v2_rnn_layer + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_rnn_layer.py) diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 04c0fc7cb0bf1..41d9683464d29 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -11,16 +11,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import difflib import unittest -import paddle.trainer_config_helpers as conf_helps import paddle.v2.activation as activation import paddle.v2.attr as attr import paddle.v2.data_type as data_type import paddle.v2.layer as layer -from paddle.trainer_config_helpers.config_parser_utils import \ - parse_network_config as parse_network pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -57,51 +53,5 @@ def test_cost_layer(self): print layer.parse_network(cost7, cost8, cost9, cost10, cost11) -class RNNTest(unittest.TestCase): - def test_simple_rnn(self): - dict_dim = 10 - word_dim = 8 - hidden_dim = 8 - - def parse_old_rnn(): - def step(y): - mem = conf_helps.memory(name="rnn_state", size=hidden_dim) - out = conf_helps.fc_layer( - input=[y, mem], - size=hidden_dim, - act=activation.Tanh(), - bias_attr=True, - name="rnn_state") - return out - - def test(): - data1 = conf_helps.data_layer(name="word", size=dict_dim) - embd = conf_helps.embedding_layer(input=data1, size=word_dim) - conf_helps.recurrent_group(name="rnn", step=step, input=embd) - - return str(parse_network(test)) - - def parse_new_rnn(): - def new_step(y): - mem = layer.memory(name="rnn_state", size=hidden_dim) - out = layer.fc(input=[y, mem], - size=hidden_dim, - act=activation.Tanh(), - bias_attr=True, - name="rnn_state") - return out - - data1 = layer.data( - name="word", type=data_type.integer_value(dict_dim)) - embd = layer.embedding(input=data1, size=word_dim) - rnn_layer = layer.recurrent_group( - name="rnn", step=new_step, input=embd) - return str(layer.parse_network(rnn_layer)) - - diff = difflib.unified_diff(parse_old_rnn().splitlines(1), - parse_new_rnn().splitlines(1)) - print ''.join(diff) - - if __name__ == '__main__': unittest.main() diff --git a/python/paddle/v2/tests/test_rnn_layer.py b/python/paddle/v2/tests/test_rnn_layer.py new file mode 100644 index 0000000000000..bf2c4db61aa50 --- /dev/null +++ b/python/paddle/v2/tests/test_rnn_layer.py @@ -0,0 +1,143 @@ +# Copyright PaddlePaddle contributors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import difflib +import unittest + +import paddle.trainer_config_helpers as conf_helps +import paddle.v2.activation as activation +import paddle.v2.data_type as data_type +import paddle.v2.layer as layer +from paddle.trainer_config_helpers.config_parser_utils import \ + parse_network_config as parse_network + + +class RNNTest(unittest.TestCase): + def test_simple_rnn(self): + dict_dim = 10 + word_dim = 8 + hidden_dim = 8 + + def parse_old_rnn(): + def step(y): + mem = conf_helps.memory(name="rnn_state", size=hidden_dim) + out = conf_helps.fc_layer( + input=[y, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + def test(): + data = conf_helps.data_layer(name="word", size=dict_dim) + embd = conf_helps.embedding_layer(input=data, size=word_dim) + conf_helps.recurrent_group(name="rnn", step=step, input=embd) + + return str(parse_network(test)) + + def parse_new_rnn(): + def new_step(y): + mem = layer.memory(name="rnn_state", size=hidden_dim) + out = layer.fc(input=[y, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + data = layer.data( + name="word", type=data_type.integer_value(dict_dim)) + embd = layer.embedding(input=data, size=word_dim) + rnn_layer = layer.recurrent_group( + name="rnn", step=new_step, input=embd) + return str(layer.parse_network(rnn_layer)) + + diff = difflib.unified_diff(parse_old_rnn().splitlines(1), + parse_new_rnn().splitlines(1)) + print ''.join(diff) + + def test_sequence_rnn_multi_input(self): + dict_dim = 10 + word_dim = 8 + hidden_dim = 8 + label_dim = 3 + + def parse_old_rnn(): + def step(y, wid): + z = conf_helps.embedding_layer(input=wid, size=word_dim) + mem = conf_helps.memory(name="rnn_state", size=hidden_dim) + out = conf_helps.fc_layer( + input=[y, z, mem], + size=hidden_dim, + act=conf_helps.TanhActivation(), + bias_attr=True, + name="rnn_state") + return out + + def test(): + data = conf_helps.data_layer(name="word", size=dict_dim) + label = conf_helps.data_layer(name="label", size=label_dim) + emb = conf_helps.embedding_layer(input=data, size=word_dim) + out = conf_helps.recurrent_group( + name="rnn", step=step, input=[emb, data]) + + rep = conf_helps.last_seq(input=out) + prob = conf_helps.fc_layer( + size=label_dim, + input=rep, + act=conf_helps.SoftmaxActivation(), + bias_attr=True) + + conf_helps.outputs( + conf_helps.classification_cost( + input=prob, label=label)) + + return str(parse_network(test)) + + def parse_new_rnn(): + def step(y, wid): + z = layer.embedding(input=wid, size=word_dim) + mem = layer.memory(name="rnn_state", size=hidden_dim) + out = layer.fc(input=[y, z, mem], + size=hidden_dim, + act=activation.Tanh(), + bias_attr=True, + name="rnn_state") + return out + + data = layer.data( + name="word", type=data_type.dense_vector(dict_dim)) + label = layer.data( + name="label", type=data_type.dense_vector(label_dim)) + emb = layer.embedding(input=data, size=word_dim) + out = layer.recurrent_group( + name="rnn", step=step, input=[emb, data]) + + rep = layer.last_seq(input=out) + prob = layer.fc(size=label_dim, + input=rep, + act=activation.Softmax(), + bias_attr=True) + + cost = layer.classification_cost(input=prob, label=label) + + return str(layer.parse_network(cost)) + + diff = difflib.unified_diff(parse_old_rnn().splitlines(1), + parse_new_rnn().splitlines(1)) + print ''.join(diff) + + +if __name__ == '__main__': + unittest.main() From 876d597495015ba416639af7426258d32587986e Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 27 Feb 2017 20:41:00 +0800 Subject: [PATCH 009/153] memory have same name with some layer --- python/paddle/v2/layer.py | 2 ++ python/paddle/v2/tests/CMakeLists.txt | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 6dea3afbcf407..dbd802bee8270 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -139,6 +139,8 @@ def to_proto(self, context): if self.name is None: return self.to_proto_impl(**kwargs) + elif isinstance(self, MemoryV2): + return self.to_proto_impl(**kwargs) elif self.name not in context: context[self.name] = self.to_proto_impl(**kwargs) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index bc0f24792796b..b2f43c42de8eb 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -1,7 +1,11 @@ add_test(NAME test_v2_layer COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_layer.py) + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_layer.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) add_test(NAME test_v2_rnn_layer COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_rnn_layer.py) + +add_test(NAME test_v2_api + COMMAND bash ${PROJ_ROOT}/python/paddle/v2/tests/run_tests.sh ${PYTHON_EXECUTABLE}) From 32b168c78ff807ca178bfb016b3d178178b66202 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 12:35:22 +0800 Subject: [PATCH 010/153] Refine code --- demo/recommendation/api_train_v2.py | 12 ++++++++++++ python/paddle/v2/dataset/__init__.py | 4 +++- python/paddle/v2/dataset/movielens.py | 10 ++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 demo/recommendation/api_train_v2.py diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py new file mode 100644 index 0000000000000..64dff9ae43285 --- /dev/null +++ b/demo/recommendation/api_train_v2.py @@ -0,0 +1,12 @@ +import paddle.v2 as paddle + + +def main(): + movie_title_dict = paddle.dataset.movielens.get_movie_title_dict() + title_word_count = len(movie_title_dict) + + paddle.layer.mixed + + +if __name__ == '__main__': + main() diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py index 9647e9850332b..a947edd2cce64 100644 --- a/python/paddle/v2/dataset/__init__.py +++ b/python/paddle/v2/dataset/__init__.py @@ -1,3 +1,5 @@ import mnist +import cifar +import movielens -__all__ = ['mnist'] +__all__ = ['mnist', 'cifar', 'movielens'] diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py index dcffcff2f58c6..b66448fafe421 100644 --- a/python/paddle/v2/dataset/movielens.py +++ b/python/paddle/v2/dataset/movielens.py @@ -4,7 +4,7 @@ import random import functools -__all__ = ['train_creator', 'test_creator'] +__all__ = ['train_creator', 'test_creator', 'get_movie_title_dict'] class MovieInfo(object): @@ -40,7 +40,8 @@ def value(self): def __initialize_meta_info__(): fn = download( url='http://files.grouplens.org/datasets/movielens/ml-1m.zip', - md5='c4d9eecfca2ab87c1945afe126590906') + module_name='movielens', + md5sum='c4d9eecfca2ab87c1945afe126590906') global MOVIE_INFO if MOVIE_INFO is None: pattern = re.compile(r'^(.*)\((\d+)\)$') @@ -107,6 +108,11 @@ def __reader_creator__(**kwargs): test_creator = functools.partial(__reader_creator__, is_test=True) +def get_movie_title_dict(): + __initialize_meta_info__() + return MOVIE_TITLE_DICT + + def unittest(): for train_count, _ in enumerate(train_creator()()): pass From 9ccc94f4a4d5bd87793730be1a73888c09a55cb3 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Mon, 27 Feb 2017 19:56:33 +0800 Subject: [PATCH 011/153] srl api training --- demo/semantic_role_labeling/api_train_v2.py | 112 ++++++++++++++++++++ demo/semantic_role_labeling/model_v2.py | 103 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 demo/semantic_role_labeling/api_train_v2.py create mode 100644 demo/semantic_role_labeling/model_v2.py diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py new file mode 100644 index 0000000000000..33b966cca579f --- /dev/null +++ b/demo/semantic_role_labeling/api_train_v2.py @@ -0,0 +1,112 @@ +import numpy +import paddle.v2 as paddle +from paddle.trainer_config_helpers.atts import ParamAttr + +from mode_v2 import db_lstm + +word_dict_file = './data/wordDict.txt' +label_dict_file = './data/targetDict.txt' +predicate_file = './data/verbDict.txt' + +word_dict = dict() +label_dict = dict() +predicate_dict = dict() + +with open(word_dict_file, 'r') as f_word, \ + open(label_dict_file, 'r') as f_label, \ + open(predicate_file, 'r') as f_pre: + for i, line in enumerate(f_word): + w = line.strip() + word_dict[w] = i + + for i, line in enumerate(f_label): + w = line.strip() + label_dict[w] = i + + for i, line in enumerate(f_pre): + w = line.strip() + predicate_dict[w] = i + +word_dict_len = len(word_dict) +label_dict_len = len(label_dict) +pred_len = len(predicate_dict) + + +def train_reader(file_name="data/feature"): + def reader(): + with open(file_name, 'r') as fdata: + for line in fdata: + sentence, predicate, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2, mark, label = \ + line.strip().split('\t') + + words = sentence.split() + sen_len = len(words) + word_slot = [word_dict.get(w, UNK_IDX) for w in words] + + predicate_slot = [predicate_dict.get(predicate)] * sen_len + ctx_n2_slot = [word_dict.get(ctx_n2, UNK_IDX)] * sen_len + ctx_n1_slot = [word_dict.get(ctx_n1, UNK_IDX)] * sen_len + ctx_0_slot = [word_dict.get(ctx_0, UNK_IDX)] * sen_len + ctx_p1_slot = [word_dict.get(ctx_p1, UNK_IDX)] * sen_len + ctx_p2_slot = [word_dict.get(ctx_p2, UNK_IDX)] * sen_len + + marks = mark.split() + mark_slot = [int(w) for w in marks] + + label_list = label.split() + label_slot = [label_dict.get(w) for w in label_list] + yield word_slot, ctx_n2_slot, ctx_n1_slot, \ + ctx_0_slot, ctx_p1_slot, ctx_p2_slot, predicate_slot, mark_slot, label_slot + + return reader + + +def main(): + paddle.init(use_gpu=False, trainer_count=1) + + label_dict_len = 500 + # define network topology + output = db_lstm() + target = paddle.layer.data(name='target', size=label_dict_len) + crf_cost = paddle.layer.crf_layer( + size=500, + input=output, + label=target, + param_attr=paddle.attr.Param( + name='crfw', initial_std=default_std, learning_rate=mix_hidden_lr)) + + crf_dec = paddle.layer.crf_decoding_layer( + name='crf_dec_l', + size=label_dict_len, + input=output, + label=target, + param_attr=paddle.attr.Param(name='crfw')) + + topo = [crf_cost, crf_dec] + parameters = paddle.parameters.create(topo) + optimizer = paddle.optimizer.Momentum(momentum=0.01, learning_rate=2e-2) + + def event_handler(event): + if isinstance(event, paddle.event.EndIteration): + para = parameters.get('___fc_2__.w0') + print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, + event.cost, para.mean()) + + else: + pass + + trainer = paddle.trainer.SGD(update_equation=optimizer) + + trainer.train( + train_data_reader=train_reader, + batch_size=32, + topology=topo, + parameters=parameters, + event_handler=event_handler, + num_passes=10000, + data_types=[], + reader_dict={}) + + +if __name__ == '__main__': + main() diff --git a/demo/semantic_role_labeling/model_v2.py b/demo/semantic_role_labeling/model_v2.py new file mode 100644 index 0000000000000..d4d011770dc2d --- /dev/null +++ b/demo/semantic_role_labeling/model_v2.py @@ -0,0 +1,103 @@ +import paddle.v2 as paddle + + +def db_lstm(word_dict_len, label_dict_len, pred_len): + mark_dict_len = 2 + word_dim = 32 + mark_dim = 5 + hidden_dim = 512 + depth = 8 + + #8 features + word = paddle.layer.data(name='word_data', size=word_dict_len) + predicate = paddle.layer.data(name='verb_data', size=pred_len) + + ctx_n2 = paddle.layer.data(name='ctx_n2_data', size=word_dict_len) + ctx_n1 = paddle.layer.data(name='ctx_n1_data', size=word_dict_len) + ctx_0 = paddle.layer.data(name='ctx_0_data', size=word_dict_len) + ctx_p1 = paddle.layer.data(name='ctx_p1_data', size=word_dict_len) + ctx_p2 = paddle.layer.data(name='ctx_p2_data', size=word_dict_len) + mark = paddle.layer.data(name='mark_data', size=mark_dict_len) + + default_std = 1 / math.sqrt(hidden_dim) / 3.0 + + emb_para = paddle.attr.Param(name='emb', initial_std=0., learning_rate=0.) + std_0 = paddle.attr.Param(initial_std=0.) + std_default = paddle.attr.Param(initial_std=default_std) + + predicate_embedding = paddle.layer.embeding( + size=word_dim, + input=predicate, + param_attr=paddle.attr.Param( + name='vemb', initial_std=default_std)) + mark_embedding = paddle.layer.embeding( + name='word_ctx-in_embedding', + size=mark_dim, + input=mark, + param_attr=std_0) + + word_input = [word, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2] + emb_layers = [ + paddle.layer.embeding( + size=word_dim, input=x, param_attr=emb_para) for x in word_input + ] + emb_layers.append(predicate_embedding) + emb_layers.append(mark_embedding) + + hidden_0 = paddle.layer.mixed( + size=hidden_dim, + bias_attr=std_default, + input=[ + paddle.layer.full_matrix_projection( + input=emb, param_attr=std_default) for emb in emb_layers + ]) + + mix_hidden_lr = 1e-3 + lstm_para_attr = paddle.attr.Param(initial_std=0.0, learning_rate=1.0) + hidden_para_attr = paddle.attr.Param( + initial_std=default_std, learning_rate=mix_hidden_lr) + + lstm_0 = paddle.layer.lstmemory( + input=hidden_0, + act=paddle.activation.Relu(), + gate_act=paddle.activation.Sigmoid(), + state_act=paddle.activation.Sigmoid(), + bias_attr=std_0, + param_attr=lstm_para_attr) + + #stack L-LSTM and R-LSTM with direct edges + input_tmp = [hidden_0, lstm_0] + + for i in range(1, depth): + mix_hidden = paddle.layer.mixed( + size=hidden_dim, + bias_attr=std_default, + input=[ + paddle.layer.full_matrix_projection( + input=input_tmp[0], param_attr=hidden_para_attr), + paddle.layer.full_matrix_projection( + input=input_tmp[1], param_attr=lstm_para_attr) + ]) + + lstm = paddle.layer.lstmemory( + input=mix_hidden, + act=paddle.activation.Relu(), + gate_act=paddle.activation.Sigmoid(), + state_act=paddle.activation.Sigmoid(), + reverse=((i % 2) == 1), + bias_attr=std_0, + param_attr=lstm_para_attr) + + input_tmp = [mix_hidden, lstm] + + feature_out = paddle.layer.mixed( + size=label_dict_len, + bias_attr=std_default, + input=[ + paddle.layer.full_matrix_projection( + input=input_tmp[0], param_attr=hidden_para_attr), + paddle.layer.full_matrix_projection( + input=input_tmp[1], param_attr=lstm_para_attr) + ], ) + + return feature_out From da754d85de3ffcf850ad2b375d8922110c7279e1 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 28 Feb 2017 14:55:16 +0800 Subject: [PATCH 012/153] srl api training --- demo/semantic_role_labeling/api_train_v2.py | 21 +++++++++++------ demo/semantic_role_labeling/model_v2.py | 25 +++++++++++---------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py index 33b966cca579f..daaf0f058229a 100644 --- a/demo/semantic_role_labeling/api_train_v2.py +++ b/demo/semantic_role_labeling/api_train_v2.py @@ -1,8 +1,6 @@ import numpy import paddle.v2 as paddle -from paddle.trainer_config_helpers.atts import ParamAttr - -from mode_v2 import db_lstm +from model_v2 import db_lstm word_dict_file = './data/wordDict.txt' label_dict_file = './data/targetDict.txt' @@ -64,9 +62,8 @@ def reader(): def main(): paddle.init(use_gpu=False, trainer_count=1) - label_dict_len = 500 # define network topology - output = db_lstm() + output = db_lstm(word_dict_len, label_dict_len, pred_len) target = paddle.layer.data(name='target', size=label_dict_len) crf_cost = paddle.layer.crf_layer( size=500, @@ -97,6 +94,17 @@ def event_handler(event): trainer = paddle.trainer.SGD(update_equation=optimizer) + reader_dict = { + 'word_data': 0, + 'verb_data': 1, + 'ctx_n2_data': 2, + 'ctx_n1_data': 3, + 'ctx_0_data': 4, + 'ctx_p1_data': 5, + 'ctx_p2_data': 6, + 'mark_data': 7, + 'target': 8 + } trainer.train( train_data_reader=train_reader, batch_size=32, @@ -104,8 +112,7 @@ def event_handler(event): parameters=parameters, event_handler=event_handler, num_passes=10000, - data_types=[], - reader_dict={}) + reader_dict=reader_dict) if __name__ == '__main__': diff --git a/demo/semantic_role_labeling/model_v2.py b/demo/semantic_role_labeling/model_v2.py index d4d011770dc2d..a78190a2b22aa 100644 --- a/demo/semantic_role_labeling/model_v2.py +++ b/demo/semantic_role_labeling/model_v2.py @@ -1,3 +1,4 @@ +import math import paddle.v2 as paddle @@ -9,15 +10,18 @@ def db_lstm(word_dict_len, label_dict_len, pred_len): depth = 8 #8 features - word = paddle.layer.data(name='word_data', size=word_dict_len) - predicate = paddle.layer.data(name='verb_data', size=pred_len) + def d_type(size): + return paddle.data_type.integer_value_sequence(size) - ctx_n2 = paddle.layer.data(name='ctx_n2_data', size=word_dict_len) - ctx_n1 = paddle.layer.data(name='ctx_n1_data', size=word_dict_len) - ctx_0 = paddle.layer.data(name='ctx_0_data', size=word_dict_len) - ctx_p1 = paddle.layer.data(name='ctx_p1_data', size=word_dict_len) - ctx_p2 = paddle.layer.data(name='ctx_p2_data', size=word_dict_len) - mark = paddle.layer.data(name='mark_data', size=mark_dict_len) + word = paddle.layer.data(name='word_data', type=d_type(word_dict_len)) + predicate = paddle.layer.data(name='verb_data', type=d_type(pred_len)) + + ctx_n2 = paddle.layer.data(name='ctx_n2_data', type=d_type(word_dict_len)) + ctx_n1 = paddle.layer.data(name='ctx_n1_data', type=d_type(word_dict_len)) + ctx_0 = paddle.layer.data(name='ctx_0_data', type=d_type(word_dict_len)) + ctx_p1 = paddle.layer.data(name='ctx_p1_data', type=d_type(word_dict_len)) + ctx_p2 = paddle.layer.data(name='ctx_p2_data', type=d_type(word_dict_len)) + mark = paddle.layer.data(name='mark_data', type=d_type(mark_dict_len)) default_std = 1 / math.sqrt(hidden_dim) / 3.0 @@ -31,10 +35,7 @@ def db_lstm(word_dict_len, label_dict_len, pred_len): param_attr=paddle.attr.Param( name='vemb', initial_std=default_std)) mark_embedding = paddle.layer.embeding( - name='word_ctx-in_embedding', - size=mark_dim, - input=mark, - param_attr=std_0) + size=mark_dim, input=mark, param_attr=std_0) word_input = [word, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2] emb_layers = [ From 07a86b52f4a792c3f2350fb1fadb3f34513c37b1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 28 Feb 2017 16:42:51 +0800 Subject: [PATCH 013/153] Refine --- demo/recommendation/api_train_v2.py | 34 +++++++++++++++++++++++++-- python/paddle/v2/dataset/movielens.py | 34 ++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py index 64dff9ae43285..c726fa5bdb31f 100644 --- a/demo/recommendation/api_train_v2.py +++ b/demo/recommendation/api_train_v2.py @@ -3,9 +3,39 @@ def main(): movie_title_dict = paddle.dataset.movielens.get_movie_title_dict() - title_word_count = len(movie_title_dict) + uid = paddle.layer.data( + name='user_id', + type=paddle.data_type.integer_value( + paddle.dataset.movielens.max_user_id() + 1)) + usr_emb = paddle.layer.embedding(input=uid, size=32) - paddle.layer.mixed + usr_gender_id = paddle.layer.data( + name='gender_id', type=paddle.data_type.integer_value(2)) + usr_gender_emb = paddle.layer.embedding(input=usr_gender_id, size=16) + + usr_age_id = paddle.layer.data( + name='age_id', + type=paddle.data_type.integer_value( + len(paddle.dataset.movielens.age_table))) + usr_age_emb = paddle.embedding(input=usr_age_id, size=16) + + usr_combined_features = paddle.fc( + input=[usr_emb, usr_gender_emb, usr_age_emb], + size=200, + act=paddle.activation.Tanh()) + + mov_id = paddle.layer.data( + name='movie_id', + type=paddle.data_type.integer_value( + paddle.dataset.movielens.max_movie_id() + 1)) + mov_emb = paddle.layer.embedding(input=mov_id, size=32) + + mov_title_id = paddle.layer.data( + name='movie_title', + type=paddle.data_type.integer_value(len(movie_title_dict))) + mov_title_emb = paddle.embedding(input=mov_title_id, size=32) + with paddle.layer.mixed() as mixed: + pass if __name__ == '__main__': diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py index b66448fafe421..6efe42adbaff9 100644 --- a/python/paddle/v2/dataset/movielens.py +++ b/python/paddle/v2/dataset/movielens.py @@ -4,7 +4,12 @@ import random import functools -__all__ = ['train_creator', 'test_creator', 'get_movie_title_dict'] +__all__ = [ + 'train', 'test', 'get_movie_title_dict', 'max_movie_id', 'max_user_id', + 'age_table' +] + +age_table = [1, 18, 25, 35, 45, 50, 56] class MovieInfo(object): @@ -24,7 +29,7 @@ class UserInfo(object): def __init__(self, index, gender, age, job_id): self.index = int(index) self.is_male = gender == 'M' - self.age = [1, 18, 25, 35, 45, 50, 56].index(int(age)) + self.age = age_table.index(int(age)) self.job_id = int(job_id) def value(self): @@ -104,8 +109,8 @@ def __reader_creator__(**kwargs): return lambda: __reader__(**kwargs) -train_creator = functools.partial(__reader_creator__, is_test=False) -test_creator = functools.partial(__reader_creator__, is_test=True) +train = functools.partial(__reader_creator__, is_test=False) +test = functools.partial(__reader_creator__, is_test=True) def get_movie_title_dict(): @@ -113,10 +118,27 @@ def get_movie_title_dict(): return MOVIE_TITLE_DICT +def __max_index_info__(a, b): + if a.index > b.index: + return a + else: + return b + + +def max_movie_id(): + __initialize_meta_info__() + return reduce(__max_index_info__, MOVIE_INFO.viewvalues()).index + + +def max_user_id(): + __initialize_meta_info__() + return reduce(__max_index_info__, USER_INFO.viewvalues()).index + + def unittest(): - for train_count, _ in enumerate(train_creator()()): + for train_count, _ in enumerate(train()()): pass - for test_count, _ in enumerate(test_creator()()): + for test_count, _ in enumerate(test()()): pass print train_count, test_count From b6a0f9a32a4a3e35f9d8ffa4728c69fada5fe5ed Mon Sep 17 00:00:00 2001 From: liaogang Date: Tue, 28 Feb 2017 18:00:34 +0800 Subject: [PATCH 014/153] Add vgg training via api v2 --- demo/image_classification/train_v2_vgg.py | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 demo/image_classification/train_v2_vgg.py diff --git a/demo/image_classification/train_v2_vgg.py b/demo/image_classification/train_v2_vgg.py new file mode 100644 index 0000000000000..33b53b27daf4b --- /dev/null +++ b/demo/image_classification/train_v2_vgg.py @@ -0,0 +1,85 @@ +import paddle.v2 as paddle + + +def event_handler(event): + if isinstance(event, paddle.event.EndIteration): + if event.batch_id % 100 == 0: + print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, + event.cost) + else: + pass + + +def vgg_bn_drop(input): + def conv_block(ipt, num_filter, groups, dropouts, num_channels=None): + return paddle.layer.img_conv_group( + input=ipt, + num_channels=num_channels, + pool_size=2, + pool_stride=2, + conv_num_filter=[num_filter] * groups, + conv_filter_size=3, + conv_act=paddle.activation.Relu(), + conv_with_batchnorm=True, + conv_batchnorm_drop_rate=dropouts, + pool_type=pooling.Max()) + + conv1 = conv_block(input, 64, 2, [0.3, 0], 3) + conv2 = conv_block(conv1, 128, 2, [0.4, 0]) + conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0]) + conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0]) + conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0]) + + drop = paddle.layer.dropout(input=conv5, dropout_rate=0.5) + fc1 = paddle.layer.fc(input=drop, size=512, act=paddle.activation.Linear()) + bn = paddle.layer.batch_norm( + input=fc1, + act=paddle.activation.Relu(), + layer_attr=ExtraAttr(drop_rate=0.5)) + fc2 = paddle.layer.fc(input=bn, size=512, act=paddle.activation.Linear()) + return fc2 + + +def main(): + datadim = 3 * 32 * 32 + classdim = 10 + + paddle.init(use_gpu=False, trainer_count=1) + + image = paddle.layer.data( + name="image", type=paddle.data_type.dense_vector(datadim)) + # net = vgg_bn_drop(image) + out = paddle.layer.fc(input=image, + size=classdim, + act=paddle.activation.Softmax()) + + lbl = paddle.layer.data( + name="label", type=paddle.data_type.integer_value(classdim)) + cost = paddle.layer.classification_cost(input=out, label=lbl) + + parameters = paddle.parameters.create(cost) + momentum_optimizer = paddle.optimizer.Momentum( + momentum=0.9, + regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128), + learning_rate=0.1 / 128.0, + learning_rate_decay_a=0.1, + learning_rate_decay_b=50000 * 100, + learning_rate_schedule='discexp', + batch_size=128) + + trainer = paddle.trainer.SGD(update_equation=momentum_optimizer) + trainer.train( + reader=paddle.reader.batched( + paddle.reader.shuffle( + paddle.dataset.cifar.train10(), buf_size=3072), + batch_size=128), + cost=cost, + num_passes=1, + parameters=parameters, + event_handler=event_handler, + reader_dict={'image': 0, + 'label': 1}, ) + + +if __name__ == '__main__': + main() From 7ad8363036af9d8ae91e6698ff09804023602bdf Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 28 Feb 2017 19:44:56 +0800 Subject: [PATCH 015/153] support boot_layer --- .../paddle/trainer_config_helpers/layers.py | 6 ++- python/paddle/v2/layer.py | 37 ++++++++++++++++--- python/paddle/v2/tests/CMakeLists.txt | 1 - 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index a8b536dda4f24..4f7a2735e296d 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -3110,7 +3110,8 @@ def recurrent_group(step, name=None, targetInlink=None, is_generating=False, - in_args_converter=None): + in_args_converter=None, + boot_layer=None): """ Recurrent layer group is an extremely flexible recurrent unit in PaddlePaddle. As long as the user defines the calculation done within a @@ -3256,6 +3257,9 @@ def map_in_links(x): if in_args_converter is None: layer_outs = step(*in_args) else: + # append boot_layer to the last of in_args + if boot_layer is not None: + in_args.append(boot_layer) layer_outs = step(*in_args_converter(*in_args)).to_proto(dict()) if isinstance(layer_outs, LayerOutput): diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 1155eca9c815b..542d5a515c561 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -140,10 +140,13 @@ def to_proto(self, context): if self.name is None: return self.to_proto_impl(**kwargs) elif isinstance(self, MemoryV2): - return self.to_proto_impl(**kwargs) - elif self.name not in context: - context[self.name] = self.to_proto_impl(**kwargs) + name = self.name + "#__memory__" + if name not in context: + context[name] = self.to_proto_impl(**kwargs) + return context[name] + if self.name not in context: + context[self.name] = self.to_proto_impl(**kwargs) return context[self.name] def to_proto_impl(self, **kwargs): @@ -256,9 +259,32 @@ def to_proto_impl(self): return self.layer_output +class StaticInputV2(Layer): + def __init__(self, **kwargs): + self.__parent_names__ = ['input'] + other_kwargs = dict() + parent_layers = dict() + for pname in self.__parent_names__: + if kwargs.has_key(pname): + parent_layers[pname] = kwargs[pname] + for key in kwargs.keys(): + if key not in self.__parent_names__: + other_kwargs[key] = kwargs[key] + self.__kwargs__ = other_kwargs + super(StaticInputV2, self).__init__(parent_layers=parent_layers) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__kwargs__: + args[each] = self.__kwargs__[each] + return conf_helps.StaticInput(**args) + + class RecurrentGroupV2(Layer): def __init__(self, name, **kwargs): - self.__parent_names__ = ['input'] + self.__parent_names__ = ['input', 'boot_layer'] other_kwargs = dict() parent_layers = dict() for pname in self.__parent_names__: @@ -443,7 +469,8 @@ def mixed(size=0, ['nce', 'nce_layer', ['input', 'label']], ['hsigmoid', 'hsigmoid', ['input', 'label']], # check layers - ['eos', 'eos_layer', ['input']] + ['eos', 'eos_layer', ['input']], + ['gru_step_layer', 'gru_step_layer', ['input', 'output_mem']] ] for l in layer_list: globals()[l[0]] = __convert_to_v2__(l[1], l[2]) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index 948cebdf727c6..572deaff35671 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -10,7 +10,6 @@ add_test(NAME test_v2_rnn_layer COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_rnn_layer.py) - add_test(NAME test_topology COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_topology.py From e6e8bfb44ef70320bcf1cca1abeebd6ff58281b4 Mon Sep 17 00:00:00 2001 From: dangqingqing Date: Tue, 28 Feb 2017 19:48:22 +0800 Subject: [PATCH 016/153] update --- demo/semantic_role_labeling/api_train_v2.py | 55 ++++++++++----------- demo/semantic_role_labeling/model_v2.py | 25 ++++++++-- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py index daaf0f058229a..0317c818db256 100644 --- a/demo/semantic_role_labeling/api_train_v2.py +++ b/demo/semantic_role_labeling/api_train_v2.py @@ -2,6 +2,8 @@ import paddle.v2 as paddle from model_v2 import db_lstm +UNK_IDX = 0 + word_dict_file = './data/wordDict.txt' label_dict_file = './data/targetDict.txt' predicate_file = './data/verbDict.txt' @@ -29,6 +31,10 @@ label_dict_len = len(label_dict) pred_len = len(predicate_dict) +print 'word_dict_len=%d' % word_dict_len +print 'label_dict_len=%d' % label_dict_len +print 'pred_len=%d' % pred_len + def train_reader(file_name="data/feature"): def reader(): @@ -63,31 +69,16 @@ def main(): paddle.init(use_gpu=False, trainer_count=1) # define network topology - output = db_lstm(word_dict_len, label_dict_len, pred_len) - target = paddle.layer.data(name='target', size=label_dict_len) - crf_cost = paddle.layer.crf_layer( - size=500, - input=output, - label=target, - param_attr=paddle.attr.Param( - name='crfw', initial_std=default_std, learning_rate=mix_hidden_lr)) - - crf_dec = paddle.layer.crf_decoding_layer( - name='crf_dec_l', - size=label_dict_len, - input=output, - label=target, - param_attr=paddle.attr.Param(name='crfw')) - - topo = [crf_cost, crf_dec] - parameters = paddle.parameters.create(topo) + crf_cost, crf_dec = db_lstm(word_dict_len, label_dict_len, pred_len) + + #parameters = paddle.parameters.create([crf_cost, crf_dec]) + parameters = paddle.parameters.create(crf_cost) optimizer = paddle.optimizer.Momentum(momentum=0.01, learning_rate=2e-2) def event_handler(event): if isinstance(event, paddle.event.EndIteration): - para = parameters.get('___fc_2__.w0') print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id, - event.cost, para.mean()) + event.cost) else: pass @@ -96,23 +87,27 @@ def event_handler(event): reader_dict = { 'word_data': 0, - 'verb_data': 1, - 'ctx_n2_data': 2, - 'ctx_n1_data': 3, - 'ctx_0_data': 4, - 'ctx_p1_data': 5, - 'ctx_p2_data': 6, + 'ctx_n2_data': 1, + 'ctx_n1_data': 2, + 'ctx_0_data': 3, + 'ctx_p1_data': 4, + 'ctx_p2_data': 5, + 'verb_data': 6, 'mark_data': 7, - 'target': 8 + 'target': 8, } + #trn_reader = paddle.reader.batched( + # paddle.reader.shuffle( + # train_reader(), buf_size=8192), batch_size=2) + trn_reader = paddle.reader.batched(train_reader(), batch_size=1) trainer.train( - train_data_reader=train_reader, - batch_size=32, - topology=topo, + reader=trn_reader, + cost=crf_cost, parameters=parameters, event_handler=event_handler, num_passes=10000, reader_dict=reader_dict) + #cost=[crf_cost, crf_dec], if __name__ == '__main__': diff --git a/demo/semantic_role_labeling/model_v2.py b/demo/semantic_role_labeling/model_v2.py index a78190a2b22aa..cec58e52c7940 100644 --- a/demo/semantic_role_labeling/model_v2.py +++ b/demo/semantic_role_labeling/model_v2.py @@ -23,23 +23,25 @@ def d_type(size): ctx_p2 = paddle.layer.data(name='ctx_p2_data', type=d_type(word_dict_len)) mark = paddle.layer.data(name='mark_data', type=d_type(mark_dict_len)) + target = paddle.layer.data(name='target', type=d_type(label_dict_len)) + default_std = 1 / math.sqrt(hidden_dim) / 3.0 emb_para = paddle.attr.Param(name='emb', initial_std=0., learning_rate=0.) std_0 = paddle.attr.Param(initial_std=0.) std_default = paddle.attr.Param(initial_std=default_std) - predicate_embedding = paddle.layer.embeding( + predicate_embedding = paddle.layer.embedding( size=word_dim, input=predicate, param_attr=paddle.attr.Param( name='vemb', initial_std=default_std)) - mark_embedding = paddle.layer.embeding( + mark_embedding = paddle.layer.embedding( size=mark_dim, input=mark, param_attr=std_0) word_input = [word, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2] emb_layers = [ - paddle.layer.embeding( + paddle.layer.embedding( size=word_dim, input=x, param_attr=emb_para) for x in word_input ] emb_layers.append(predicate_embedding) @@ -101,4 +103,19 @@ def d_type(size): input=input_tmp[1], param_attr=lstm_para_attr) ], ) - return feature_out + crf_cost = paddle.layer.crf(size=label_dict_len, + input=feature_out, + label=target, + param_attr=paddle.attr.Param( + name='crfw', + initial_std=default_std, + learning_rate=mix_hidden_lr)) + + crf_dec = paddle.layer.crf_decoding( + name='crf_dec_l', + size=label_dict_len, + input=feature_out, + label=target, + param_attr=paddle.attr.Param(name='crfw')) + + return crf_cost, crf_dec From 1478dd622508f9e07416667e483c6e0eb6b55733 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 1 Mar 2017 11:13:17 +0800 Subject: [PATCH 017/153] Add git completion, prompt, pre-commit in docker --- paddle/scripts/docker/Dockerfile | 46 +- paddle/scripts/docker/root/.bashrc | 46 + paddle/scripts/docker/root/.gitconfig | 43 + .../docker/root/.scripts/git-completion.sh | 2663 +++++++++++++++++ .../docker/root/.scripts/git-prompt.sh | 445 +++ 5 files changed, 3225 insertions(+), 18 deletions(-) create mode 100755 paddle/scripts/docker/root/.bashrc create mode 100755 paddle/scripts/docker/root/.gitconfig create mode 100755 paddle/scripts/docker/root/.scripts/git-completion.sh create mode 100755 paddle/scripts/docker/root/.scripts/git-prompt.sh diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 27d19dc15c8bd..27423faef47de 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -5,38 +5,49 @@ ARG DEBIAN_FRONTEND=noninteractive ARG UBUNTU_MIRROR RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi' +# ENV variables +ARG BUILD_WOBOQ +ARG BUILD_AND_INSTALL +ARG WITH_AVX +ARG WITH_DOC +ARG WITH_STYLE_CHECK + +ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} +ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} +ENV WITH_GPU=OFF +ENV WITH_AVX=${WITH_AVX:-ON} +ENV WITH_DOC=${WITH_DOC:-OFF} +ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} + +ENV HOME /root + +# Add bash enhancements +ADD root/.bashrc /root/.bashrc +ADD root/.gitconfig /root/.gitconfig +ADD root/.scripts /root/.scripts + RUN apt-get update && \ apt-get install -y git python-pip python-dev openssh-server bison && \ apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \ apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \ apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \ - apt-get install -y automake && \ + apt-get install -y automake locales && \ apt-get clean -y +# Fix locales to en_US.UTF-8 +RUN localedef -i en_US -f UTF-8 en_US.UTF-8 + RUN pip install --upgrade pip && \ - pip install -U "protobuf==3.1.0" && \ + pip install -U 'protobuf==3.1.0' && \ pip install -U wheel pillow BeautifulSoup && \ pip install -U docopt PyYAML sphinx && \ - pip install -U sphinx_rtd_theme recommonmark jupyter + pip install -U sphinx_rtd_theme recommonmark && \ + pip install -U pre-commit 'requests==2.9.2' jupyter RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ cd cmake-3.4.1 && ./bootstrap && make -j `nproc` && make install && \ cd .. && rm -rf cmake-3.4.1 -ARG BUILD_WOBOQ -ARG BUILD_AND_INSTALL -ARG WITH_AVX -ARG WITH_DOC -ARG WITH_STYLE_CHECK - -ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF} -ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF} -ENV WITH_GPU=OFF -ENV WITH_AVX=${WITH_AVX:-ON} -ENV WITH_DOC=${WITH_DOC:-OFF} -ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF} - -RUN mkdir /paddle COPY . /paddle/ RUN /paddle/paddle/scripts/docker/build.sh VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"] @@ -53,7 +64,6 @@ RUN mkdir /notes/ WORKDIR "/notes" EXPOSE 8888 -RUN mkdir -p /opt/bin COPY ./paddle/scripts/docker/entrypoint /opt/bin/ CMD ["/opt/bin/entrypoint"] diff --git a/paddle/scripts/docker/root/.bashrc b/paddle/scripts/docker/root/.bashrc new file mode 100755 index 0000000000000..4b3024e4e81a0 --- /dev/null +++ b/paddle/scripts/docker/root/.bashrc @@ -0,0 +1,46 @@ +# Locales + +export LC_ALL=en_US.UTF-8 +export LANG=en_US.UTF-8 +export LANGUAGE=en_US.UTF-8 + +# Aliases + +alias rm='rm -i' +alias cp='cp -i' +alias mv='mv -i' + +alias ls='ls -hFG' +alias l='ls -lF' +alias ll='ls -alF' +alias lt='ls -ltrF' +alias ll='ls -alF' +alias lls='ls -alSrF' +alias llt='ls -altrF' + +# Colorize directory listing + +alias ls="ls -ph --color=auto" + +# Colorize grep + +if echo hello|grep --color=auto l >/dev/null 2>&1; then + export GREP_OPTIONS="--color=auto" GREP_COLOR="1;31" +fi + +# Shell + +export CLICOLOR="1" + +YELLOW="\[\033[1;33m\]" +NO_COLOUR="\[\033[0m\]" +GREEN="\[\033[1;32m\]" +WHITE="\[\033[1;37m\]" + +source ~/.scripts/git-prompt.sh + +export PS1="\[\033[1;33m\]λ $WHITE\h $GREEN\w$YELLOW\$(__git_ps1 \" \[\033[35m\]{\[\033[36m\]%s\[\033[35m\]}\")$NO_COLOUR " + +# Git + +source ~/.scripts/git-completion.sh diff --git a/paddle/scripts/docker/root/.gitconfig b/paddle/scripts/docker/root/.gitconfig new file mode 100755 index 0000000000000..6c249803a5040 --- /dev/null +++ b/paddle/scripts/docker/root/.gitconfig @@ -0,0 +1,43 @@ +[user] + name = + email = + +[alias] + st = status --branch --short + ci = commit + br = branch + co = checkout + df = diff + l = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short + ll = log --stat + +[merge] + tool = vimdiff + +[core] + excludesfile = ~/.gitignore + editor = vim + +[color] + branch = auto + diff = auto + status = auto + +[color "branch"] + current = yellow reverse + local = yellow + remote = green + +[color "diff"] + meta = yellow bold + frag = magenta bold + old = red bold + new = green bold + +[color "status"] + added = yellow + changed = green + untracked = cyan + +[push] + default = matching \ No newline at end of file diff --git a/paddle/scripts/docker/root/.scripts/git-completion.sh b/paddle/scripts/docker/root/.scripts/git-completion.sh new file mode 100755 index 0000000000000..bdddef5ac2faf --- /dev/null +++ b/paddle/scripts/docker/root/.scripts/git-completion.sh @@ -0,0 +1,2663 @@ +#!bash +# +# bash/zsh completion support for core Git. +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). +# Distributed under the GNU General Public License, version 2.0. +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) .git/remotes file names +# *) git 'subcommands' +# *) tree paths within 'ref:path/to/file' expressions +# *) file paths within current working directory and index +# *) common --long-options +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-completion.sh +# 3) Consider changing your PS1 to also show the current branch, +# see git-prompt.sh for details. + +case "$COMP_WORDBREAKS" in +*:*) : great ;; +*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" +esac + +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + if [ -n "${__git_dir-}" ]; then + echo "$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" || return 1 + echo "$GIT_DIR" + elif [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# The following function is based on code from: +# +# bash_completion - programmable completion functions for bash 3.2+ +# +# Copyright © 2006-2008, Ian Macdonald +# © 2009-2010, Bash Completion Maintainers +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The latest version of this software can be obtained here: +# +# http://bash-completion.alioth.debian.org/ +# +# RELEASE: 2.x + +# This function can be used to access a tokenized list of words +# on the command line: +# +# __git_reassemble_comp_words_by_ref '=:' +# if test "${words_[cword_-1]}" = -w +# then +# ... +# fi +# +# The argument should be a collection of characters from the list of +# word completion separators (COMP_WORDBREAKS) to treat as ordinary +# characters. +# +# This is roughly equivalent to going back in time and setting +# COMP_WORDBREAKS to exclude those characters. The intent is to +# make option types like --date= and : easy to +# recognize by treating each shell word as a single token. +# +# It is best not to set COMP_WORDBREAKS directly because the value is +# shared with other completion scripts. By the time the completion +# function gets called, COMP_WORDS has already been populated so local +# changes to COMP_WORDBREAKS have no effect. +# +# Output: words_, cword_, cur_. + +__git_reassemble_comp_words_by_ref() +{ + local exclude i j first + # Which word separators to exclude? + exclude="${1//[^$COMP_WORDBREAKS]}" + cword_=$COMP_CWORD + if [ -z "$exclude" ]; then + words_=("${COMP_WORDS[@]}") + return + fi + # List of word completion separators has shrunk; + # re-assemble words to complete. + for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do + # Append each nonempty word consisting of just + # word separator characters to the current word. + first=t + while + [ $i -gt 0 ] && + [ -n "${COMP_WORDS[$i]}" ] && + # word consists of excluded word separators + [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] + do + # Attach to the previous token, + # unless the previous token is the command name. + if [ $j -ge 2 ] && [ -n "$first" ]; then + ((j--)) + fi + first= + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + if (($i < ${#COMP_WORDS[@]} - 1)); then + ((i++)) + else + # Done. + return + fi + done + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + done +} + +if ! type _get_comp_words_by_ref >/dev/null 2>&1; then +_get_comp_words_by_ref () +{ + local exclude cur_ words_ cword_ + if [ "$1" = "-n" ]; then + exclude=$2 + shift 2 + fi + __git_reassemble_comp_words_by_ref "$exclude" + cur_=${words_[cword_]} + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=$cur_ + ;; + prev) + prev=${words_[$cword_-1]} + ;; + words) + words=("${words_[@]}") + ;; + cword) + cword=$cword_ + ;; + esac + shift + done +} +fi + +__gitcompadd () +{ + local i=0 + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp () +{ + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c i=0 IFS=$' \t\n' + for c in $1; do + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; + esac +} + +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words, separated by a single newline. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word instead of +# the default space (optional). If specified but empty, nothing is +# appended. +__gitcomp_nl () +{ + local IFS=$'\n' + __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Generates completion reply with compgen from newline-separated possible +# completion filenames. +# It accepts 1 to 3 arguments: +# 1: List of possible completion filenames, separated by a single newline. +# 2: A directory prefix to be added to each possible completion filename +# (optional). +# 3: Generate possible completion matches for this word (optional). +__gitcomp_file () +{ + local IFS=$'\n' + + # XXX does not work when the directory prefix contains a tilde, + # since tilde expansion is not applied. + # This means that COMPREPLY will be empty and Bash default + # completion will be used. + __gitcompadd "$1" "${2-}" "${3-$cur}" "" + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ > /dev/null +} + +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. +__git_ls_files_helper () +{ + ( + test -n "${CDPATH+set}" && unset CDPATH + cd "$1" + if [ "$2" == "--committable" ]; then + git diff-index --name-only --relative HEAD + else + # NOTE: $2 is not quoted in order to support multiple options + git ls-files --exclude-standard $2 + fi + ) 2>/dev/null +} + + +# __git_index_files accepts 1 or 2 arguments: +# 1: Options to pass to ls-files (required). +# 2: A directory path (optional). +# If provided, only files within the specified directory are listed. +# Sub directories are never recursed. Path must have a trailing +# slash. +__git_index_files () +{ + local dir="$(__gitdir)" root="${2-.}" file + + if [ -d "$dir" ]; then + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + done | sort | uniq + fi +} + +__git_heads () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/heads + return + fi +} + +__git_tags () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/tags + return + fi +} + +# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments +# presence of 2nd argument means use the guess heuristic employed +# by checkout for tracking branches +__git_refs () +{ + local i hash dir="$(__gitdir "${1-}")" track="${2-}" + local format refs + if [ -d "$dir" ]; then + case "$cur" in + refs|refs/*) + format="refname" + refs="${cur%/*}" + track="" + ;; + *) + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do + if [ -e "$dir/$i" ]; then echo $i; fi + done + format="refname:short" + refs="refs/tags refs/heads refs/remotes" + ;; + esac + git --git-dir="$dir" for-each-ref --format="%($format)" \ + $refs + if [ -n "$track" ]; then + # employ the heuristic used by git checkout + # Try to find a remote branch that matches the completion word + # but only output if the branch name is unique + local ref entry + git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \ + "refs/remotes/" | \ + while read -r entry; do + eval "$entry" + ref="${ref#*/}" + if [[ "$ref" == "$cur"* ]]; then + echo "$ref" + fi + done | sort | uniq -u + fi + return + fi + case "$cur" in + refs|refs/*) + git ls-remote "$dir" "$cur*" 2>/dev/null | \ + while read -r hash i; do + case "$i" in + *^{}) ;; + *) echo "$i" ;; + esac + done + ;; + *) + echo "HEAD" + git for-each-ref --format="%(refname:short)" -- "refs/remotes/$dir/" | sed -e "s#^$dir/##" + ;; + esac +} + +# __git_refs2 requires 1 argument (to pass to __git_refs) +__git_refs2 () +{ + local i + for i in $(__git_refs "$1"); do + echo "$i:$i" + done +} + +# __git_refs_remotes requires 1 argument (to pass to ls-remote) +__git_refs_remotes () +{ + local i hash + git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ + while read -r hash i; do + echo "$i:refs/remotes/$1/${i#refs/heads/}" + done +} + +__git_remotes () +{ + local i IFS=$'\n' d="$(__gitdir)" + test -d "$d/remotes" && ls -1 "$d/remotes" + for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do + i="${i#remote.}" + echo "${i/.url*/}" + done +} + +__git_list_merge_strategies () +{ + git merge -s help 2>&1 | + sed -n -e '/[Aa]vailable strategies are: /,/^$/{ + s/\.$// + s/.*:// + s/^[ ]*// + s/[ ]*$// + p + }' +} + +__git_merge_strategies= +# 'git merge -s help' (and thus detection of the merge strategy +# list) fails, unfortunately, if run outside of any git working +# tree. __git_merge_strategies is set to the empty string in +# that case, and the detection will be repeated the next time it +# is needed. +__git_compute_merge_strategies () +{ + test -n "$__git_merge_strategies" || + __git_merge_strategies=$(__git_list_merge_strategies) +} + +__git_complete_revlist_file () +{ + local pfx ls ref cur_="$cur" + case "$cur_" in + *..?*:*) + return + ;; + ?*:*) + ref="${cur_%%:*}" + cur_="${cur_#*:}" + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + ls="$ref:$pfx" + pfx="$pfx/" + ;; + *) + ls="$ref" + ;; + esac + + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="$ref:$pfx" ;; + esac + + __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ + | sed '/^100... blob /{ + s,^.* ,, + s,$, , + } + /^120000 blob /{ + s,^.* ,, + s,$, , + } + /^040000 tree /{ + s,^.* ,, + s,$,/, + } + s/^.* //')" \ + "$pfx" "$cur_" "" + ;; + *...*) + pfx="${cur_%...*}..." + cur_="${cur_#*...}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *..*) + pfx="${cur_%..*}.." + cur_="${cur_#*..}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + + +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ + local pfx="" cur_="$cur" + + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + pfx="${pfx}/" + ;; + esac + + __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_" +} + +__git_complete_file () +{ + __git_complete_revlist_file +} + +__git_complete_revlist () +{ + __git_complete_revlist_file +} + +__git_complete_remote_or_refspec () +{ + local cur_="$cur" cmd="${words[1]}" + local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 + if [ "$cmd" = "remote" ]; then + ((c++)) + fi + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; + --all) + case "$cmd" in + push) no_complete_refspec=1 ;; + fetch) + return + ;; + *) ;; + esac + ;; + -*) ;; + *) remote="$i"; break ;; + esac + ((c++)) + done + if [ -z "$remote" ]; then + __gitcomp_nl "$(__git_remotes)" + return + fi + if [ $no_complete_refspec = 1 ]; then + return + fi + [ "$remote" = "." ] && remote= + case "$cur_" in + *:*) + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="${cur_%%:*}:" ;; + esac + cur_="${cur_#*:}" + lhs=0 + ;; + +*) + pfx="+" + cur_="${cur_#+}" + ;; + esac + case "$cmd" in + fetch) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + pull|remote) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + push) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + fi + ;; + esac +} + +__git_complete_strategy () +{ + __git_compute_merge_strategies + case "$prev" in + -s|--strategy) + __gitcomp "$__git_merge_strategies" + return 0 + esac + case "$cur" in + --strategy=*) + __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}" + return 0 + ;; + esac + return 1 +} + +__git_commands () { + if test -n "${GIT_TESTING_COMMAND_COMPLETION:-}" + then + printf "%s" "${GIT_TESTING_COMMAND_COMPLETION}" + else + git help -a|egrep '^ [a-zA-Z0-9]' + fi +} + +__git_list_all_commands () +{ + local i IFS=" "$'\n' + for i in $(__git_commands) + do + case $i in + *--*) : helper pattern;; + *) echo $i;; + esac + done +} + +__git_all_commands= +__git_compute_all_commands () +{ + test -n "$__git_all_commands" || + __git_all_commands=$(__git_list_all_commands) +} + +__git_list_porcelain_commands () +{ + local i IFS=" "$'\n' + __git_compute_all_commands + for i in $__git_all_commands + do + case $i in + *--*) : helper pattern;; + applymbox) : ask gittus;; + applypatch) : ask gittus;; + archimport) : import;; + cat-file) : plumbing;; + check-attr) : plumbing;; + check-ignore) : plumbing;; + check-mailmap) : plumbing;; + check-ref-format) : plumbing;; + checkout-index) : plumbing;; + commit-tree) : plumbing;; + count-objects) : infrequent;; + credential-cache) : credentials helper;; + credential-store) : credentials helper;; + cvsexportcommit) : export;; + cvsimport) : import;; + cvsserver) : daemon;; + daemon) : daemon;; + diff-files) : plumbing;; + diff-index) : plumbing;; + diff-tree) : plumbing;; + fast-import) : import;; + fast-export) : export;; + fsck-objects) : plumbing;; + fetch-pack) : plumbing;; + fmt-merge-msg) : plumbing;; + for-each-ref) : plumbing;; + hash-object) : plumbing;; + http-*) : transport;; + index-pack) : plumbing;; + init-db) : deprecated;; + local-fetch) : plumbing;; + lost-found) : infrequent;; + ls-files) : plumbing;; + ls-remote) : plumbing;; + ls-tree) : plumbing;; + mailinfo) : plumbing;; + mailsplit) : plumbing;; + merge-*) : plumbing;; + mktree) : plumbing;; + mktag) : plumbing;; + pack-objects) : plumbing;; + pack-redundant) : plumbing;; + pack-refs) : plumbing;; + parse-remote) : plumbing;; + patch-id) : plumbing;; + peek-remote) : plumbing;; + prune) : plumbing;; + prune-packed) : plumbing;; + quiltimport) : import;; + read-tree) : plumbing;; + receive-pack) : plumbing;; + remote-*) : transport;; + repo-config) : deprecated;; + rerere) : plumbing;; + rev-list) : plumbing;; + rev-parse) : plumbing;; + runstatus) : plumbing;; + sh-setup) : internal;; + shell) : daemon;; + show-ref) : plumbing;; + send-pack) : plumbing;; + show-index) : plumbing;; + ssh-*) : transport;; + stripspace) : plumbing;; + symbolic-ref) : plumbing;; + tar-tree) : deprecated;; + unpack-file) : plumbing;; + unpack-objects) : plumbing;; + update-index) : plumbing;; + update-ref) : plumbing;; + update-server-info) : daemon;; + upload-archive) : plumbing;; + upload-pack) : plumbing;; + write-tree) : plumbing;; + var) : infrequent;; + verify-pack) : infrequent;; + verify-tag) : plumbing;; + *) echo $i;; + esac + done +} + +__git_porcelain_commands= +__git_compute_porcelain_commands () +{ + __git_compute_all_commands + test -n "$__git_porcelain_commands" || + __git_porcelain_commands=$(__git_list_porcelain_commands) +} + +__git_pretty_aliases () +{ + local i IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do + case "$i" in + pretty.*) + i="${i#pretty.}" + echo "${i/ */}" + ;; + esac + done +} + +__git_aliases () +{ + local i IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do + case "$i" in + alias.*) + i="${i#alias.}" + echo "${i/ */}" + ;; + esac + done +} + +# __git_aliased_command requires 1 argument +__git_aliased_command () +{ + local word cmdline=$(git --git-dir="$(__gitdir)" \ + config --get "alias.$1") + for word in $cmdline; do + case "$word" in + \!gitk|gitk) + echo "gitk" + return + ;; + \!*) : shell command alias ;; + -*) : option ;; + *=*) : setting env ;; + git) : git itself ;; + *) + echo "$word" + return + esac + done +} + +# __git_find_on_cmdline requires 1 argument +__git_find_on_cmdline () +{ + local word subcommand c=1 + while [ $c -lt $cword ]; do + word="${words[c]}" + for subcommand in $1; do + if [ "$subcommand" = "$word" ]; then + echo "$subcommand" + return + fi + done + ((c++)) + done +} + +__git_has_doubledash () +{ + local c=1 + while [ $c -lt $cword ]; do + if [ "--" = "${words[c]}" ]; then + return 0 + fi + ((c++)) + done + return 1 +} + +# Try to count non option arguments passed on the command line for the +# specified git command. +# When options are used, it is necessary to use the special -- option to +# tell the implementation were non option arguments begin. +# XXX this can not be improved, since options can appear everywhere, as +# an example: +# git mv x -n y +# +# __git_count_arguments requires 1 argument: the git command executed. +__git_count_arguments () +{ + local word i c=0 + + # Skip "git" (first argument) + for ((i=1; i < ${#words[@]}; i++)); do + word="${words[i]}" + + case "$word" in + --) + # Good; we can assume that the following are only non + # option arguments. + ((c = 0)) + ;; + "$1") + # Skip the specified git command and discard git + # main options + ((c = 0)) + ;; + ?*) + ((c++)) + ;; + esac + done + + printf "%d" $c +} + +__git_whitespacelist="nowarn warn error error-all fix" + +_git_am () +{ + local dir="$(__gitdir)" + if [ -d "$dir"/rebase-apply ]; then + __gitcomp "--skip --continue --resolved --abort" + return + fi + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --3way --committer-date-is-author-date --ignore-date + --ignore-whitespace --ignore-space-change + --interactive --keep --no-utf8 --signoff --utf8 + --whitespace= --scissors + " + return + esac +} + +_git_apply () +{ + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --stat --numstat --summary --check --index + --cached --index-info --reverse --reject --unidiff-zero + --apply --no-add --exclude= + --ignore-whitespace --ignore-space-change + --whitespace= --inaccurate-eof --verbose + " + return + esac +} + +_git_add () +{ + case "$cur" in + --*) + __gitcomp " + --interactive --refresh --patch --update --dry-run + --ignore-errors --intent-to-add + " + return + esac + + # XXX should we check for --update and --all options ? + __git_complete_index_file "--others --modified" +} + +_git_archive () +{ + case "$cur" in + --format=*) + __gitcomp "$(git archive --list)" "" "${cur##--format=}" + return + ;; + --remote=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--remote=}" + return + ;; + --*) + __gitcomp " + --format= --list --verbose + --prefix= --remote= --exec= + " + return + ;; + esac + __git_complete_file +} + +_git_bisect () +{ + __git_has_doubledash && return + + local subcommands="start bad good skip reset visualize replay log run" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + if [ -f "$(__gitdir)"/BISECT_START ]; then + __gitcomp "$subcommands" + else + __gitcomp "replay start" + fi + return + fi + + case "$subcommand" in + bad|good|reset|skip|start) + __gitcomp_nl "$(__git_refs)" + ;; + *) + ;; + esac +} + +_git_branch () +{ + local i c=1 only_local_ref="n" has_r="n" + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-m) only_local_ref="y" ;; + -r) has_r="y" ;; + esac + ((c++)) + done + + case "$cur" in + --set-upstream-to=*) + __gitcomp "$(__git_refs)" "" "${cur##--set-upstream-to=}" + ;; + --*) + __gitcomp " + --color --no-color --verbose --abbrev= --no-abbrev + --track --no-track --contains --merged --no-merged + --set-upstream-to= --edit-description --list + --unset-upstream + " + ;; + *) + if [ $only_local_ref = "y" -a $has_r = "n" ]; then + __gitcomp_nl "$(__git_heads)" + else + __gitcomp_nl "$(__git_refs)" + fi + ;; + esac +} + +_git_bundle () +{ + local cmd="${words[2]}" + case "$cword" in + 2) + __gitcomp "create list-heads verify unbundle" + ;; + 3) + # looking for a file + ;; + *) + case "$cmd" in + create) + __git_complete_revlist + ;; + esac + ;; + esac +} + +_git_checkout () +{ + __git_has_doubledash && return + + case "$cur" in + --conflict=*) + __gitcomp "diff3 merge" "" "${cur##--conflict=}" + ;; + --*) + __gitcomp " + --quiet --ours --theirs --track --no-track --merge + --conflict= --orphan --patch + " + ;; + *) + # check if --track, --no-track, or --no-guess was specified + # if so, disable DWIM mode + local flags="--track --no-track --no-guess" track=1 + if [ -n "$(__git_find_on_cmdline "$flags")" ]; then + track='' + fi + __gitcomp_nl "$(__git_refs '' $track)" + ;; + esac +} + +_git_cherry () +{ + __gitcomp "$(__git_refs)" +} + +_git_cherry_pick () +{ + local dir="$(__gitdir)" + if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __gitcomp "--continue --quit --abort" + return + fi + case "$cur" in + --*) + __gitcomp "--edit --no-commit --signoff --strategy= --mainline" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + +_git_clean () +{ + case "$cur" in + --*) + __gitcomp "--dry-run --quiet" + return + ;; + esac + + # XXX should we check for -x option ? + __git_complete_index_file "--others" +} + +_git_clone () +{ + case "$cur" in + --*) + __gitcomp " + --local + --no-hardlinks + --shared + --reference + --quiet + --no-checkout + --bare + --mirror + --origin + --upload-pack + --template= + --depth + --single-branch + --branch + " + return + ;; + esac +} + +_git_commit () +{ + case "$prev" in + -c|-C) + __gitcomp_nl "$(__git_refs)" "" "${cur}" + return + ;; + esac + + case "$cur" in + --cleanup=*) + __gitcomp "default strip verbatim whitespace + " "" "${cur##--cleanup=}" + return + ;; + --reuse-message=*|--reedit-message=*|\ + --fixup=*|--squash=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + return + ;; + --untracked-files=*) + __gitcomp "all no normal" "" "${cur##--untracked-files=}" + return + ;; + --*) + __gitcomp " + --all --author= --signoff --verify --no-verify + --edit --no-edit + --amend --include --only --interactive + --dry-run --reuse-message= --reedit-message= + --reset-author --file= --message= --template= + --cleanup= --untracked-files --untracked-files= + --verbose --quiet --fixup= --squash= + " + return + esac + + if git rev-parse --verify --quiet HEAD >/dev/null; then + __git_complete_index_file "--committable" + else + # This is the first commit + __git_complete_index_file "--cached" + fi +} + +_git_describe () +{ + case "$cur" in + --*) + __gitcomp " + --all --tags --contains --abbrev= --candidates= + --exact-match --debug --long --match --always + " + return + esac + __gitcomp_nl "$(__git_refs)" +} + +__git_diff_algorithms="myers minimal patience histogram" + +__git_diff_common_options="--stat --numstat --shortstat --summary + --patch-with-stat --name-only --name-status --color + --no-color --color-words --no-renames --check + --full-index --binary --abbrev --diff-filter= + --find-copies-harder + --text --ignore-space-at-eol --ignore-space-change + --ignore-all-space --exit-code --quiet --ext-diff + --no-ext-diff + --no-prefix --src-prefix= --dst-prefix= + --inter-hunk-context= + --patience --histogram --minimal + --raw --word-diff + --dirstat --dirstat= --dirstat-by-file + --dirstat-by-file= --cumulative + --diff-algorithm= +" + +_git_diff () +{ + __git_has_doubledash && return + + case "$cur" in + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs --no-index + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff + tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3 codecompare +" + +_git_difftool () +{ + __git_has_doubledash && return + + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs + --no-renames --diff-filter= --find-copies-harder + --relative --ignore-submodules + --tool=" + return + ;; + esac + __git_complete_revlist_file +} + +__git_fetch_options=" + --quiet --verbose --append --upload-pack --force --keep --depth= + --tags --no-tags --all --prune --dry-run +" + +_git_fetch () +{ + case "$cur" in + --*) + __gitcomp "$__git_fetch_options" + return + ;; + esac + __git_complete_remote_or_refspec +} + +__git_format_patch_options=" + --stdout --attach --no-attach --thread --thread= --no-thread + --numbered --start-number --numbered-files --keep-subject --signoff + --signature --no-signature --in-reply-to= --cc= --full-index --binary + --not --all --cover-letter --no-prefix --src-prefix= --dst-prefix= + --inline --suffix= --ignore-if-in-upstream --subject-prefix= + --output-directory --reroll-count --to= --quiet --notes +" + +_git_format_patch () +{ + case "$cur" in + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --*) + __gitcomp "$__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_fsck () +{ + case "$cur" in + --*) + __gitcomp " + --tags --root --unreachable --cache --no-reflogs --full + --strict --verbose --lost-found + " + return + ;; + esac +} + +_git_gc () +{ + case "$cur" in + --*) + __gitcomp "--prune --aggressive" + return + ;; + esac +} + +_git_gitk () +{ + _gitk +} + +__git_match_ctag() { + awk "/^${1////\\/}/ { print \$1 }" "$2" +} + +_git_grep () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + --cached + --text --ignore-case --word-regexp --invert-match + --full-name --line-number + --extended-regexp --basic-regexp --fixed-strings + --perl-regexp + --files-with-matches --name-only + --files-without-match + --max-depth + --count + --and --or --not --all-match + " + return + ;; + esac + + case "$cword,$prev" in + 2,*|*,-*) + if test -r tags; then + __gitcomp_nl "$(__git_match_ctag "$cur" tags)" + return + fi + ;; + esac + + __gitcomp_nl "$(__git_refs)" +} + +_git_help () +{ + case "$cur" in + --*) + __gitcomp "--all --info --man --web" + return + ;; + esac + __git_compute_all_commands + __gitcomp "$__git_all_commands $(__git_aliases) + attributes cli core-tutorial cvs-migration + diffcore gitk glossary hooks ignore modules + namespaces repository-layout tutorial tutorial-2 + workflows + " +} + +_git_init () +{ + case "$cur" in + --shared=*) + __gitcomp " + false true umask group all world everybody + " "" "${cur##--shared=}" + return + ;; + --*) + __gitcomp "--quiet --bare --template= --shared --shared=" + return + ;; + esac +} + +_git_ls_files () +{ + case "$cur" in + --*) + __gitcomp "--cached --deleted --modified --others --ignored + --stage --directory --no-empty-directory --unmerged + --killed --exclude= --exclude-from= + --exclude-per-directory= --exclude-standard + --error-unmatch --with-tree= --full-name + --abbrev --ignored --exclude-per-directory + " + return + ;; + esac + + # XXX ignore options like --modified and always suggest all cached + # files. + __git_complete_index_file "--cached" +} + +_git_ls_remote () +{ + __gitcomp_nl "$(__git_remotes)" +} + +_git_ls_tree () +{ + __git_complete_file +} + +# Options that go well for log, shortlog and gitk +__git_log_common_options=" + --not --all + --branches --tags --remotes + --first-parent --merges --no-merges + --max-count= + --max-age= --since= --after= + --min-age= --until= --before= + --min-parents= --max-parents= + --no-min-parents --no-max-parents +" +# Options that go well for log and gitk (not shortlog) +__git_log_gitk_options=" + --dense --sparse --full-history + --simplify-merges --simplify-by-decoration + --left-right --notes --no-notes +" +# Options that go well for log and shortlog (not gitk) +__git_log_shortlog_options=" + --author= --committer= --grep= + --all-match +" + +__git_log_pretty_formats="oneline short medium full fuller email raw format:" +__git_log_date_formats="relative iso8601 rfc2822 short local default raw" + +_git_log () +{ + __git_has_doubledash && return + + local g="$(git rev-parse --git-dir 2>/dev/null)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --date=*) + __gitcomp "$__git_log_date_formats" "" "${cur##--date=}" + return + ;; + --decorate=*) + __gitcomp "long short" "" "${cur##--decorate=}" + return + ;; + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + $__git_log_gitk_options + --root --topo-order --date-order --reverse + --follow --full-diff + --abbrev-commit --abbrev= + --relative-date --date= + --pretty= --format= --oneline + --cherry-pick + --graph + --decorate --decorate= + --walk-reflogs + --parents --children + $merge + $__git_diff_common_options + --pickaxe-all --pickaxe-regex + " + return + ;; + esac + __git_complete_revlist +} + +__git_merge_options=" + --no-commit --no-stat --log --no-log --squash --strategy + --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit +" + +_git_merge () +{ + __git_complete_strategy && return + + case "$cur" in + --*) + __gitcomp "$__git_merge_options" + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_mergetool () +{ + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--tool=" + return + ;; + esac +} + +_git_merge_base () +{ + __gitcomp_nl "$(__git_refs)" +} + +_git_mv () +{ + case "$cur" in + --*) + __gitcomp "--dry-run" + return + ;; + esac + + if [ $(__git_count_arguments "mv") -gt 0 ]; then + # We need to show both cached and untracked files (including + # empty directories) since this may not be the last argument. + __git_complete_index_file "--cached --others --directory" + else + __git_complete_index_file "--cached" + fi +} + +_git_name_rev () +{ + __gitcomp "--tags --all --stdin" +} + +_git_notes () +{ + local subcommands='add append copy edit list prune remove show' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + case "$subcommand,$cur" in + ,--*) + __gitcomp '--ref' + ;; + ,*) + case "$prev" in + --ref) + __gitcomp_nl "$(__git_refs)" + ;; + *) + __gitcomp "$subcommands --ref" + ;; + esac + ;; + add,--reuse-message=*|append,--reuse-message=*|\ + add,--reedit-message=*|append,--reedit-message=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + ;; + add,--*|append,--*) + __gitcomp '--file= --message= --reedit-message= + --reuse-message=' + ;; + copy,--*) + __gitcomp '--stdin' + ;; + prune,--*) + __gitcomp '--dry-run --verbose' + ;; + prune,*) + ;; + *) + case "$prev" in + -m|-F) + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac + ;; + esac +} + +_git_pull () +{ + __git_complete_strategy && return + + case "$cur" in + --*) + __gitcomp " + --rebase --no-rebase + $__git_merge_options + $__git_fetch_options + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +_git_push () +{ + case "$prev" in + --repo) + __gitcomp_nl "$(__git_remotes)" + return + esac + case "$cur" in + --repo=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}" + return + ;; + --*) + __gitcomp " + --all --mirror --tags --dry-run --force --verbose + --receive-pack= --repo= --set-upstream + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +_git_rebase () +{ + local dir="$(__gitdir)" + if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then + __gitcomp "--continue --skip --abort" + return + fi + __git_complete_strategy && return + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --onto --merge --strategy --interactive + --preserve-merges --stat --no-stat + --committer-date-is-author-date --ignore-date + --ignore-whitespace --whitespace= + --autosquash + " + + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_reflog () +{ + local subcommands="show delete expire" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + __gitcomp_nl "$(__git_refs)" + fi +} + +__git_send_email_confirm_options="always never auto cc compose" +__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all" + +_git_send_email () +{ + case "$cur" in + --confirm=*) + __gitcomp " + $__git_send_email_confirm_options + " "" "${cur##--confirm=}" + return + ;; + --suppress-cc=*) + __gitcomp " + $__git_send_email_suppresscc_options + " "" "${cur##--suppress-cc=}" + + return + ;; + --smtp-encryption=*) + __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}" + return + ;; + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --*) + __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to + --compose --confirm= --dry-run --envelope-sender + --from --identity + --in-reply-to --no-chain-reply-to --no-signed-off-by-cc + --no-suppress-from --no-thread --quiet + --signed-off-by-cc --smtp-pass --smtp-server + --smtp-server-port --smtp-encryption= --smtp-user + --subject --suppress-cc= --suppress-from --thread --to + --validate --no-validate + $__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_stage () +{ + _git_add +} + +__git_config_get_set_variables () +{ + local prevword word config_file= c=$cword + while [ $c -gt 1 ]; do + word="${words[c]}" + case "$word" in + --system|--global|--local|--file=*) + config_file="$word" + break + ;; + -f|--file) + config_file="$word $prevword" + break + ;; + esac + prevword=$word + c=$((--c)) + done + + git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null | + while read -r line + do + case "$line" in + *.*=*) + echo "${line/=*/}" + ;; + esac + done +} + +_git_config () +{ + case "$prev" in + branch.*.remote|branch.*.pushremote) + __gitcomp_nl "$(__git_remotes)" + return + ;; + branch.*.merge) + __gitcomp_nl "$(__git_refs)" + return + ;; + branch.*.rebase) + __gitcomp "false true" + return + ;; + remote.pushdefault) + __gitcomp_nl "$(__git_remotes)" + return + ;; + remote.*.fetch) + local remote="${prev#remote.}" + remote="${remote%.fetch}" + if [ -z "$cur" ]; then + __gitcomp_nl "refs/heads/" "" "" "" + return + fi + __gitcomp_nl "$(__git_refs_remotes "$remote")" + return + ;; + remote.*.push) + local remote="${prev#remote.}" + remote="${remote%.push}" + __gitcomp_nl "$(git --git-dir="$(__gitdir)" \ + for-each-ref --format='%(refname):%(refname)' \ + refs/heads)" + return + ;; + pull.twohead|pull.octopus) + __git_compute_merge_strategies + __gitcomp "$__git_merge_strategies" + return + ;; + color.branch|color.diff|color.interactive|\ + color.showbranch|color.status|color.ui) + __gitcomp "always never auto" + return + ;; + color.pager) + __gitcomp "false true" + return + ;; + color.*.*) + __gitcomp " + normal black red green yellow blue magenta cyan white + bold dim ul blink reverse + " + return + ;; + diff.submodule) + __gitcomp "log short" + return + ;; + help.format) + __gitcomp "man info web html" + return + ;; + log.date) + __gitcomp "$__git_log_date_formats" + return + ;; + sendemail.aliasesfiletype) + __gitcomp "mutt mailrc pine elm gnus" + return + ;; + sendemail.confirm) + __gitcomp "$__git_send_email_confirm_options" + return + ;; + sendemail.suppresscc) + __gitcomp "$__git_send_email_suppresscc_options" + return + ;; + --get|--get-all|--unset|--unset-all) + __gitcomp_nl "$(__git_config_get_set_variables)" + return + ;; + *.*) + return + ;; + esac + case "$cur" in + --*) + __gitcomp " + --system --global --local --file= + --list --replace-all + --get --get-all --get-regexp + --add --unset --unset-all + --remove-section --rename-section + " + return + ;; + branch.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_" + return + ;; + branch.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." + return + ;; + guitool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + argprompt cmd confirm needsfile noconsole norescan + prompt revprompt revunmerged title + " "$pfx" "$cur_" + return + ;; + difftool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + man.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + mergetool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path trustExitCode" "$pfx" "$cur_" + return + ;; + pager.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __git_compute_all_commands + __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" + return + ;; + remote.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + url proxy fetch push mirror skipDefaultUpdate + receivepack uploadpack tagopt pushurl + " "$pfx" "$cur_" + return + ;; + remote.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." + return + ;; + url.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_" + return + ;; + esac + __gitcomp " + add.ignoreErrors + advice.commitBeforeMerge + advice.detachedHead + advice.implicitIdentity + advice.pushNonFastForward + advice.resolveConflict + advice.statusHints + alias. + am.keepcr + apply.ignorewhitespace + apply.whitespace + branch.autosetupmerge + branch.autosetuprebase + browser. + clean.requireForce + color.branch + color.branch.current + color.branch.local + color.branch.plain + color.branch.remote + color.decorate.HEAD + color.decorate.branch + color.decorate.remoteBranch + color.decorate.stash + color.decorate.tag + color.diff + color.diff.commit + color.diff.frag + color.diff.func + color.diff.meta + color.diff.new + color.diff.old + color.diff.plain + color.diff.whitespace + color.grep + color.grep.context + color.grep.filename + color.grep.function + color.grep.linenumber + color.grep.match + color.grep.selected + color.grep.separator + color.interactive + color.interactive.error + color.interactive.header + color.interactive.help + color.interactive.prompt + color.pager + color.showbranch + color.status + color.status.added + color.status.changed + color.status.header + color.status.nobranch + color.status.untracked + color.status.updated + color.ui + commit.status + commit.template + core.abbrev + core.askpass + core.attributesfile + core.autocrlf + core.bare + core.bigFileThreshold + core.compression + core.createObject + core.deltaBaseCacheLimit + core.editor + core.eol + core.excludesfile + core.fileMode + core.fsyncobjectfiles + core.gitProxy + core.ignoreStat + core.ignorecase + core.logAllRefUpdates + core.loosecompression + core.notesRef + core.packedGitLimit + core.packedGitWindowSize + core.pager + core.preferSymlinkRefs + core.preloadindex + core.quotepath + core.repositoryFormatVersion + core.safecrlf + core.sharedRepository + core.sparseCheckout + core.symlinks + core.trustctime + core.warnAmbiguousRefs + core.whitespace + core.worktree + diff.autorefreshindex + diff.external + diff.ignoreSubmodules + diff.mnemonicprefix + diff.noprefix + diff.renameLimit + diff.renames + diff.statGraphWidth + diff.submodule + diff.suppressBlankEmpty + diff.tool + diff.wordRegex + diff.algorithm + difftool. + difftool.prompt + fetch.recurseSubmodules + fetch.unpackLimit + format.attach + format.cc + format.headers + format.numbered + format.pretty + format.signature + format.signoff + format.subjectprefix + format.suffix + format.thread + format.to + gc. + gc.aggressiveWindow + gc.auto + gc.autopacklimit + gc.packrefs + gc.pruneexpire + gc.reflogexpire + gc.reflogexpireunreachable + gc.rerereresolved + gc.rerereunresolved + gitcvs.allbinary + gitcvs.commitmsgannotation + gitcvs.dbTableNamePrefix + gitcvs.dbdriver + gitcvs.dbname + gitcvs.dbpass + gitcvs.dbuser + gitcvs.enabled + gitcvs.logfile + gitcvs.usecrlfattr + guitool. + gui.blamehistoryctx + gui.commitmsgwidth + gui.copyblamethreshold + gui.diffcontext + gui.encoding + gui.fastcopyblame + gui.matchtrackingbranch + gui.newbranchtemplate + gui.pruneduringfetch + gui.spellingdictionary + gui.trustmtime + help.autocorrect + help.browser + help.format + http.lowSpeedLimit + http.lowSpeedTime + http.maxRequests + http.minSessions + http.noEPSV + http.postBuffer + http.proxy + http.sslCAInfo + http.sslCAPath + http.sslCert + http.sslCertPasswordProtected + http.sslKey + http.sslVerify + http.useragent + i18n.commitEncoding + i18n.logOutputEncoding + imap.authMethod + imap.folder + imap.host + imap.pass + imap.port + imap.preformattedHTML + imap.sslverify + imap.tunnel + imap.user + init.templatedir + instaweb.browser + instaweb.httpd + instaweb.local + instaweb.modulepath + instaweb.port + interactive.singlekey + log.date + log.decorate + log.showroot + mailmap.file + man. + man.viewer + merge. + merge.conflictstyle + merge.log + merge.renameLimit + merge.renormalize + merge.stat + merge.tool + merge.verbosity + mergetool. + mergetool.keepBackup + mergetool.keepTemporaries + mergetool.prompt + notes.displayRef + notes.rewrite. + notes.rewrite.amend + notes.rewrite.rebase + notes.rewriteMode + notes.rewriteRef + pack.compression + pack.deltaCacheLimit + pack.deltaCacheSize + pack.depth + pack.indexVersion + pack.packSizeLimit + pack.threads + pack.window + pack.windowMemory + pager. + pretty. + pull.octopus + pull.twohead + push.default + rebase.autosquash + rebase.stat + receive.autogc + receive.denyCurrentBranch + receive.denyDeleteCurrent + receive.denyDeletes + receive.denyNonFastForwards + receive.fsckObjects + receive.unpackLimit + receive.updateserverinfo + remote.pushdefault + remotes. + repack.usedeltabaseoffset + rerere.autoupdate + rerere.enabled + sendemail. + sendemail.aliasesfile + sendemail.aliasfiletype + sendemail.bcc + sendemail.cc + sendemail.cccmd + sendemail.chainreplyto + sendemail.confirm + sendemail.envelopesender + sendemail.from + sendemail.identity + sendemail.multiedit + sendemail.signedoffbycc + sendemail.smtpdomain + sendemail.smtpencryption + sendemail.smtppass + sendemail.smtpserver + sendemail.smtpserveroption + sendemail.smtpserverport + sendemail.smtpuser + sendemail.suppresscc + sendemail.suppressfrom + sendemail.thread + sendemail.to + sendemail.validate + showbranch.default + status.relativePaths + status.showUntrackedFiles + status.submodulesummary + submodule. + tar.umask + transfer.unpackLimit + url. + user.email + user.name + user.signingkey + web.browser + branch. remote. + " +} + +_git_remote () +{ + local subcommands="add rename remove set-head set-branches set-url show prune update" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + rename|remove|set-url|show|prune) + __gitcomp_nl "$(__git_remotes)" + ;; + set-head|set-branches) + __git_complete_remote_or_refspec + ;; + update) + local i c='' IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do + i="${i#remotes.}" + c="$c ${i/ */}" + done + __gitcomp "$c" + ;; + *) + ;; + esac +} + +_git_replace () +{ + __gitcomp_nl "$(__git_refs)" +} + +_git_reset () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp "--merge --mixed --hard --soft --patch" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_revert () +{ + case "$cur" in + --*) + __gitcomp "--edit --mainline --no-edit --no-commit --signoff" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_rm () +{ + case "$cur" in + --*) + __gitcomp "--cached --dry-run --ignore-unmatch --quiet" + return + ;; + esac + + __git_complete_index_file "--cached" +} + +_git_shortlog () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + --numbered --summary + " + return + ;; + esac + __git_complete_revlist +} + +_git_show () +{ + __git_has_doubledash && return + + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--pretty= --format= --abbrev-commit --oneline + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +_git_show_branch () +{ + case "$cur" in + --*) + __gitcomp " + --all --remotes --topo-order --current --more= + --list --independent --merge-base --no-name + --color --no-color + --sha1-name --sparse --topics --reflog + " + return + ;; + esac + __git_complete_revlist +} + +_git_stash () +{ + local save_opts='--keep-index --no-keep-index --quiet --patch' + local subcommands='save list show apply clear drop pop create branch' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + case "$cur" in + --*) + __gitcomp "$save_opts" + ;; + *) + if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then + __gitcomp "$subcommands" + fi + ;; + esac + else + case "$subcommand,$cur" in + save,--*) + __gitcomp "$save_opts" + ;; + apply,--*|pop,--*) + __gitcomp "--index --quiet" + ;; + show,--*|drop,--*|branch,--*) + ;; + show,*|apply,*|drop,*|pop,*|branch,*) + __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + | sed -n -e 's/:.*//p')" + ;; + *) + ;; + esac + fi +} + +_git_submodule () +{ + __git_has_doubledash && return + + local subcommands="add status init deinit update summary foreach sync" + if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then + case "$cur" in + --*) + __gitcomp "--quiet --cached" + ;; + *) + __gitcomp "$subcommands" + ;; + esac + return + fi +} + +_git_svn () +{ + local subcommands=" + init fetch clone rebase dcommit log find-rev + set-tree commit-diff info create-ignore propget + proplist show-ignore show-externals branch tag blame + migrate mkdirs reset gc + " + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + local remote_opts="--username= --config-dir= --no-auth-cache" + local fc_opts=" + --follow-parent --authors-file= --repack= + --no-metadata --use-svm-props --use-svnsync-props + --log-window-size= --no-checkout --quiet + --repack-flags --use-log-author --localtime + --ignore-paths= --include-paths= $remote_opts + " + local init_opts=" + --template= --shared= --trunk= --tags= + --branches= --stdlayout --minimize-url + --no-metadata --use-svm-props --use-svnsync-props + --rewrite-root= --prefix= --use-log-author + --add-author-from $remote_opts + " + local cmt_opts=" + --edit --rmdir --find-copies-harder --copy-similarity= + " + + case "$subcommand,$cur" in + fetch,--*) + __gitcomp "--revision= --fetch-all $fc_opts" + ;; + clone,--*) + __gitcomp "--revision= $fc_opts $init_opts" + ;; + init,--*) + __gitcomp "$init_opts" + ;; + dcommit,--*) + __gitcomp " + --merge --strategy= --verbose --dry-run + --fetch-all --no-rebase --commit-url + --revision --interactive $cmt_opts $fc_opts + " + ;; + set-tree,--*) + __gitcomp "--stdin $cmt_opts $fc_opts" + ;; + create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\ + show-externals,--*|mkdirs,--*) + __gitcomp "--revision=" + ;; + log,--*) + __gitcomp " + --limit= --revision= --verbose --incremental + --oneline --show-commit --non-recursive + --authors-file= --color + " + ;; + rebase,--*) + __gitcomp " + --merge --verbose --strategy= --local + --fetch-all --dry-run $fc_opts + " + ;; + commit-diff,--*) + __gitcomp "--message= --file= --revision= $cmt_opts" + ;; + info,--*) + __gitcomp "--url" + ;; + branch,--*) + __gitcomp "--dry-run --message --tag" + ;; + tag,--*) + __gitcomp "--dry-run --message" + ;; + blame,--*) + __gitcomp "--git-format" + ;; + migrate,--*) + __gitcomp " + --config-dir= --ignore-paths= --minimize + --no-auth-cache --username= + " + ;; + reset,--*) + __gitcomp "--revision= --parent" + ;; + *) + ;; + esac + fi +} + +_git_tag () +{ + local i c=1 f=0 + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-v) + __gitcomp_nl "$(__git_tags)" + return + ;; + -f) + f=1 + ;; + esac + ((c++)) + done + + case "$prev" in + -m|-F) + ;; + -*|tag) + if [ $f = 1 ]; then + __gitcomp_nl "$(__git_tags)" + fi + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + +_git_whatchanged () +{ + _git_log +} + +__git_main () +{ + local i c=1 command __git_dir + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --git-dir=*) __git_dir="${i#--git-dir=}" ;; + --git-dir) ((c++)) ; __git_dir="${words[c]}" ;; + --bare) __git_dir="." ;; + --help) command="help"; break ;; + -c|--work-tree|--namespace) ((c++)) ;; + -*) ;; + *) command="$i"; break ;; + esac + ((c++)) + done + + if [ -z "$command" ]; then + case "$cur" in + --*) __gitcomp " + --paginate + --no-pager + --git-dir= + --bare + --version + --exec-path + --exec-path= + --html-path + --man-path + --info-path + --work-tree= + --namespace= + --no-replace-objects + --help + " + ;; + *) __git_compute_porcelain_commands + __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;; + esac + return + fi + + local completion_func="_git_${command//-/_}" + declare -f $completion_func >/dev/null && $completion_func && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + completion_func="_git_${expansion//-/_}" + declare -f $completion_func >/dev/null && $completion_func + fi +} + +__gitk_main () +{ + __git_has_doubledash && return + + local g="$(__gitdir)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_gitk_options + $merge + " + return + ;; + esac + __git_complete_revlist +} + +if [[ -n ${ZSH_VERSION-} ]]; then + echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2 + + autoload -U +X compinit && compinit + + __gitcomp () + { + emulate -L zsh + + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c IFS=$' \t\n' + local -a array + for c in ${=1}; do + c="$c${4-}" + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + array[$#array+1]="$c" + done + compset -P '*[=:]' + compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 + ;; + esac + } + + __gitcomp_nl () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 + } + + __gitcomp_file () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 + } + + _git () + { + local _ret=1 cur cword prev + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + emulate ksh -c __${service}_main + let _ret && _default && _ret=0 + return _ret + } + + compdef _git git gitk + return +fi + +__git_func_wrap () +{ + local cur words cword prev + _get_comp_words_by_ref -n =: cur words cword prev + $1 +} + +# Setup completion for certain functions defined above by setting common +# variables and workarounds. +# This is NOT a public function; use at your own risk. +__git_complete () +{ + local wrapper="__git_wrap${2}" + eval "$wrapper () { __git_func_wrap $2 ; }" + complete -o bashdefault -o default -o nospace -F $wrapper $1 2>/dev/null \ + || complete -o default -o nospace -F $wrapper $1 +} + +# wrapper for backwards compatibility +_git () +{ + __git_wrap__git_main +} + +# wrapper for backwards compatibility +_gitk () +{ + __git_wrap__gitk_main +} + +__git_complete git __git_main +__git_complete gitk __gitk_main + +# The following are necessary only for Cygwin, and only are needed +# when the user has tab-completed the executable name and consequently +# included the '.exe' suffix. +# +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then +__git_complete git.exe __git_main +fi diff --git a/paddle/scripts/docker/root/.scripts/git-prompt.sh b/paddle/scripts/docker/root/.scripts/git-prompt.sh new file mode 100755 index 0000000000000..576f4ec14c94a --- /dev/null +++ b/paddle/scripts/docker/root/.scripts/git-prompt.sh @@ -0,0 +1,445 @@ +# bash/zsh git prompt support +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Distributed under the GNU General Public License, version 2.0. +# +# This script allows you to see repository status in your prompt. +# +# To enable: +# +# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-prompt.sh +# 3a) Change your PS1 to call __git_ps1 as +# command-substitution: +# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' +# ZSH: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' +# the optional argument will be used as format string. +# 3b) Alternatively, for a slightly faster prompt, __git_ps1 can +# be used for PROMPT_COMMAND in Bash or for precmd() in Zsh +# with two parameters,
 and , which are strings
+#        you would put in $PS1 before and after the status string
+#        generated by the git-prompt machinery.  e.g.
+#        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#          will show username, at-sign, host, colon, cwd, then
+#          various status string, followed by dollar and SP, as
+#          your prompt.
+#        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
+#          will show username, pipe, then various status string,
+#          followed by colon, cwd, dollar and SP, as your prompt.
+#        Optionally, you can supply a third argument with a printf
+#        format string to finetune the output of the branch status
+#
+# The repository status will be displayed only if you are currently in a
+# git repository. The %s token is the placeholder for the shown status.
+#
+# The prompt status always includes the current branch name.
+#
+# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
+# unstaged (*) and staged (+) changes will be shown next to the branch
+# name.  You can configure this per-repository with the
+# bash.showDirtyState variable, which defaults to true once
+# GIT_PS1_SHOWDIRTYSTATE is enabled.
+#
+# You can also see if currently something is stashed, by setting
+# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+# then a '$' will be shown next to the branch name.
+#
+# If you would like to see if there're untracked files, then you can set
+# GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
+# files, then a '%' will be shown next to the branch name.  You can
+# configure this per-repository with the bash.showUntrackedFiles
+# variable, which defaults to true once GIT_PS1_SHOWUNTRACKEDFILES is
+# enabled.
+#
+# If you would like to see the difference between HEAD and its upstream,
+# set GIT_PS1_SHOWUPSTREAM="auto".  A "<" indicates you are behind, ">"
+# indicates you are ahead, "<>" indicates you have diverged and "="
+# indicates that there is no difference. You can further control
+# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
+# of values:
+#
+#     verbose       show number of commits ahead/behind (+/-) upstream
+#     legacy        don't use the '--count' option available in recent
+#                   versions of git-rev-list
+#     git           always compare HEAD to @{upstream}
+#     svn           always compare HEAD to your SVN upstream
+#
+# By default, __git_ps1 will compare HEAD to your SVN upstream if it can
+# find one, or @{upstream} otherwise.  Once you have set
+# GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
+# setting the bash.showUpstream config variable.
+#
+# If you would like to see more information about the identity of
+# commits checked out as a detached HEAD, set GIT_PS1_DESCRIBE_STYLE
+# to one of these values:
+#
+#     contains      relative to newer annotated tag (v1.6.3.2~35)
+#     branch        relative to newer tag or branch (master~4)
+#     describe      relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
+#     default       exactly matching tag
+#
+# If you would like a colored hint about the current dirty state, set
+# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
+# the colored output of "git status -sb" and are available only when
+# using __git_ps1 for PROMPT_COMMAND or precmd.
+
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+  local key value
+  local svn_remote svn_url_pattern count n
+  local upstream=git legacy="" verbose=""
+
+  svn_remote=()
+  # get some config options from git-config
+  local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+  while read -r key value; do
+    case "$key" in
+    bash.showupstream)
+      GIT_PS1_SHOWUPSTREAM="$value"
+      if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+        p=""
+        return
+      fi
+      ;;
+    svn-remote.*.url)
+      svn_remote[$((${#svn_remote[@]} + 1))]="$value"
+      svn_url_pattern+="\\|$value"
+      upstream=svn+git # default upstream is SVN if available, else git
+      ;;
+    esac
+  done <<< "$output"
+
+  # parse configuration values
+  for option in ${GIT_PS1_SHOWUPSTREAM}; do
+    case "$option" in
+    git|svn) upstream="$option" ;;
+    verbose) verbose=1 ;;
+    legacy)  legacy=1  ;;
+    esac
+  done
+
+  # Find our upstream
+  case "$upstream" in
+  git)    upstream="@{upstream}" ;;
+  svn*)
+    # get the upstream from the "git-svn-id: ..." in a commit message
+    # (git-svn uses essentially the same procedure internally)
+    local -a svn_upstream
+    svn_upstream=($(git log --first-parent -1 \
+          --grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
+    if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+      svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}
+      svn_upstream=${svn_upstream%@*}
+      local n_stop="${#svn_remote[@]}"
+      for ((n=1; n <= n_stop; n++)); do
+        svn_upstream=${svn_upstream#${svn_remote[$n]}}
+      done
+
+      if [[ -z "$svn_upstream" ]]; then
+        # default branch name for checkouts with no layout:
+        upstream=${GIT_SVN_ID:-git-svn}
+      else
+        upstream=${svn_upstream#/}
+      fi
+    elif [[ "svn+git" = "$upstream" ]]; then
+      upstream="@{upstream}"
+    fi
+    ;;
+  esac
+
+  # Find how many commits we are ahead/behind our upstream
+  if [[ -z "$legacy" ]]; then
+    count="$(git rev-list --count --left-right \
+        "$upstream"...HEAD 2>/dev/null)"
+  else
+    # produce equivalent output to --count for older versions of git
+    local commits
+    if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+    then
+      local commit behind=0 ahead=0
+      for commit in $commits
+      do
+        case "$commit" in
+        "<"*) ((behind++)) ;;
+        *)    ((ahead++))  ;;
+        esac
+      done
+      count="$behind  $ahead"
+    else
+      count=""
+    fi
+  fi
+
+  # calculate the result
+  if [[ -z "$verbose" ]]; then
+    case "$count" in
+    "") # no upstream
+      p="" ;;
+    "0  0") # equal to upstream
+      p="=" ;;
+    "0  "*) # ahead of upstream
+      p=">" ;;
+    *"  0") # behind upstream
+      p="<" ;;
+    *)      # diverged from upstream
+      p="<>" ;;
+    esac
+  else
+    case "$count" in
+    "") # no upstream
+      p="" ;;
+    "0  0") # equal to upstream
+      p=" u=" ;;
+    "0  "*) # ahead of upstream
+      p=" u+${count#0 }" ;;
+    *"  0") # behind upstream
+      p=" u-${count%  0}" ;;
+    *)      # diverged from upstream
+      p=" u+${count#* }-${count%  *}" ;;
+    esac
+  fi
+
+}
+
+# Helper function that is meant to be called from __git_ps1.  It
+# injects color codes into the appropriate gitstring variables used
+# to build a gitstring.
+__git_ps1_colorize_gitstring ()
+{
+  if [[ -n ${ZSH_VERSION-} ]]; then
+    local c_red='%F{red}'
+    local c_green='%F{green}'
+    local c_lblue='%F{blue}'
+    local c_clear='%f'
+  else
+    # Using \[ and \] around colors is necessary to prevent
+    # issues with command line editing/browsing/completion!
+    local c_red='\[\e[31m\]'
+    local c_green='\[\e[32m\]'
+    local c_lblue='\[\e[1;34m\]'
+    local c_clear='\[\e[0m\]'
+  fi
+  local bad_color=$c_red
+  local ok_color=$c_green
+  local flags_color="$c_lblue"
+
+  local branch_color=""
+  if [ $detached = no ]; then
+    branch_color="$ok_color"
+  else
+    branch_color="$bad_color"
+  fi
+  c="$branch_color$c"
+
+  z="$c_clear$z"
+  if [ "$w" = "*" ]; then
+    w="$bad_color$w"
+  fi
+  if [ -n "$i" ]; then
+    i="$ok_color$i"
+  fi
+  if [ -n "$s" ]; then
+    s="$flags_color$s"
+  fi
+  if [ -n "$u" ]; then
+    u="$bad_color$u"
+  fi
+  r="$c_clear$r"
+}
+
+# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
+# when called from PS1 using command substitution
+# in this mode it prints text to add to bash PS1 prompt (includes branch name)
+#
+# __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
+# in that case it _sets_ PS1. The arguments are parts of a PS1 string.
+# when two arguments are given, the first is prepended and the second appended
+# to the state string when assigned to PS1.
+# The optional third parameter will be used as printf format string to further
+# customize the output of the git-status string.
+# In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
+__git_ps1 ()
+{
+  local pcmode=no
+  local detached=no
+  local ps1pc_start='\u@\h:\w '
+  local ps1pc_end='\$ '
+  local printf_format=' (%s)'
+
+  case "$#" in
+    2|3)  pcmode=yes
+      ps1pc_start="$1"
+      ps1pc_end="$2"
+      printf_format="${3:-$printf_format}"
+    ;;
+    0|1)  printf_format="${1:-$printf_format}"
+    ;;
+    *)  return
+    ;;
+  esac
+
+  local repo_info rev_parse_exit_code
+  repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+    --is-bare-repository --is-inside-work-tree \
+    --short HEAD 2>/dev/null)"
+  rev_parse_exit_code="$?"
+
+  if [ -z "$repo_info" ]; then
+    if [ $pcmode = yes ]; then
+      #In PC mode PS1 always needs to be set
+      PS1="$ps1pc_start$ps1pc_end"
+    fi
+    return
+  fi
+
+  local short_sha
+  if [ "$rev_parse_exit_code" = "0" ]; then
+    short_sha="${repo_info##*$'\n'}"
+    repo_info="${repo_info%$'\n'*}"
+  fi
+  local inside_worktree="${repo_info##*$'\n'}"
+  repo_info="${repo_info%$'\n'*}"
+  local bare_repo="${repo_info##*$'\n'}"
+  repo_info="${repo_info%$'\n'*}"
+  local inside_gitdir="${repo_info##*$'\n'}"
+  local g="${repo_info%$'\n'*}"
+
+  local r=""
+  local b=""
+  local step=""
+  local total=""
+  if [ -d "$g/rebase-merge" ]; then
+    read b 2>/dev/null <"$g/rebase-merge/head-name"
+    read step 2>/dev/null <"$g/rebase-merge/msgnum"
+    read total 2>/dev/null <"$g/rebase-merge/end"
+    if [ -f "$g/rebase-merge/interactive" ]; then
+      r="|REBASE-i"
+    else
+      r="|REBASE-m"
+    fi
+  else
+    if [ -d "$g/rebase-apply" ]; then
+      read step 2>/dev/null <"$g/rebase-apply/next"
+      read total 2>/dev/null <"$g/rebase-apply/last"
+      if [ -f "$g/rebase-apply/rebasing" ]; then
+        read b 2>/dev/null <"$g/rebase-apply/head-name"
+        r="|REBASE"
+      elif [ -f "$g/rebase-apply/applying" ]; then
+        r="|AM"
+      else
+        r="|AM/REBASE"
+      fi
+    elif [ -f "$g/MERGE_HEAD" ]; then
+      r="|MERGING"
+    elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+      r="|CHERRY-PICKING"
+    elif [ -f "$g/REVERT_HEAD" ]; then
+      r="|REVERTING"
+    elif [ -f "$g/BISECT_LOG" ]; then
+      r="|BISECTING"
+    fi
+
+    if [ -n "$b" ]; then
+      :
+    elif [ -h "$g/HEAD" ]; then
+      # symlink symbolic ref
+      b="$(git symbolic-ref HEAD 2>/dev/null)"
+    else
+      local head=""
+      if ! read head 2>/dev/null <"$g/HEAD"; then
+        if [ $pcmode = yes ]; then
+          PS1="$ps1pc_start$ps1pc_end"
+        fi
+        return
+      fi
+      # is it a symbolic ref?
+      b="${head#ref: }"
+      if [ "$head" = "$b" ]; then
+        detached=yes
+        b="$(
+        case "${GIT_PS1_DESCRIBE_STYLE-}" in
+        (contains)
+          git describe --contains HEAD ;;
+        (branch)
+          git describe --contains --all HEAD ;;
+        (describe)
+          git describe HEAD ;;
+        (* | default)
+          git describe --tags --exact-match HEAD ;;
+        esac 2>/dev/null)" ||
+
+        b="$short_sha..."
+        b="($b)"
+      fi
+    fi
+  fi
+
+  if [ -n "$step" ] && [ -n "$total" ]; then
+    r="$r $step/$total"
+  fi
+
+  local w=""
+  local i=""
+  local s=""
+  local u=""
+  local c=""
+  local p=""
+
+  if [ "true" = "$inside_gitdir" ]; then
+    if [ "true" = "$bare_repo" ]; then
+      c="BARE:"
+    else
+      b="GIT_DIR!"
+    fi
+  elif [ "true" = "$inside_worktree" ]; then
+    if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+       [ "$(git config --bool bash.showDirtyState)" != "false" ]
+    then
+      git diff --no-ext-diff --quiet --exit-code || w="*"
+      if [ -n "$short_sha" ]; then
+        git diff-index --cached --quiet HEAD -- || i="+"
+      else
+        i="#"
+      fi
+    fi
+    if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
+       [ -r "$g/refs/stash" ]; then
+      s="$"
+    fi
+
+    if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+       [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+       git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
+    then
+      u="%${ZSH_VERSION+%}"
+    fi
+
+    if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+      __git_ps1_show_upstream
+    fi
+  fi
+
+  local z="${GIT_PS1_STATESEPARATOR-" "}"
+
+  # NO color option unless in PROMPT_COMMAND mode
+  if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+    __git_ps1_colorize_gitstring
+  fi
+
+  local f="$w$i$s$u"
+  local gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
+
+  if [ $pcmode = yes ]; then
+    if [[ -n ${ZSH_VERSION-} ]]; then
+      gitstring=$(printf -- "$printf_format" "$gitstring")
+    else
+      printf -v gitstring -- "$printf_format" "$gitstring"
+    fi
+    PS1="$ps1pc_start$gitstring$ps1pc_end"
+  else
+    printf -- "$printf_format" "$gitstring"
+  fi
+}

From f6a481edaa2d00be1243b24801d834927fb7072f Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 12:48:39 +0800
Subject: [PATCH 018/153] Add .bashrc into docker

---
 paddle/scripts/docker/Dockerfile | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile
index 27423faef47de..ea1d8aba361d2 100644
--- a/paddle/scripts/docker/Dockerfile
+++ b/paddle/scripts/docker/Dockerfile
@@ -22,9 +22,7 @@ ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF}
 ENV HOME /root
 
 # Add bash enhancements
-ADD root/.bashrc /root/.bashrc
-ADD root/.gitconfig /root/.gitconfig
-ADD root/.scripts /root/.scripts
+COPY ./paddle/scripts/docker/root/ /root/
 
 RUN apt-get update && \
     apt-get install -y git python-pip python-dev openssh-server bison && \

From f7ecd312c5a56c48eeafd63fb168f106ad973e66 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 12:49:35 +0800
Subject: [PATCH 019/153] update event handler

---
 demo/image_classification/train_v2_vgg.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/demo/image_classification/train_v2_vgg.py b/demo/image_classification/train_v2_vgg.py
index 33b53b27daf4b..25bfd798ebf82 100644
--- a/demo/image_classification/train_v2_vgg.py
+++ b/demo/image_classification/train_v2_vgg.py
@@ -6,8 +6,6 @@ def event_handler(event):
         if event.batch_id % 100 == 0:
             print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id,
                                                   event.cost)
-    else:
-        pass
 
 
 def vgg_bn_drop(input):

From d227f4479e5d9b58c45059871c5cd4e221b1a05f Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 15:06:24 +0800
Subject: [PATCH 020/153] Add resnet

---
 demo/image_classification/train_v2_resnet.py | 158 +++++++++++++++++++
 demo/image_classification/train_v2_vgg.py    |  16 +-
 2 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 demo/image_classification/train_v2_resnet.py

diff --git a/demo/image_classification/train_v2_resnet.py b/demo/image_classification/train_v2_resnet.py
new file mode 100644
index 0000000000000..fdfa87cd8755e
--- /dev/null
+++ b/demo/image_classification/train_v2_resnet.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import paddle.v2 as paddle
+
+
+def event_handler(event):
+    if isinstance(event, paddle.event.EndIteration):
+        if event.batch_id % 100 == 0:
+            print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id,
+                                                  event.cost)
+
+
+def conv_bn_layer(input,
+                  ch_out,
+                  filter_size,
+                  stride,
+                  padding,
+                  active_type=paddle.activation.Relu(),
+                  ch_in=None):
+    tmp = paddle.layer.img_conv(
+        input=input,
+        filter_size=filter_size,
+        num_channels=ch_in,
+        num_filters=ch_out,
+        stride=stride,
+        padding=padding,
+        act=paddle.activation.Linear(),
+        bias_attr=False)
+    return paddle.layer.batch_norm(input=tmp, act=active_type)
+
+
+def shortcut(ipt, n_in, n_out, stride):
+    if n_in != n_out:
+        print("n_in != n_out")
+        return conv_bn_layer(ipt, n_out, 1, stride, 0,
+                             paddle.activation.Linear())
+    else:
+        return ipt
+
+
+def basicblock(ipt, ch_out, stride):
+    ch_in = ipt.num_filters
+    tmp = conv_bn_layer(ipt, ch_out, 3, stride, 1)
+    tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1, paddle.activation.Linear())
+    short = shortcut(ipt, ch_in, ch_out, stride)
+    return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())
+
+
+def bottleneck(ipt, ch_out, stride):
+    ch_in = ipt.num_filter
+    tmp = conv_bn_layer(ipt, ch_out, 1, stride, 0)
+    tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1)
+    tmp = conv_bn_layer(tmp, ch_out * 4, 1, 1, 0, paddle.activation.Linear())
+    short = shortcut(ipt, ch_in, ch_out * 4, stride)
+    return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())
+
+
+def layer_warp(block_func, ipt, features, count, stride):
+    tmp = block_func(ipt, features, stride)
+    for i in range(1, count):
+        tmp = block_func(tmp, features, 1)
+    return tmp
+
+
+def resnet_imagenet(ipt, depth=50):
+    cfg = {
+        18: ([2, 2, 2, 1], basicblock),
+        34: ([3, 4, 6, 3], basicblock),
+        50: ([3, 4, 6, 3], bottleneck),
+        101: ([3, 4, 23, 3], bottleneck),
+        152: ([3, 8, 36, 3], bottleneck)
+    }
+    stages, block_func = cfg[depth]
+    tmp = conv_bn_layer(
+        ipt, ch_in=3, ch_out=64, filter_size=7, stride=2, padding=3)
+    tmp = paddle.layer.img_pool(input=tmp, pool_size=3, stride=2)
+    tmp = layer_warp(block_func, tmp, 64, stages[0], 1)
+    tmp = layer_warp(block_func, tmp, 128, stages[1], 2)
+    tmp = layer_warp(block_func, tmp, 256, stages[2], 2)
+    tmp = layer_warp(block_func, tmp, 512, stages[3], 2)
+    tmp = paddle.layer.img_pool(
+        input=tmp, pool_size=7, stride=1, pool_type=paddle.pooling.Avg())
+
+    tmp = paddle.layer.fc(input=tmp, size=1000, act=paddle.activation.Softmax())
+    return tmp
+
+
+def resnet_cifar10(ipt, depth=32):
+    # depth should be one of 20, 32, 44, 56, 110, 1202
+    assert (depth - 2) % 6 == 0
+    n = (depth - 2) / 6
+    nStages = {16, 64, 128}
+    conv1 = conv_bn_layer(
+        ipt, ch_in=3, ch_out=16, filter_size=3, stride=1, padding=1)
+    res1 = layer_warp(basicblock, conv1, 16, n, 1)
+    res2 = layer_warp(basicblock, res1, 32, n, 2)
+    res3 = layer_warp(basicblock, res2, 64, n, 2)
+    pool = paddle.layer.img_pool(
+        input=res3, pool_size=8, stride=1, pool_type=paddle.pooling.Avg())
+    return pool
+
+
+def main():
+    datadim = 3 * 32 * 32
+    classdim = 10
+
+    paddle.init(use_gpu=False, trainer_count=1)
+
+    image = paddle.layer.data(
+        name="image", type=paddle.data_type.dense_vector(datadim))
+    net = resnet_cifar10(image, depth=32)
+    out = paddle.layer.fc(input=net,
+                          size=classdim,
+                          act=paddle.activation.Softmax())
+
+    lbl = paddle.layer.data(
+        name="label", type=paddle.data_type.integer_value(classdim))
+    cost = paddle.layer.classification_cost(input=out, label=lbl)
+
+    parameters = paddle.parameters.create(cost)
+
+    momentum_optimizer = paddle.optimizer.Momentum(
+        momentum=0.9,
+        regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
+        learning_rate=0.1 / 128.0,
+        learning_rate_decay_a=0.1,
+        learning_rate_decay_b=50000 * 100,
+        learning_rate_schedule='discexp',
+        batch_size=128)
+
+    trainer = paddle.trainer.SGD(update_equation=momentum_optimizer)
+    trainer.train(
+        reader=paddle.reader.batched(
+            paddle.reader.shuffle(
+                paddle.dataset.cifar.train10(), buf_size=3072),
+            batch_size=128),
+        cost=cost,
+        num_passes=1,
+        parameters=parameters,
+        event_handler=event_handler,
+        reader_dict={'image': 0,
+                     'label': 1}, )
+
+
+if __name__ == '__main__':
+    main()
diff --git a/demo/image_classification/train_v2_vgg.py b/demo/image_classification/train_v2_vgg.py
index 25bfd798ebf82..5656ac85c6125 100644
--- a/demo/image_classification/train_v2_vgg.py
+++ b/demo/image_classification/train_v2_vgg.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2 as paddle
 
 
@@ -20,7 +34,7 @@ def conv_block(ipt, num_filter, groups, dropouts, num_channels=None):
             conv_act=paddle.activation.Relu(),
             conv_with_batchnorm=True,
             conv_batchnorm_drop_rate=dropouts,
-            pool_type=pooling.Max())
+            pool_type=paddle.pooling.Max())
 
     conv1 = conv_block(input, 64, 2, [0.3, 0], 3)
     conv2 = conv_block(conv1, 128, 2, [0.4, 0])

From 73af1942c8fcf89fffa0a13b7d8fdc6cdcdcb815 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Wed, 1 Mar 2017 15:54:46 +0800
Subject: [PATCH 021/153] add the implementation of rnn by yuyang

---
 .../paddle/trainer_config_helpers/layers.py   |   2 +-
 python/paddle/v2/layer.py                     | 151 +++++++++++-------
 2 files changed, 97 insertions(+), 56 deletions(-)

diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py
index 250878cbe1159..dcb39784a5412 100755
--- a/python/paddle/trainer_config_helpers/layers.py
+++ b/python/paddle/trainer_config_helpers/layers.py
@@ -822,7 +822,7 @@ def data_layer(name, size, height=None, width=None, layer_attr=None):
     return LayerOutput(name, LayerType.DATA, size=size)
 
 
-@wrap_name_default("embedding")
+@wrap_name_default("embedding_layer")
 @wrap_param_attr_default()
 @layer_support(ERROR_CLIPPING)
 def embedding_layer(input, size, name=None, param_attr=None, layer_attr=None):
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index 4f6c71664a8be..71d0e54c0a6f8 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -76,6 +76,9 @@ class for each layer creation function in paddle.trainer_config_helpers.layers.
     wrap_bias_attr_default
 from paddle.trainer_config_helpers.default_decorators import wrap_name_default
 from paddle.trainer_config_helpers.layers import layer_support
+from paddle.trainer.config_parser import \
+    RecurrentLayerGroupWithoutOutLinksBegin, RecurrentLayerGroupSetOutLink, \
+    RecurrentLayerGroupEnd, model_type
 
 import activation
 import data_type
@@ -126,21 +129,28 @@ def to_proto(self, context):
                                self.__parent_layers__[layer_name])
             kwargs[layer_name] = v1_layer
 
-        if self.name is None:
+        if self.context_name() is None:
             return self.to_proto_impl(**kwargs)
         elif isinstance(self, MemoryV2):
             name = self.name + "#__memory__"
             if name not in context:
                 context[name] = self.to_proto_impl(**kwargs)
             return context[name]
-
-        if self.name not in context:
-            context[self.name] = self.to_proto_impl(**kwargs)
+        elif self.context_name() not in context:
+            context[self.context_name()] = self.to_proto_impl(**kwargs)
         return context[self.name]
 
     def to_proto_impl(self, **kwargs):
         raise NotImplementedError()
 
+    def context_name(self):
+        """
+        Context name means the context which stores `to_proto_impl` result.
+        If multiple layer share same context_name, the `to_proto_impl` of them
+        will be invoked only once.
+        """
+        return self.name
+
 
 def __convert_to_v2__(method_name, parent_names, is_default_name=True):
     if is_default_name:
@@ -231,6 +241,9 @@ def to_proto_impl(self, **kwargs):
 
         return conf_helps.memory(name=self.name, size=self.size, **args)
 
+    def context_name(self):
+        return self.name + "#memory"
+
 
 class LayerOutputV2(Layer):
     """
@@ -249,60 +262,20 @@ def to_proto_impl(self):
 
 
 class StaticInputV2(Layer):
-    def __init__(self, **kwargs):
-        self.__parent_names__ = ['input']
-        other_kwargs = dict()
-        parent_layers = dict()
-        for pname in self.__parent_names__:
-            if kwargs.has_key(pname):
-                parent_layers[pname] = kwargs[pname]
-        for key in kwargs.keys():
-            if key not in self.__parent_names__:
-                other_kwargs[key] = kwargs[key]
-        self.__kwargs__ = other_kwargs
-        super(StaticInputV2, self).__init__(parent_layers=parent_layers)
-
-    def to_proto_impl(self, **kwargs):
-        args = dict()
-        for each in kwargs:
-            args[each] = kwargs[each]
-        for each in self.__kwargs__:
-            args[each] = self.__kwargs__[each]
-        return conf_helps.StaticInput(**args)
-
-
-class RecurrentGroupV2(Layer):
-    def __init__(self, name, **kwargs):
-        self.__parent_names__ = ['input', 'boot_layer']
-        other_kwargs = dict()
-        parent_layers = dict()
-        for pname in self.__parent_names__:
-            if kwargs.has_key(pname):
-                parent_layers[pname] = kwargs[pname]
-        for key in kwargs.keys():
-            if key not in self.__parent_names__:
-                other_kwargs[key] = kwargs[key]
-        self.__kwargs__ = other_kwargs
-
-        super(RecurrentGroupV2, self).__init__(
-            name=name, parent_layers=parent_layers)
+    def __init__(self, input=None, **kwargs):
+        assert input is not None
+        self.__kwargs__ = kwargs
+        super(StaticInputV2, self).__init__(
+            name=input.name, parent_layers={'input': input})
 
-    wrapper = wrap_name_default(name_prefix='recurrent_group')
-    __init__ = wrapper(__init__)
+    def context_name(self):
+        return self.name + "#static_input"
 
     def to_proto_impl(self, **kwargs):
-        def in_args_converter(*in_args):
-            if not isinstance(in_args, collections.Sequence):
-                in_args = [in_args]
-            return [LayerOutputV2(input) for input in in_args]
-
         args = dict()
-        for each in kwargs:
-            args[each] = kwargs[each]
-        for each in self.__kwargs__:
-            args[each] = self.__kwargs__[each]
-        return conf_helps.recurrent_group(
-            name=self.name, in_args_converter=in_args_converter, **args)
+        args.update(kwargs)
+        args.update(self.__kwargs__)
+        return conf_helps.StaticInput(**args)
 
 
 class MixedLayerV2(Layer):
@@ -377,11 +350,79 @@ def mixed(size=0,
     return MixedLayerV2(size, input, name, act, bias_attr, layer_attr)
 
 
+class RecurrentLayerInput(Layer):
+    def __init__(self, recurrent_name, index, parent_layers):
+        assert len(parent_layers) == 1
+        self.__parents__ = parent_layers.values()[0]
+        print self.__parents__, parent_layers
+        super(RecurrentLayerInput, self).__init__(
+            name=self.__parents__[index].name, parent_layers=parent_layers)
+        self.__recurrent_name__ = recurrent_name
+
+    def context_name(self):
+        return self.__recurrent_name__ + ".begin"
+
+    def to_proto_impl(self, **kwargs):
+        model_type('recurrent_nn')
+        RecurrentLayerGroupWithoutOutLinksBegin(
+            name=self.__recurrent_name__,
+            in_links=map(lambda x: x.name, self.__parents__))
+        return self
+
+
+class RecurrentLayerOutput(Layer):
+    def __init__(self, recurrent_name, index, parent_layers):
+        assert len(parent_layers) == 1
+        self.__parents__ = parent_layers.values()[0]
+        super(RecurrentLayerOutput, self).__init__(
+            name=self.__parents__[index].name, parent_layers=parent_layers)
+        self.__recurrent_name__ = recurrent_name
+
+    def context_name(self):
+        return self.__recurrent_name__ + ".end"
+
+    def to_proto_impl(self, **kwargs):
+        for l in self.__parents__:
+            RecurrentLayerGroupSetOutLink(l.name)
+        RecurrentLayerGroupEnd(name=self.__recurrent_name__)
+
+
+@wrap_name_default()
+def recurrent_group(step, input, name=None):
+    if not isinstance(input, collections.Sequence):
+        input = [input]
+
+    actual_input = [
+        RecurrentLayerInput(
+            recurrent_name=name,
+            index=i,
+            parent_layers={'recurrent_inputs': input})
+        for i in xrange(len(input))
+    ]
+
+    actual_output = step(*actual_input)
+
+    if not isinstance(actual_output, collections.Sequence):
+        actual_output = [actual_output]
+
+    retv = [
+        RecurrentLayerOutput(
+            recurrent_name=name,
+            index=i,
+            parent_layers={'recurrent_outputs': actual_output})
+        for i in xrange(len(actual_output))
+    ]
+    if len(retv) == 1:
+        return retv[0]
+    else:
+        return retv
+
+
 LayerV2 = Layer
 data = DataLayerV2
 AggregateLevel = conf_helps.layers.AggregateLevel
 ExpandLevel = conf_helps.layers.ExpandLevel
-recurrent_group = RecurrentGroupV2
+recurrent_group = recurrent_group
 memory = MemoryV2
 
 

From fd3be087d603bc1ea399769b79c1b0f9e1758161 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Wed, 1 Mar 2017 16:01:42 +0800
Subject: [PATCH 022/153] restore recurrent_group in v1

---
 python/paddle/trainer_config_helpers/layers.py | 12 ++----------
 python/paddle/v2/layer.py                      |  5 -----
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py
index dcb39784a5412..2b95c2ed0f356 100755
--- a/python/paddle/trainer_config_helpers/layers.py
+++ b/python/paddle/trainer_config_helpers/layers.py
@@ -3115,9 +3115,7 @@ def recurrent_group(step,
                     reverse=False,
                     name=None,
                     targetInlink=None,
-                    is_generating=False,
-                    in_args_converter=None,
-                    boot_layer=None):
+                    is_generating=False):
     """
     Recurrent layer group is an extremely flexible recurrent unit in
     PaddlePaddle. As long as the user defines the calculation done within a
@@ -3260,13 +3258,7 @@ def map_in_links(x):
 
     assert (is_generating != has_LayerOutput)
 
-    if in_args_converter is None:
-        layer_outs = step(*in_args)
-    else:
-        # append boot_layer to the last of in_args
-        if boot_layer is not None:
-            in_args.append(boot_layer)
-        layer_outs = step(*in_args_converter(*in_args)).to_proto(dict())
+    layer_outs = step(*in_args)
 
     if isinstance(layer_outs, LayerOutput):
         layer_outs = [layer_outs]
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index 71d0e54c0a6f8..f1ca0b46ebc42 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -131,11 +131,6 @@ def to_proto(self, context):
 
         if self.context_name() is None:
             return self.to_proto_impl(**kwargs)
-        elif isinstance(self, MemoryV2):
-            name = self.name + "#__memory__"
-            if name not in context:
-                context[name] = self.to_proto_impl(**kwargs)
-            return context[name]
         elif self.context_name() not in context:
             context[self.context_name()] = self.to_proto_impl(**kwargs)
         return context[self.name]

From 6b199367e0339119a699292ff488976bdb22554f Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Wed, 1 Mar 2017 16:27:55 +0800
Subject: [PATCH 023/153] handle memory layer

---
 python/paddle/v2/layer.py | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index f1ca0b46ebc42..bdb0c29a47db0 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -133,7 +133,11 @@ def to_proto(self, context):
             return self.to_proto_impl(**kwargs)
         elif self.context_name() not in context:
             context[self.context_name()] = self.to_proto_impl(**kwargs)
-        return context[self.name]
+
+        if self.use_context_name():
+            return context[self.context_name()]
+        else:
+            return context[self.name]
 
     def to_proto_impl(self, **kwargs):
         raise NotImplementedError()
@@ -146,6 +150,9 @@ def context_name(self):
         """
         return self.name
 
+    def use_context_name(self):
+        return False
+
 
 def __convert_to_v2__(method_name, parent_names, is_default_name=True):
     if is_default_name:
@@ -239,6 +246,13 @@ def to_proto_impl(self, **kwargs):
     def context_name(self):
         return self.name + "#memory"
 
+    def use_context_name(self):
+        """
+        memory layer will have the same name with some layer
+        :return:
+        """
+        return True
+
 
 class LayerOutputV2(Layer):
     """

From d9b2e7d09ec2d74f1c2a689e45838c95008006a2 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Wed, 1 Mar 2017 17:27:31 +0800
Subject: [PATCH 024/153] Complete recommendation demo in API.v2

---
 demo/recommendation/api_train_v2.py   | 69 ++++++++++++++++++++++++---
 python/paddle/v2/dataset/movielens.py | 19 +++++++-
 2 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py
index c726fa5bdb31f..3ff86c2c45e05 100644
--- a/demo/recommendation/api_train_v2.py
+++ b/demo/recommendation/api_train_v2.py
@@ -2,6 +2,7 @@
 
 
 def main():
+    paddle.init(use_gpu=False, trainer_count=3)
     movie_title_dict = paddle.dataset.movielens.get_movie_title_dict()
     uid = paddle.layer.data(
         name='user_id',
@@ -17,10 +18,17 @@ def main():
         name='age_id',
         type=paddle.data_type.integer_value(
             len(paddle.dataset.movielens.age_table)))
-    usr_age_emb = paddle.embedding(input=usr_age_id, size=16)
+    usr_age_emb = paddle.layer.embedding(input=usr_age_id, size=16)
 
-    usr_combined_features = paddle.fc(
-        input=[usr_emb, usr_gender_emb, usr_age_emb],
+    usr_job_id = paddle.layer.data(
+        name='job_id',
+        type=paddle.data_type.integer_value(paddle.dataset.movielens.max_job_id(
+        ) + 1))
+
+    usr_job_emb = paddle.layer.embedding(input=usr_job_id, size=16)
+
+    usr_combined_features = paddle.layer.fc(
+        input=[usr_emb, usr_gender_emb, usr_age_emb, usr_job_emb],
         size=200,
         act=paddle.activation.Tanh())
 
@@ -30,12 +38,59 @@ def main():
             paddle.dataset.movielens.max_movie_id() + 1))
     mov_emb = paddle.layer.embedding(input=mov_id, size=32)
 
+    mov_categories = paddle.layer.data(
+        name='category_id',
+        type=paddle.data_type.sparse_binary_vector(
+            len(paddle.dataset.movielens.movie_categories())))
+
+    mov_categories_hidden = paddle.layer.fc(input=mov_categories, size=32)
+
     mov_title_id = paddle.layer.data(
         name='movie_title',
-        type=paddle.data_type.integer_value(len(movie_title_dict)))
-    mov_title_emb = paddle.embedding(input=mov_title_id, size=32)
-    with paddle.layer.mixed() as mixed:
-        pass
+        type=paddle.data_type.integer_value_sequence(len(movie_title_dict)))
+    mov_title_emb = paddle.layer.embedding(input=mov_title_id, size=32)
+    mov_title_conv = paddle.networks.sequence_conv_pool(
+        input=mov_title_emb, hidden_size=32, context_len=3)
+
+    mov_combined_features = paddle.layer.fc(
+        input=[mov_emb, mov_categories_hidden, mov_title_conv],
+        size=200,
+        act=paddle.activation.Tanh())
+
+    inference = paddle.layer.cos_sim(
+        a=usr_combined_features, b=mov_combined_features, size=1, scale=5)
+    cost = paddle.layer.regression_cost(
+        input=inference,
+        label=paddle.layer.data(
+            name='score', type=paddle.data_type.dense_vector(1)))
+
+    parameters = paddle.parameters.create(cost)
+
+    trainer = paddle.trainer.SGD(cost=cost,
+                                 parameters=parameters,
+                                 update_equation=paddle.optimizer.Adam(
+                                     learning_rate=1e-4))
+
+    def event_handler(event):
+        if isinstance(event, paddle.event.EndIteration):
+            if event.batch_id % 100 == 0:
+                print "Pass %d Batch %d Cost %.2f" % (
+                    event.pass_id, event.batch_id, event.cost)
+
+    trainer.train(
+        reader=paddle.reader.batched(
+            paddle.dataset.movielens.train(), batch_size=256),
+        event_handler=event_handler,
+        reader_dict={
+            'user_id': 0,
+            'gender_id': 1,
+            'age_id': 2,
+            'job_id': 3,
+            'movie_id': 4,
+            'category_id': 5,
+            'movie_title': 6,
+            'score': 7
+        })
 
 
 if __name__ == '__main__':
diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py
index 6efe42adbaff9..058400502fc31 100644
--- a/python/paddle/v2/dataset/movielens.py
+++ b/python/paddle/v2/dataset/movielens.py
@@ -6,7 +6,7 @@
 
 __all__ = [
     'train', 'test', 'get_movie_title_dict', 'max_movie_id', 'max_user_id',
-    'age_table'
+    'age_table', 'movie_categories', 'max_job_id'
 ]
 
 age_table = [1, 18, 25, 35, 45, 50, 56]
@@ -135,6 +135,23 @@ def max_user_id():
     return reduce(__max_index_info__, USER_INFO.viewvalues()).index
 
 
+def __max_job_id_impl__(a, b):
+    if a.job_id > b.job_id:
+        return a
+    else:
+        return b
+
+
+def max_job_id():
+    __initialize_meta_info__()
+    return reduce(__max_job_id_impl__, USER_INFO.viewvalues()).job_id
+
+
+def movie_categories():
+    __initialize_meta_info__()
+    return CATEGORIES_DICT
+
+
 def unittest():
     for train_count, _ in enumerate(train()()):
         pass

From 542eb736ab66ca5f7f974fde8d6a91bbfa781f4b Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Wed, 1 Mar 2017 15:47:07 +0800
Subject: [PATCH 025/153] update

---
 demo/semantic_role_labeling/api_train_v2.py | 37 +++++++++++----------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py
index 0317c818db256..cfbd2a022426b 100644
--- a/demo/semantic_role_labeling/api_train_v2.py
+++ b/demo/semantic_role_labeling/api_train_v2.py
@@ -1,4 +1,4 @@
-import numpy
+import numpy as np
 import paddle.v2 as paddle
 from model_v2 import db_lstm
 
@@ -31,10 +31,6 @@
 label_dict_len = len(label_dict)
 pred_len = len(predicate_dict)
 
-print 'word_dict_len=%d' % word_dict_len
-print 'label_dict_len=%d' % label_dict_len
-print 'pred_len=%d' % pred_len
-
 
 def train_reader(file_name="data/feature"):
     def reader():
@@ -65,25 +61,34 @@ def reader():
     return reader
 
 
+def load_parameter(file_name, h, w):
+    with open(file_name, 'rb') as f:
+        f.read(16)  # skip header for float type.
+        return np.fromfile(f, dtype=np.float32).reshape(h, w)
+
+
 def main():
     paddle.init(use_gpu=False, trainer_count=1)
 
     # define network topology
     crf_cost, crf_dec = db_lstm(word_dict_len, label_dict_len, pred_len)
 
-    #parameters = paddle.parameters.create([crf_cost, crf_dec])
-    parameters = paddle.parameters.create(crf_cost)
+    parameters = paddle.parameters.create([crf_cost, crf_dec])
     optimizer = paddle.optimizer.Momentum(momentum=0.01, learning_rate=2e-2)
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
-            print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id,
-                                                  event.cost)
-
+            if event.batch_id % 100 == 0:
+                print "Pass %d, Batch %d, Cost %f, %s" % (
+                    event.pass_id, event.batch_id, event.cost, event.metrics)
         else:
             pass
 
-    trainer = paddle.trainer.SGD(update_equation=optimizer)
+    trainer = paddle.trainer.SGD(cost=crf_cost,
+                                 parameters=parameters,
+                                 update_equation=optimizer)
+
+    parameters.set('emb', load_parameter("data/emb", 44068, 32))
 
     reader_dict = {
         'word_data': 0,
@@ -96,18 +101,14 @@ def event_handler(event):
         'mark_data': 7,
         'target': 8,
     }
-    #trn_reader = paddle.reader.batched(
-    #    paddle.reader.shuffle(
-    #        train_reader(), buf_size=8192), batch_size=2)
-    trn_reader = paddle.reader.batched(train_reader(), batch_size=1)
+    trn_reader = paddle.reader.batched(
+        paddle.reader.shuffle(
+            train_reader(), buf_size=8192), batch_size=10)
     trainer.train(
         reader=trn_reader,
-        cost=crf_cost,
-        parameters=parameters,
         event_handler=event_handler,
         num_passes=10000,
         reader_dict=reader_dict)
-    #cost=[crf_cost, crf_dec],
 
 
 if __name__ == '__main__':

From 82ec9f225b210ff99d83b97e0e09938061aba4ee Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 17:50:19 +0800
Subject: [PATCH 026/153] Training the understand sentiment model with the new
 API.

---
 demo/sentiment/train_with_new_api.py | 182 +++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)
 create mode 100644 demo/sentiment/train_with_new_api.py

diff --git a/demo/sentiment/train_with_new_api.py b/demo/sentiment/train_with_new_api.py
new file mode 100644
index 0000000000000..f937b029068c2
--- /dev/null
+++ b/demo/sentiment/train_with_new_api.py
@@ -0,0 +1,182 @@
+from os.path import join as join_path
+import paddle.v2 as paddle
+import paddle.v2.layer as layer
+import paddle.v2.activation as activation
+import paddle.v2.data_type as data_type
+
+
+def sequence_conv_pool(input,
+                       input_size,
+                       context_len,
+                       hidden_size,
+                       name=None,
+                       context_start=None,
+                       pool_type=None,
+                       context_proj_layer_name=None,
+                       context_proj_param_attr=False,
+                       fc_layer_name=None,
+                       fc_param_attr=None,
+                       fc_bias_attr=None,
+                       fc_act=None,
+                       pool_bias_attr=None,
+                       fc_attr=None,
+                       context_attr=None,
+                       pool_attr=None):
+    """
+    Text convolution pooling layers helper.
+
+    Text input => Context Projection => FC Layer => Pooling => Output.
+
+    :param name: name of output layer(pooling layer name)
+    :type name: basestring
+    :param input: name of input layer
+    :type input: LayerOutput
+    :param context_len: context projection length. See
+                        context_projection's document.
+    :type context_len: int
+    :param hidden_size: FC Layer size.
+    :type hidden_size: int
+    :param context_start: context projection length. See
+                          context_projection's context_start.
+    :type context_start: int or None
+    :param pool_type: pooling layer type. See pooling_layer's document.
+    :type pool_type: BasePoolingType.
+    :param context_proj_layer_name: context projection layer name.
+                                    None if user don't care.
+    :type context_proj_layer_name: basestring
+    :param context_proj_param_attr: context projection parameter attribute.
+                                    None if user don't care.
+    :type context_proj_param_attr: ParameterAttribute or None.
+    :param fc_layer_name: fc layer name. None if user don't care.
+    :type fc_layer_name: basestring
+    :param fc_param_attr: fc layer parameter attribute. None if user don't care.
+    :type fc_param_attr: ParameterAttribute or None
+    :param fc_bias_attr: fc bias parameter attribute. False if no bias,
+                         None if user don't care.
+    :type fc_bias_attr: ParameterAttribute or None
+    :param fc_act: fc layer activation type. None means tanh
+    :type fc_act: BaseActivation
+    :param pool_bias_attr: pooling layer bias attr. None if don't care.
+                           False if no bias.
+    :type pool_bias_attr: ParameterAttribute or None.
+    :param fc_attr: fc layer extra attribute.
+    :type fc_attr: ExtraLayerAttribute
+    :param context_attr: context projection layer extra attribute.
+    :type context_attr: ExtraLayerAttribute
+    :param pool_attr: pooling layer extra attribute.
+    :type pool_attr: ExtraLayerAttribute
+    :return: output layer name.
+    :rtype: LayerOutput
+    """
+    # Set Default Value to param
+    context_proj_layer_name = "%s_conv_proj" % name \
+        if context_proj_layer_name is None else context_proj_layer_name
+
+    with layer.mixed(
+            name=context_proj_layer_name,
+            size=input_size * context_len,
+            act=activation.Linear(),
+            layer_attr=context_attr) as m:
+        m += layer.context_projection(
+            input=input,
+            context_len=context_len,
+            context_start=context_start,
+            padding_attr=context_proj_param_attr)
+
+    fc_layer_name = "%s_conv_fc" % name \
+        if fc_layer_name is None else fc_layer_name
+    fl = layer.fc(name=fc_layer_name,
+                  input=m,
+                  size=hidden_size,
+                  act=fc_act,
+                  layer_attr=fc_attr,
+                  param_attr=fc_param_attr,
+                  bias_attr=fc_bias_attr)
+
+    return layer.pooling(
+        name=name,
+        input=fl,
+        pooling_type=pool_type,
+        bias_attr=pool_bias_attr,
+        layer_attr=pool_attr)
+
+
+def convolution_net(input_dim,
+                    class_dim=2,
+                    emb_dim=128,
+                    hid_dim=128,
+                    is_predict=False):
+    data = layer.data("word", data_type.integer_value_sequence(input_dim))
+    emb = layer.embedding(input=data, size=emb_dim)
+    conv_3 = sequence_conv_pool(
+        input=emb, input_size=emb_dim, context_len=3, hidden_size=hid_dim)
+    conv_4 = sequence_conv_pool(
+        input=emb, input_size=emb_dim, context_len=4, hidden_size=hid_dim)
+    output = layer.fc(input=[conv_3, conv_4],
+                      size=class_dim,
+                      act=activation.Softmax())
+    lbl = layer.data("label", data_type.integer_value(1))
+    cost = layer.classification_cost(input=output, label=lbl)
+    return cost
+
+
+def data_reader():
+    data_dir = "./data/pre-imdb"
+    train_file = "train_part_000"
+    test_file = "test_part_000"
+    dict_file = "dict.txt"
+    train_file = join_path(data_dir, train_file)
+    test_file = join_path(data_dir, test_file)
+    dict_file = join_path(data_dir, dict_file)
+
+    with open(dict_file, 'r') as fdict, open(train_file, 'r') as fdata:
+        dictionary = dict()
+        for i, line in enumerate(fdict):
+            dictionary[line.split('\t')[0]] = i
+
+        print('dict len : %d' % (len(dictionary)))
+        for line_count, line in enumerate(fdata):
+            label, comment = line.strip().split('\t\t')
+            label = int(label)
+            words = comment.split()
+            word_slot = [dictionary[w] for w in words if w in dictionary]
+            yield (word_slot, label)
+
+
+if __name__ == '__main__':
+    data_dir = "./data/pre-imdb"
+    train_list = "train.list"
+    test_list = "test.list"
+    dict_file = "dict.txt"
+    dict_dim = len(open(join_path(data_dir, "dict.txt")).readlines())
+    class_dim = len(open(join_path(data_dir, 'labels.list')).readlines())
+    is_predict = False
+
+    # init
+    paddle.init(use_gpu=True, trainer_count=4)
+
+    # network config
+    cost = convolution_net(dict_dim, class_dim=class_dim, is_predict=is_predict)
+
+    # create parameters
+    parameters = paddle.parameters.create(cost)
+
+    adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01)
+
+    def event_handler(event):
+        if isinstance(event, paddle.event.EndIteration):
+            if event.batch_id % 1 == 0:
+                print "Pass %d, Batch %d, Cost %f, %s" % (
+                    event.pass_id, event.batch_id, event.cost, event.metrics)
+
+    trainer = paddle.trainer.SGD(cost=cost,
+                                 parameters=parameters,
+                                 update_equation=adam_optimizer)
+
+    trainer.train(
+        reader=paddle.reader.batched(
+            data_reader, batch_size=128),
+        event_handler=event_handler,
+        reader_dict={'word': 0,
+                     'label': 1},
+        num_passes=10)

From 3a5f98c36a13a4c027ee87461f52b49ebb6b6002 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 18:59:00 +0800
Subject: [PATCH 027/153] Add reader.shuffle

---
 demo/sentiment/train_with_new_api.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/demo/sentiment/train_with_new_api.py b/demo/sentiment/train_with_new_api.py
index f937b029068c2..59a303c0d58a0 100644
--- a/demo/sentiment/train_with_new_api.py
+++ b/demo/sentiment/train_with_new_api.py
@@ -134,7 +134,6 @@ def data_reader():
         for i, line in enumerate(fdict):
             dictionary[line.split('\t')[0]] = i
 
-        print('dict len : %d' % (len(dictionary)))
         for line_count, line in enumerate(fdata):
             label, comment = line.strip().split('\t\t')
             label = int(label)
@@ -165,7 +164,7 @@ def data_reader():
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
-            if event.batch_id % 1 == 0:
+            if event.batch_id % 100 == 0:
                 print "Pass %d, Batch %d, Cost %f, %s" % (
                     event.pass_id, event.batch_id, event.cost, event.metrics)
 
@@ -175,7 +174,8 @@ def event_handler(event):
 
     trainer.train(
         reader=paddle.reader.batched(
-            data_reader, batch_size=128),
+            paddle.reader.shuffle(
+                data_reader, buf_size=4096), batch_size=128),
         event_handler=event_handler,
         reader_dict={'word': 0,
                      'label': 1},

From 41f04e5ae4a459c0934cc7bca55e75dbbbb51b8a Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 19:25:09 +0800
Subject: [PATCH 028/153] Add regularization and model_average

---
 demo/sentiment/train_with_new_api.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/demo/sentiment/train_with_new_api.py b/demo/sentiment/train_with_new_api.py
index 59a303c0d58a0..bec07de92a13a 100644
--- a/demo/sentiment/train_with_new_api.py
+++ b/demo/sentiment/train_with_new_api.py
@@ -160,7 +160,10 @@ def data_reader():
     # create parameters
     parameters = paddle.parameters.create(cost)
 
-    adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01)
+    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))
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):

From 1d0a8c2f745dc15d17a83ac43e8e3ca9296d6216 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 19:31:57 +0800
Subject: [PATCH 029/153] rename train_v2.py

---
 demo/sentiment/{train_with_new_api.py => train_v2.py} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename demo/sentiment/{train_with_new_api.py => train_v2.py} (100%)

diff --git a/demo/sentiment/train_with_new_api.py b/demo/sentiment/train_v2.py
similarity index 100%
rename from demo/sentiment/train_with_new_api.py
rename to demo/sentiment/train_v2.py

From 803da664eddfc85bb55e192b7a98c696bf4fe112 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 19:49:17 +0800
Subject: [PATCH 030/153] Add test

---
 demo/sentiment/train_v2.py | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py
index bec07de92a13a..a764798addff0 100644
--- a/demo/sentiment/train_v2.py
+++ b/demo/sentiment/train_v2.py
@@ -142,6 +142,28 @@ def data_reader():
             yield (word_slot, label)
 
 
+def test_reader():
+    data_dir = "./data/pre-imdb"
+    train_file = "train_part_000"
+    test_file = "test_part_000"
+    dict_file = "dict.txt"
+    train_file = join_path(data_dir, train_file)
+    test_file = join_path(data_dir, test_file)
+    dict_file = join_path(data_dir, dict_file)
+
+    with open(dict_file, 'r') as fdict, open(test_file, 'r') as ftest:
+        dictionary = dict()
+        for i, line in enumerate(fdict):
+            dictionary[line.split('\t')[0]] = i
+
+        for line_count, line in enumerate(ftest):
+            label, comment = line.strip().split('\t\t')
+            label = int(label)
+            words = comment.split()
+            word_slot = [dictionary[w] for w in words if w in dictionary]
+            yield (word_slot, label)
+
+
 if __name__ == '__main__':
     data_dir = "./data/pre-imdb"
     train_list = "train.list"
@@ -170,6 +192,13 @@ def event_handler(event):
             if event.batch_id % 100 == 0:
                 print "Pass %d, Batch %d, Cost %f, %s" % (
                     event.pass_id, event.batch_id, event.cost, event.metrics)
+        if isinstance(event, paddle.event.EndPass):
+            result = trainer.test(
+                reader=paddle.reader.batched(
+                    test_reader, batch_size=128),
+                reader_dict={'word': 0,
+                             'label': 1})
+            print "Test with Pass %d, %s" % (event.pass_id, result.metrics)
 
     trainer = paddle.trainer.SGD(cost=cost,
                                  parameters=parameters,

From ad44a3ebcaa062342ec799f020bd3975e6b5f899 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 20:14:43 +0800
Subject: [PATCH 031/153] Update vgg and resnet via api v2

---
 demo/image_classification/api_v2_resnet.py    |  74 ++++++++
 .../{train_v2_vgg.py => api_v2_train.py}      |  59 ++-----
 demo/image_classification/api_v2_vgg.py       |  47 ++++++
 demo/image_classification/train_v2_resnet.py  | 158 ------------------
 4 files changed, 139 insertions(+), 199 deletions(-)
 create mode 100644 demo/image_classification/api_v2_resnet.py
 rename demo/image_classification/{train_v2_vgg.py => api_v2_train.py} (55%)
 create mode 100644 demo/image_classification/api_v2_vgg.py
 delete mode 100644 demo/image_classification/train_v2_resnet.py

diff --git a/demo/image_classification/api_v2_resnet.py b/demo/image_classification/api_v2_resnet.py
new file mode 100644
index 0000000000000..19d20540780be
--- /dev/null
+++ b/demo/image_classification/api_v2_resnet.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import paddle.v2 as paddle
+
+__all__ = ['resnet_cifar10']
+
+
+def conv_bn_layer(input,
+                  ch_out,
+                  filter_size,
+                  stride,
+                  padding,
+                  active_type=paddle.activation.Relu(),
+                  ch_in=None):
+    tmp = paddle.layer.img_conv(
+        input=input,
+        filter_size=filter_size,
+        num_channels=ch_in,
+        num_filters=ch_out,
+        stride=stride,
+        padding=padding,
+        act=paddle.activation.Linear(),
+        bias_attr=False)
+    return paddle.layer.batch_norm(input=tmp, act=active_type)
+
+
+def shortcut(ipt, n_in, n_out, stride):
+    if n_in != n_out:
+        return conv_bn_layer(ipt, n_out, 1, stride, 0,
+                             paddle.activation.Linear())
+    else:
+        return ipt
+
+
+def basicblock(ipt, ch_out, stride):
+    ch_in = ch_out * 2
+    tmp = conv_bn_layer(ipt, ch_out, 3, stride, 1)
+    tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1, paddle.activation.Linear())
+    short = shortcut(ipt, ch_in, ch_out, stride)
+    return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())
+
+
+def layer_warp(block_func, ipt, features, count, stride):
+    tmp = block_func(ipt, features, stride)
+    for i in range(1, count):
+        tmp = block_func(tmp, features, 1)
+    return tmp
+
+
+def resnet_cifar10(ipt, depth=32):
+    # depth should be one of 20, 32, 44, 56, 110, 1202
+    assert (depth - 2) % 6 == 0
+    n = (depth - 2) / 6
+    nStages = {16, 64, 128}
+    conv1 = conv_bn_layer(
+        ipt, ch_in=3, ch_out=16, filter_size=3, stride=1, padding=1)
+    res1 = layer_warp(basicblock, conv1, 16, n, 1)
+    res2 = layer_warp(basicblock, res1, 32, n, 2)
+    res3 = layer_warp(basicblock, res2, 64, n, 2)
+    pool = paddle.layer.img_pool(
+        input=res3, pool_size=8, stride=1, pool_type=paddle.pooling.Avg())
+    return pool
diff --git a/demo/image_classification/train_v2_vgg.py b/demo/image_classification/api_v2_train.py
similarity index 55%
rename from demo/image_classification/train_v2_vgg.py
rename to demo/image_classification/api_v2_train.py
index 5656ac85c6125..44a8db39414f3 100644
--- a/demo/image_classification/train_v2_vgg.py
+++ b/demo/image_classification/api_v2_train.py
@@ -10,9 +10,10 @@
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
-# limitations under the License.
+# limitations under the License
 
-import paddle.v2 as paddle
+from api_v2_vgg import resnet_cifar10
+from api_v2_resnet import vgg_bn_drop
 
 
 def event_handler(event):
@@ -22,46 +23,21 @@ def event_handler(event):
                                                   event.cost)
 
 
-def vgg_bn_drop(input):
-    def conv_block(ipt, num_filter, groups, dropouts, num_channels=None):
-        return paddle.layer.img_conv_group(
-            input=ipt,
-            num_channels=num_channels,
-            pool_size=2,
-            pool_stride=2,
-            conv_num_filter=[num_filter] * groups,
-            conv_filter_size=3,
-            conv_act=paddle.activation.Relu(),
-            conv_with_batchnorm=True,
-            conv_batchnorm_drop_rate=dropouts,
-            pool_type=paddle.pooling.Max())
-
-    conv1 = conv_block(input, 64, 2, [0.3, 0], 3)
-    conv2 = conv_block(conv1, 128, 2, [0.4, 0])
-    conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
-    conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
-    conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
-
-    drop = paddle.layer.dropout(input=conv5, dropout_rate=0.5)
-    fc1 = paddle.layer.fc(input=drop, size=512, act=paddle.activation.Linear())
-    bn = paddle.layer.batch_norm(
-        input=fc1,
-        act=paddle.activation.Relu(),
-        layer_attr=ExtraAttr(drop_rate=0.5))
-    fc2 = paddle.layer.fc(input=bn, size=512, act=paddle.activation.Linear())
-    return fc2
-
-
 def main():
     datadim = 3 * 32 * 32
     classdim = 10
 
-    paddle.init(use_gpu=False, trainer_count=1)
+    paddle.init(use_gpu=True, trainer_count=1)
 
     image = paddle.layer.data(
         name="image", type=paddle.data_type.dense_vector(datadim))
+
+    # option 1. resnet
+    net = resnet_cifar10(image, depth=32)
+    # option 2. vgg
     # net = vgg_bn_drop(image)
-    out = paddle.layer.fc(input=image,
+
+    out = paddle.layer.fc(input=net,
                           size=classdim,
                           act=paddle.activation.Softmax())
 
@@ -70,27 +46,28 @@ def main():
     cost = paddle.layer.classification_cost(input=out, label=lbl)
 
     parameters = paddle.parameters.create(cost)
+
     momentum_optimizer = paddle.optimizer.Momentum(
         momentum=0.9,
-        regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128),
+        regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
         learning_rate=0.1 / 128.0,
         learning_rate_decay_a=0.1,
         learning_rate_decay_b=50000 * 100,
         learning_rate_schedule='discexp',
         batch_size=128)
 
-    trainer = paddle.trainer.SGD(update_equation=momentum_optimizer)
+    trainer = paddle.trainer.SGD(cost=cost,
+                                 parameters=parameters,
+                                 update_equation=momentum_optimizer)
     trainer.train(
         reader=paddle.reader.batched(
             paddle.reader.shuffle(
-                paddle.dataset.cifar.train10(), buf_size=3072),
+                paddle.dataset.cifar.train10(), buf_size=50000),
             batch_size=128),
-        cost=cost,
-        num_passes=1,
-        parameters=parameters,
+        num_passes=5,
         event_handler=event_handler,
         reader_dict={'image': 0,
-                     'label': 1}, )
+                     'label': 1})
 
 
 if __name__ == '__main__':
diff --git a/demo/image_classification/api_v2_vgg.py b/demo/image_classification/api_v2_vgg.py
new file mode 100644
index 0000000000000..1e0e6b93adde3
--- /dev/null
+++ b/demo/image_classification/api_v2_vgg.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import paddle.v2 as paddle
+
+__all__ = ['vgg_bn_drop']
+
+
+def vgg_bn_drop(input):
+    def conv_block(ipt, num_filter, groups, dropouts, num_channels=None):
+        return paddle.networks.img_conv_group(
+            input=ipt,
+            num_channels=num_channels,
+            pool_size=2,
+            pool_stride=2,
+            conv_num_filter=[num_filter] * groups,
+            conv_filter_size=3,
+            conv_act=paddle.activation.Relu(),
+            conv_with_batchnorm=True,
+            conv_batchnorm_drop_rate=dropouts,
+            pool_type=paddle.pooling.Max())
+
+    conv1 = conv_block(input, 64, 2, [0.3, 0], 3)
+    conv2 = conv_block(conv1, 128, 2, [0.4, 0])
+    conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
+    conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
+    conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
+
+    drop = paddle.layer.dropout(input=conv5, dropout_rate=0.5)
+    fc1 = paddle.layer.fc(input=drop, size=512, act=paddle.activation.Linear())
+    bn = paddle.layer.batch_norm(
+        input=fc1,
+        act=paddle.activation.Relu(),
+        layer_attr=paddle.attr.Extra(drop_rate=0.5))
+    fc2 = paddle.layer.fc(input=bn, size=512, act=paddle.activation.Linear())
+    return fc2
diff --git a/demo/image_classification/train_v2_resnet.py b/demo/image_classification/train_v2_resnet.py
deleted file mode 100644
index fdfa87cd8755e..0000000000000
--- a/demo/image_classification/train_v2_resnet.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import paddle.v2 as paddle
-
-
-def event_handler(event):
-    if isinstance(event, paddle.event.EndIteration):
-        if event.batch_id % 100 == 0:
-            print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id,
-                                                  event.cost)
-
-
-def conv_bn_layer(input,
-                  ch_out,
-                  filter_size,
-                  stride,
-                  padding,
-                  active_type=paddle.activation.Relu(),
-                  ch_in=None):
-    tmp = paddle.layer.img_conv(
-        input=input,
-        filter_size=filter_size,
-        num_channels=ch_in,
-        num_filters=ch_out,
-        stride=stride,
-        padding=padding,
-        act=paddle.activation.Linear(),
-        bias_attr=False)
-    return paddle.layer.batch_norm(input=tmp, act=active_type)
-
-
-def shortcut(ipt, n_in, n_out, stride):
-    if n_in != n_out:
-        print("n_in != n_out")
-        return conv_bn_layer(ipt, n_out, 1, stride, 0,
-                             paddle.activation.Linear())
-    else:
-        return ipt
-
-
-def basicblock(ipt, ch_out, stride):
-    ch_in = ipt.num_filters
-    tmp = conv_bn_layer(ipt, ch_out, 3, stride, 1)
-    tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1, paddle.activation.Linear())
-    short = shortcut(ipt, ch_in, ch_out, stride)
-    return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())
-
-
-def bottleneck(ipt, ch_out, stride):
-    ch_in = ipt.num_filter
-    tmp = conv_bn_layer(ipt, ch_out, 1, stride, 0)
-    tmp = conv_bn_layer(tmp, ch_out, 3, 1, 1)
-    tmp = conv_bn_layer(tmp, ch_out * 4, 1, 1, 0, paddle.activation.Linear())
-    short = shortcut(ipt, ch_in, ch_out * 4, stride)
-    return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Relu())
-
-
-def layer_warp(block_func, ipt, features, count, stride):
-    tmp = block_func(ipt, features, stride)
-    for i in range(1, count):
-        tmp = block_func(tmp, features, 1)
-    return tmp
-
-
-def resnet_imagenet(ipt, depth=50):
-    cfg = {
-        18: ([2, 2, 2, 1], basicblock),
-        34: ([3, 4, 6, 3], basicblock),
-        50: ([3, 4, 6, 3], bottleneck),
-        101: ([3, 4, 23, 3], bottleneck),
-        152: ([3, 8, 36, 3], bottleneck)
-    }
-    stages, block_func = cfg[depth]
-    tmp = conv_bn_layer(
-        ipt, ch_in=3, ch_out=64, filter_size=7, stride=2, padding=3)
-    tmp = paddle.layer.img_pool(input=tmp, pool_size=3, stride=2)
-    tmp = layer_warp(block_func, tmp, 64, stages[0], 1)
-    tmp = layer_warp(block_func, tmp, 128, stages[1], 2)
-    tmp = layer_warp(block_func, tmp, 256, stages[2], 2)
-    tmp = layer_warp(block_func, tmp, 512, stages[3], 2)
-    tmp = paddle.layer.img_pool(
-        input=tmp, pool_size=7, stride=1, pool_type=paddle.pooling.Avg())
-
-    tmp = paddle.layer.fc(input=tmp, size=1000, act=paddle.activation.Softmax())
-    return tmp
-
-
-def resnet_cifar10(ipt, depth=32):
-    # depth should be one of 20, 32, 44, 56, 110, 1202
-    assert (depth - 2) % 6 == 0
-    n = (depth - 2) / 6
-    nStages = {16, 64, 128}
-    conv1 = conv_bn_layer(
-        ipt, ch_in=3, ch_out=16, filter_size=3, stride=1, padding=1)
-    res1 = layer_warp(basicblock, conv1, 16, n, 1)
-    res2 = layer_warp(basicblock, res1, 32, n, 2)
-    res3 = layer_warp(basicblock, res2, 64, n, 2)
-    pool = paddle.layer.img_pool(
-        input=res3, pool_size=8, stride=1, pool_type=paddle.pooling.Avg())
-    return pool
-
-
-def main():
-    datadim = 3 * 32 * 32
-    classdim = 10
-
-    paddle.init(use_gpu=False, trainer_count=1)
-
-    image = paddle.layer.data(
-        name="image", type=paddle.data_type.dense_vector(datadim))
-    net = resnet_cifar10(image, depth=32)
-    out = paddle.layer.fc(input=net,
-                          size=classdim,
-                          act=paddle.activation.Softmax())
-
-    lbl = paddle.layer.data(
-        name="label", type=paddle.data_type.integer_value(classdim))
-    cost = paddle.layer.classification_cost(input=out, label=lbl)
-
-    parameters = paddle.parameters.create(cost)
-
-    momentum_optimizer = paddle.optimizer.Momentum(
-        momentum=0.9,
-        regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
-        learning_rate=0.1 / 128.0,
-        learning_rate_decay_a=0.1,
-        learning_rate_decay_b=50000 * 100,
-        learning_rate_schedule='discexp',
-        batch_size=128)
-
-    trainer = paddle.trainer.SGD(update_equation=momentum_optimizer)
-    trainer.train(
-        reader=paddle.reader.batched(
-            paddle.reader.shuffle(
-                paddle.dataset.cifar.train10(), buf_size=3072),
-            batch_size=128),
-        cost=cost,
-        num_passes=1,
-        parameters=parameters,
-        event_handler=event_handler,
-        reader_dict={'image': 0,
-                     'label': 1}, )
-
-
-if __name__ == '__main__':
-    main()

From 49020f0be80428ba22913062ae877605114134eb Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 20:26:42 +0800
Subject: [PATCH 032/153] import paddle.v2

---
 demo/image_classification/api_v2_train.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py
index 44a8db39414f3..e6e4307242057 100644
--- a/demo/image_classification/api_v2_train.py
+++ b/demo/image_classification/api_v2_train.py
@@ -14,6 +14,7 @@
 
 from api_v2_vgg import resnet_cifar10
 from api_v2_resnet import vgg_bn_drop
+import paddle.v2 as paddle
 
 
 def event_handler(event):

From 5fc572c29459faf0fbc342e3582ec8b6ee6f02ac Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Wed, 1 Mar 2017 20:28:00 +0800
Subject: [PATCH 033/153] Complete Memory

---
 python/paddle/trainer/config_parser.py   |  6 +-
 python/paddle/v2/layer.py                | 99 ++++++++++++++++++------
 python/paddle/v2/tests/test_rnn_layer.py | 27 ++++---
 3 files changed, 96 insertions(+), 36 deletions(-)

diff --git a/python/paddle/trainer/config_parser.py b/python/paddle/trainer/config_parser.py
index 487d4dfd5b1b8..da937152ee0ce 100644
--- a/python/paddle/trainer/config_parser.py
+++ b/python/paddle/trainer/config_parser.py
@@ -3474,8 +3474,6 @@ def update_g_config():
     for name in g_config.model_config.output_layer_names:
         assert name in g_layer_map, \
             'input name "%s" does not correspond to a layer name' % name
-    for hook in _parse_config_hooks:
-        hook()
     return g_config
 
 
@@ -3487,8 +3485,8 @@ def parse_config(trainer_config, config_arg_str):
     passed to config script as a dictionary CONFIG_ARGS
     '''
     init_config_environment()
-    # for hook in _parse_config_hooks:
-    #     hook()
+    for hook in _parse_config_hooks:
+        hook()
 
     config_args = {}
 
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index bdb0c29a47db0..bf5d653e8ae3e 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -67,7 +67,7 @@ class for each layer creation function in paddle.trainer_config_helpers.layers.
 """
 
 import collections
-
+import inspect
 import paddle.trainer_config_helpers as conf_helps
 from paddle.trainer_config_helpers.config_parser_utils import \
     parse_network_config as __parse__
@@ -216,31 +216,83 @@ def to_proto_impl(self, **kwargs):
         return getattr(conf_helps, self.__method_name__)(name=self.name, **args)
 
 
-class MemoryV2(Layer):
-    def __init__(self, name, size, **kwargs):
-        self.name = name
-        self.size = size
+class WithExtraParent(Layer):
+    def extra_parent(self):
+        return self.__extra_parent__
 
-        parent_names = ['boot_layer']
-        parent_layers = dict()
-        other_kwargs = dict()
-        for pname in parent_names:
-            if kwargs.has_key(pname):
-                parent_layers[pname] = kwargs[pname]
+    def __init__(self, name=None, parent_layers=None):
+        self.__extra_parent__ = []
+        super(WithExtraParent, self).__init__(name, parent_layers)
 
-        for key in kwargs.keys():
-            if key not in parent_names:
-                other_kwargs[key] = kwargs[key]
-        super(MemoryV2, self).__init__(name=name, parent_layers=parent_layers)
-        self.__kwargs__ = other_kwargs
+    def append_extra_parent(self, parent):
+        self.__extra_parent__.append(parent)
 
-    def to_proto_impl(self, **kwargs):
+    def to_proto(self, context):
+        """
+        function to set proto attribute
+        """
+        kwargs = dict()
+        for p in self.__extra_parent__:
+            p.to_proto(context=context)
+
+        for layer_name in self.__parent_layers__:
+            if not isinstance(self.__parent_layers__[layer_name],
+                              collections.Sequence):
+                v1_layer = self.__parent_layers__[layer_name].to_proto(
+                    context=context)
+            else:
+                v1_layer = map(lambda x: x.to_proto(context=context),
+                               self.__parent_layers__[layer_name])
+            kwargs[layer_name] = v1_layer
+
+        if self.context_name() is None:
+            return self.to_proto_impl(context=context, **kwargs)
+        elif self.context_name() not in context:
+            context[self.context_name()] = self.to_proto_impl(
+                context=context, **kwargs)
+
+        if self.use_context_name():
+            return context[self.context_name()]
+        else:
+            return context[self.name]
+
+
+class MemoryV2(WithExtraParent):
+    def __init__(self, name, size, **kwargs):
+        self.name = name
+        self.size = size
+        super(MemoryV2, self).__init__(name=name, parent_layers=dict())
+        self.__kwargs__ = kwargs
+        self.__boot_layer_name__ = None
+        if 'boot_layer' in kwargs:
+            begin_of_current_rnn = []
+            # TODO(yuyang18): Fix inspect, it could be wrong when user invoke a
+            # function inside step.
+            st = inspect.stack()
+            for i in xrange(len(st)):
+                locs = inspect.stack()[i][0].f_locals
+                for val in locs.viewvalues():
+                    if isinstance(val, RecurrentLayerInput):
+                        begin_of_current_rnn.append(val)
+
+                if begin_of_current_rnn:
+                    break
+            assert begin_of_current_rnn is not None
+            for extra in begin_of_current_rnn:
+                self.append_extra_parent(extra)
+                assert isinstance(extra, WithExtraParent)
+                extra.append_extra_parent(kwargs['boot_layer'])
+                self.__boot_layer_name__ = kwargs['boot_layer'].name
+
+    def to_proto_impl(self, context, **kwargs):
         args = dict()
         for each in kwargs:
             args[each] = kwargs[each]
         for each in self.__kwargs__:
             args[each] = self.__kwargs__[each]
 
+        if self.__boot_layer_name__ is not None:
+            args['boot_layer'] = context[self.__boot_layer_name__]
         return conf_helps.memory(name=self.name, size=self.size, **args)
 
     def context_name(self):
@@ -328,7 +380,7 @@ def __iadd__(self, other):
             self.__inputs__.append(other)
             return self
         else:
-            raise MixedLayerTypeV2.AddToSealedMixedLayerExceptionV2()
+            raise MixedLayerV2.AddToSealedMixedLayerExceptionV2()
 
     def __enter__(self):
         assert len(self.__inputs__) == 0
@@ -359,11 +411,10 @@ def mixed(size=0,
     return MixedLayerV2(size, input, name, act, bias_attr, layer_attr)
 
 
-class RecurrentLayerInput(Layer):
+class RecurrentLayerInput(WithExtraParent):
     def __init__(self, recurrent_name, index, parent_layers):
         assert len(parent_layers) == 1
         self.__parents__ = parent_layers.values()[0]
-        print self.__parents__, parent_layers
         super(RecurrentLayerInput, self).__init__(
             name=self.__parents__[index].name, parent_layers=parent_layers)
         self.__recurrent_name__ = recurrent_name
@@ -371,7 +422,7 @@ def __init__(self, recurrent_name, index, parent_layers):
     def context_name(self):
         return self.__recurrent_name__ + ".begin"
 
-    def to_proto_impl(self, **kwargs):
+    def to_proto_impl(self, context, **kwargs):
         model_type('recurrent_nn')
         RecurrentLayerGroupWithoutOutLinksBegin(
             name=self.__recurrent_name__,
@@ -458,8 +509,10 @@ def __layer_name_mapping__(inname):
 def __layer_name_mapping_parent_names__(inname):
     all_args = getattr(conf_helps, inname).argspec.args
     return filter(
-        lambda x: x in ['input1', 'input2','label', 'input', 'a', 'b', 'expand_as',
-                        'weights', 'vectors', 'weight', 'score', 'left', 'right'],
+        lambda x: x in ['input1', 'input2', 'label', 'input', 'a', 'b',
+                        'expand_as',
+                        'weights', 'vectors', 'weight', 'score', 'left',
+                        'right'],
         all_args)
 
 
diff --git a/python/paddle/v2/tests/test_rnn_layer.py b/python/paddle/v2/tests/test_rnn_layer.py
index bf2c4db61aa50..48aeb42391576 100644
--- a/python/paddle/v2/tests/test_rnn_layer.py
+++ b/python/paddle/v2/tests/test_rnn_layer.py
@@ -106,9 +106,21 @@ def test():
             return str(parse_network(test))
 
         def parse_new_rnn():
+            data = layer.data(
+                name="word", type=data_type.dense_vector(dict_dim))
+            label = layer.data(
+                name="label", type=data_type.dense_vector(label_dim))
+            emb = layer.embedding(input=data, size=word_dim)
+
+            boot_layer = layer.data(
+                name="boot", type=data_type.dense_vector(10))
+
+            boot_layer = layer.fc(name='wtf', input=boot_layer, size=10)
+
             def step(y, wid):
                 z = layer.embedding(input=wid, size=word_dim)
-                mem = layer.memory(name="rnn_state", size=hidden_dim)
+                mem = layer.memory(
+                    name="rnn_state", size=hidden_dim, boot_layer=boot_layer)
                 out = layer.fc(input=[y, z, mem],
                                size=hidden_dim,
                                act=activation.Tanh(),
@@ -116,11 +128,6 @@ def step(y, wid):
                                name="rnn_state")
                 return out
 
-            data = layer.data(
-                name="word", type=data_type.dense_vector(dict_dim))
-            label = layer.data(
-                name="label", type=data_type.dense_vector(label_dim))
-            emb = layer.embedding(input=data, size=word_dim)
             out = layer.recurrent_group(
                 name="rnn", step=step, input=[emb, data])
 
@@ -134,9 +141,11 @@ def step(y, wid):
 
             return str(layer.parse_network(cost))
 
-        diff = difflib.unified_diff(parse_old_rnn().splitlines(1),
-                                    parse_new_rnn().splitlines(1))
-        print ''.join(diff)
+        with open("/Users/baidu/old.out", 'w') as f:
+            print >> f, parse_old_rnn()
+        with open("/Users/baidu/new.out", "w") as f:
+            print >> f, parse_new_rnn()
+        # print ''.join(diff)
 
 
 if __name__ == '__main__':

From 0a33f170a423cc238f7b1c37a8e76a48ce9f48ec Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Wed, 1 Mar 2017 20:35:04 +0800
Subject: [PATCH 034/153] Add stacked lstm network

---
 demo/sentiment/train_v2.py | 74 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 72 insertions(+), 2 deletions(-)

diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py
index a764798addff0..779bfee5b6eca 100644
--- a/demo/sentiment/train_v2.py
+++ b/demo/sentiment/train_v2.py
@@ -1,4 +1,6 @@
 from os.path import join as join_path
+import paddle.trainer_config_helpers.attrs as attrs
+from paddle.trainer_config_helpers.poolings import MaxPooling
 import paddle.v2 as paddle
 import paddle.v2.layer as layer
 import paddle.v2.activation as activation
@@ -115,7 +117,73 @@ def convolution_net(input_dim,
     output = layer.fc(input=[conv_3, conv_4],
                       size=class_dim,
                       act=activation.Softmax())
-    lbl = layer.data("label", data_type.integer_value(1))
+    lbl = layer.data("label", data_type.integer_value(2))
+    cost = layer.classification_cost(input=output, label=lbl)
+    return cost
+
+
+def stacked_lstm_net(input_dim,
+                     class_dim=2,
+                     emb_dim=128,
+                     hid_dim=512,
+                     stacked_num=3,
+                     is_predict=False):
+    """
+    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.
+    is_predict: is predicting or not.
+                Some layers is not needed in network when predicting.
+    """
+    assert stacked_num % 2 == 1
+
+    layer_attr = attrs.ExtraLayerAttribute(drop_rate=0.5)
+    fc_para_attr = attrs.ParameterAttribute(learning_rate=1e-3)
+    lstm_para_attr = attrs.ParameterAttribute(initial_std=0., learning_rate=1.)
+    para_attr = [fc_para_attr, lstm_para_attr]
+    bias_attr = attrs.ParameterAttribute(initial_std=0., l2_rate=0.)
+    relu = activation.Relu()
+    linear = activation.Linear()
+
+    data = layer.data("word", data_type.integer_value_sequence(input_dim))
+    emb = layer.embedding(input=data, size=emb_dim)
+
+    fc1 = layer.fc(input=emb, size=hid_dim, act=linear, bias_attr=bias_attr)
+    lstm1 = layer.lstmemory(
+        input=fc1, act=relu, bias_attr=bias_attr, layer_attr=layer_attr)
+
+    inputs = [fc1, lstm1]
+    for i in range(2, stacked_num + 1):
+        fc = layer.fc(input=inputs,
+                      size=hid_dim,
+                      act=linear,
+                      param_attr=para_attr,
+                      bias_attr=bias_attr)
+        lstm = layer.lstmemory(
+            input=fc,
+            reverse=(i % 2) == 0,
+            act=relu,
+            bias_attr=bias_attr,
+            layer_attr=layer_attr)
+        inputs = [fc, lstm]
+
+    fc_last = layer.pooling(input=inputs[0], pooling_type=MaxPooling())
+    lstm_last = layer.pooling(input=inputs[1], pooling_type=MaxPooling())
+    output = layer.fc(input=[fc_last, lstm_last],
+                      size=class_dim,
+                      act=activation.Softmax(),
+                      bias_attr=bias_attr,
+                      param_attr=para_attr)
+
+    lbl = layer.data("label", data_type.integer_value(2))
     cost = layer.classification_cost(input=output, label=lbl)
     return cost
 
@@ -177,7 +245,9 @@ def test_reader():
     paddle.init(use_gpu=True, trainer_count=4)
 
     # network config
-    cost = convolution_net(dict_dim, class_dim=class_dim, is_predict=is_predict)
+    # cost = convolution_net(dict_dim, class_dim=class_dim, is_predict=is_predict)
+    cost = stacked_lstm_net(
+        dict_dim, class_dim=class_dim, stacked_num=3, is_predict=is_predict)
 
     # create parameters
     parameters = paddle.parameters.create(cost)

From d935d88d42f7fa1aed6d14969bfebe3ffd01928b Mon Sep 17 00:00:00 2001
From: Luo Tao 
Date: Wed, 1 Mar 2017 20:35:51 +0800
Subject: [PATCH 035/153] mnist api v2

---
 demo/mnist/api_train_v2.py | 87 ++++++++++++++++++++++++++++++--------
 1 file changed, 70 insertions(+), 17 deletions(-)

diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py
index a59b30ccdb2ed..495c403e40320 100644
--- a/demo/mnist/api_train_v2.py
+++ b/demo/mnist/api_train_v2.py
@@ -1,48 +1,101 @@
 import paddle.v2 as paddle
 
 
+def softmax_regression(img):
+    predict = paddle.layer.fc(input=img,
+                              size=10,
+                              act=paddle.activation.Softmax())
+    return predict
+
+
+def multilayer_perceptron(img):
+    # The first fully-connected layer
+    hidden1 = paddle.layer.fc(input=img, size=128, act=paddle.activation.Relu())
+    # The second fully-connected layer and the according activation function
+    hidden2 = paddle.layer.fc(input=hidden1,
+                              size=64,
+                              act=paddle.activation.Relu())
+    # The thrid fully-connected layer, note that the hidden size should be 10,
+    # which is the number of unique digits
+    predict = paddle.layer.fc(input=hidden2,
+                              size=10,
+                              act=paddle.activation.Softmax())
+    return predict
+
+
+def convolutional_neural_network(img):
+    # first conv layer
+    conv_pool_1 = paddle.networks.simple_img_conv_pool(
+        input=img,
+        filter_size=5,
+        num_filters=20,
+        num_channel=1,
+        pool_size=2,
+        pool_stride=2,
+        act=paddle.activation.Tanh())
+    # second conv layer
+    conv_pool_2 = paddle.networks.simple_img_conv_pool(
+        input=conv_pool_1,
+        filter_size=5,
+        num_filters=50,
+        num_channel=20,
+        pool_size=2,
+        pool_stride=2,
+        act=paddle.activation.Tanh())
+    # The first fully-connected layer
+    fc1 = paddle.layer.fc(input=conv_pool_2,
+                          size=128,
+                          act=paddle.activation.Tanh())
+    # The softmax layer, note that the hidden size should be 10,
+    # which is the number of unique digits
+    predict = paddle.layer.fc(input=fc1,
+                              size=10,
+                              act=paddle.activation.Softmax())
+    return predict
+
+
 def main():
-    paddle.init(use_gpu=False, trainer_count=1)
+    paddle.init(use_gpu=True, trainer_count=1)
 
     # define network topology
     images = paddle.layer.data(
         name='pixel', type=paddle.data_type.dense_vector(784))
     label = paddle.layer.data(
         name='label', type=paddle.data_type.integer_value(10))
-    hidden1 = paddle.layer.fc(input=images, size=200)
-    hidden2 = paddle.layer.fc(input=hidden1, size=200)
-    inference = paddle.layer.fc(input=hidden2,
-                                size=10,
-                                act=paddle.activation.Softmax())
-    cost = paddle.layer.classification_cost(input=inference, label=label)
+
+    predict = softmax_regression(images)
+    #predict = multilayer_perceptron(images)
+    #predict = convolutional_neural_network(images)
+
+    cost = paddle.layer.classification_cost(input=predict, label=label)
 
     parameters = paddle.parameters.create(cost)
 
-    adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01)
+    optimizer = paddle.optimizer.Momentum(
+        learning_rate=0.1 / 128.0,
+        momentum=0.9,
+        regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128))
 
     trainer = paddle.trainer.SGD(cost=cost,
                                  parameters=parameters,
-                                 update_equation=adam_optimizer)
+                                 update_equation=optimizer)
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
-            if event.batch_id % 1000 == 0:
+            if event.batch_id % 100 == 0:
                 result = trainer.test(reader=paddle.reader.batched(
-                    paddle.dataset.mnist.test(), batch_size=256))
-
+                    paddle.dataset.mnist.test(), batch_size=128))
                 print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % (
                     event.pass_id, event.batch_id, event.cost, event.metrics,
                     result.metrics)
 
-        else:
-            pass
-
     trainer.train(
         reader=paddle.reader.batched(
             paddle.reader.shuffle(
                 paddle.dataset.mnist.train(), buf_size=8192),
-            batch_size=32),
-        event_handler=event_handler)
+            batch_size=128),
+        event_handler=event_handler,
+        num_passes=100)
 
 
 if __name__ == '__main__':

From 36672ae30988683c614dfbae17954b51baa49ca5 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 21:06:25 +0800
Subject: [PATCH 036/153] add clang-format in docker

---
 paddle/scripts/docker/Dockerfile | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile
index ea1d8aba361d2..1b55a40f102db 100644
--- a/paddle/scripts/docker/Dockerfile
+++ b/paddle/scripts/docker/Dockerfile
@@ -29,9 +29,11 @@ RUN apt-get update && \
     apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \
     apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \
     apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \
-    apt-get install -y automake locales && \
+    apt-get install -y automake locales clang-format-3.8 && \
     apt-get clean -y
 
+RUN git config --global credential.helper "cache --timeout=604800"
+
 # Fix locales to en_US.UTF-8
 RUN localedef -i en_US -f UTF-8 en_US.UTF-8
 

From 15972c08529a5e015d20df3fc76b9a608ed46374 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 21:08:22 +0800
Subject: [PATCH 037/153] Add git credential to skip password typing

---
 paddle/scripts/docker/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile
index 1b55a40f102db..b6355cc2db42a 100644
--- a/paddle/scripts/docker/Dockerfile
+++ b/paddle/scripts/docker/Dockerfile
@@ -32,7 +32,7 @@ RUN apt-get update && \
     apt-get install -y automake locales clang-format-3.8 && \
     apt-get clean -y
 
-RUN git config --global credential.helper "cache --timeout=604800"
+RUN git config --global credential.helper store
 
 # Fix locales to en_US.UTF-8
 RUN localedef -i en_US -f UTF-8 en_US.UTF-8

From a82341bbb1800d23e37a14a5284e99f621f7eb36 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Wed, 1 Mar 2017 21:17:44 +0800
Subject: [PATCH 038/153] Update Dockerfile GPU

---
 paddle/scripts/docker/Dockerfile     |  1 +
 paddle/scripts/docker/Dockerfile.gpu | 47 +++++++++++++++++-----------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile
index b6355cc2db42a..23f4d43588767 100644
--- a/paddle/scripts/docker/Dockerfile
+++ b/paddle/scripts/docker/Dockerfile
@@ -32,6 +32,7 @@ RUN apt-get update && \
     apt-get install -y automake locales clang-format-3.8 && \
     apt-get clean -y
 
+# git credential to skip password typing
 RUN git config --global credential.helper store
 
 # Fix locales to en_US.UTF-8
diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu
index 538233dd0c7bb..a975e580e4ed9 100644
--- a/paddle/scripts/docker/Dockerfile.gpu
+++ b/paddle/scripts/docker/Dockerfile.gpu
@@ -5,38 +5,50 @@ ARG DEBIAN_FRONTEND=noninteractive
 ARG UBUNTU_MIRROR
 RUN /bin/bash -c 'if [[ -n ${UBUNTU_MIRROR} ]]; then sed -i 's#http://archive.ubuntu.com#${UBUNTU_MIRROR}#g' /etc/apt/sources.list; fi'
 
+# ENV variables
+ARG BUILD_WOBOQ
+ARG BUILD_AND_INSTALL
+ARG WITH_AVX
+ARG WITH_DOC
+ARG WITH_STYLE_CHECK
+
+ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF}
+ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF}
+ENV WITH_GPU=ON
+ENV WITH_AVX=${WITH_AVX:-ON}
+ENV WITH_DOC=${WITH_DOC:-OFF}
+ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF}
+
+ENV HOME /root
+
+# Add bash enhancements
+COPY ./paddle/scripts/docker/root/ /root/
+
 RUN apt-get update && \
     apt-get install -y git python-pip python-dev openssh-server bison && \
     apt-get install -y wget unzip tar xz-utils bzip2 gzip coreutils && \
     apt-get install -y curl sed grep graphviz libjpeg-dev zlib1g-dev && \
     apt-get install -y python-numpy python-matplotlib gcc g++ gfortran && \
-    apt-get install -y automake && \
+    apt-get install -y automake locales clang-format-3.8 && \
     apt-get clean -y
 
+# git credential to skip password typing
+RUN git config --global credential.helper store
+
+# Fix locales to en_US.UTF-8
+RUN localedef -i en_US -f UTF-8 en_US.UTF-8
+
 RUN pip install --upgrade pip && \
-    pip install -U "protobuf==3.1.0" && \
+    pip install -U 'protobuf==3.1.0' && \
     pip install -U wheel pillow BeautifulSoup && \
     pip install -U docopt PyYAML sphinx && \
-    pip install -U sphinx_rtd_theme recommonmark jupyter
+    pip install -U sphinx_rtd_theme recommonmark && \
+    pip install -U pre-commit 'requests==2.9.2' jupyter
 
 RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \
     cd cmake-3.4.1 && ./bootstrap && make -j `nproc` && make install && \
     cd .. && rm -rf cmake-3.4.1
 
-ARG BUILD_WOBOQ
-ARG BUILD_AND_INSTALL
-ARG WITH_AVX
-ARG WITH_DOC
-ARG WITH_STYLE_CHECK
-
-ENV BUILD_WOBOQ=${BUILD_WOBOQ:-OFF}
-ENV BUILD_AND_INSTALL=${BUILD_AND_INSTALL:-OFF}
-ENV WITH_GPU=ON
-ENV WITH_AVX=${WITH_AVX:-ON}
-ENV WITH_DOC=${WITH_DOC:-OFF}
-ENV WITH_STYLE_CHECK=${WITH_STYLE_CHECK:-OFF}
-
-RUN mkdir /paddle
 COPY . /paddle/
 RUN /paddle/paddle/scripts/docker/build.sh
 VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"]
@@ -53,7 +65,6 @@ RUN mkdir /notes/
 WORKDIR "/notes"
 EXPOSE 8888
 
-RUN mkdir -p /opt/bin
 COPY ./paddle/scripts/docker/entrypoint /opt/bin/
 
 CMD ["/opt/bin/entrypoint"]

From 06cbd81eecf40c6b90b72da01126c176e4fc0ebf Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 02:23:02 +0800
Subject: [PATCH 039/153] CONLL05 dataset for SRL

---
 python/paddle/v2/dataset/conll05.py | 188 ++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 python/paddle/v2/dataset/conll05.py

diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py
new file mode 100644
index 0000000000000..e9029063710f2
--- /dev/null
+++ b/python/paddle/v2/dataset/conll05.py
@@ -0,0 +1,188 @@
+import paddle.v2.dataset.common
+import tarfile
+import gzip
+import itertools
+
+__all__ = ['test, get_dict', 'get_embedding']
+"""
+Conll 2005 dataset.  Paddle semantic role labeling Book and demo use this
+dataset as an example. Because Conll 2005 is not free in public, the default
+downloaded URL is test set of Conll 2005 (which is public). Users can change
+URL and MD5 to their Conll dataset.
+"""
+
+DATA_URL = 'http://www.cs.upc.edu/~srlconll/conll05st-tests.tar.gz'
+DATA_MD5 = '387719152ae52d60422c016e92a742fc'
+WORDDICT_URL = 'http://paddlepaddle.bj.bcebos.com/demo/srl_dict_and_embedding/wordDict.txt'
+WORDDICT_MD5 = 'ea7fb7d4c75cc6254716f0177a506baa'
+VERBDICT_URL = 'http://paddlepaddle.bj.bcebos.com/demo/srl_dict_and_embedding/verbDict.txt'
+VERBDICT_MD5 = '0d2977293bbb6cbefab5b0f97db1e77c'
+TRGDICT_URL = 'http://paddlepaddle.bj.bcebos.com/demo/srl_dict_and_embedding/targetDict.txt'
+TRGDICT_MD5 = 'd8c7f03ceb5fc2e5a0fa7503a4353751'
+EMB_URL = 'http://paddlepaddle.bj.bcebos.com/demo/srl_dict_and_embedding/emb'
+EMB_MD5 = 'bf436eb0faa1f6f9103017f8be57cdb7'
+
+UNK_IDX = 0
+
+
+def load_dict(filename):
+    d = dict()
+    with open(filename, 'r') as f:
+        for i, line in enumerate(f):
+            d[line.strip()] = i
+    return d
+
+
+def corpus_reader(data_path, words_name, props_name):
+    """
+    Read one corpus by corpus name. It returns an iterator. Each element of
+    this iterator is a tuple including sentence and labels. The sentence is
+    consist of a list of word IDs. The labels include a list of label IDs.
+    :param name: corpus name.
+    :type name: basestring
+    :return: a iterator of data.
+    :rtype: iterator
+    """
+
+    def reader():
+        tf = tarfile.open(data_path)
+        wf = tf.extractfile(words_name)
+        pf = tf.extractfile(props_name)
+        with gzip.GzipFile(fileobj=wf) as words_file, gzip.GzipFile(
+                fileobj=pf) as props_file:
+            sentences = []
+            labels = []
+            one_seg = []
+            for word, label in itertools.izip(words_file, props_file):
+                word = word.strip()
+                label = label.strip().split()
+
+                if len(label) == 0:  # end of sentence
+                    for i in xrange(len(one_seg[0])):
+                        a_kind_lable = [x[i] for x in one_seg]
+                        labels.append(a_kind_lable)
+
+                    if len(labels) >= 1:
+                        verb_list = []
+                        for x in labels[0]:
+                            if x != '-':
+                                verb_list.append(x)
+
+                        for i, lbl in enumerate(labels[1:]):
+                            cur_tag = 'O'
+                            is_in_bracket = False
+                            lbl_seq = []
+                            verb_word = ''
+                            for l in lbl:
+                                if l == '*' and is_in_bracket == False:
+                                    lbl_seq.append('O')
+                                elif l == '*' and is_in_bracket == True:
+                                    lbl_seq.append('I-' + cur_tag)
+                                elif l == '*)':
+                                    lbl_seq.append('I-' + cur_tag)
+                                    is_in_bracket = False
+                                elif l.find('(') != -1 and l.find(')') != -1:
+                                    cur_tag = l[1:l.find('*')]
+                                    lbl_seq.append('B-' + cur_tag)
+                                    is_in_bracket = False
+                                elif l.find('(') != -1 and l.find(')') == -1:
+                                    cur_tag = l[1:l.find('*')]
+                                    lbl_seq.append('B-' + cur_tag)
+                                    is_in_bracket = True
+                                else:
+                                    print 'error:', l
+
+                            yield sentences, verb_list[i], lbl_seq
+
+                    sentences = []
+                    labels = []
+                    one_seg = []
+                else:
+                    sentences.append(word)
+                    one_seg.append(label)
+
+    return reader
+
+
+def reader_creator(corpus_reader,
+                   word_dict=None,
+                   predicate_dict=None,
+                   label_dict=None):
+    def reader():
+        for sentence, predicate, labels in corpus_reader():
+
+            sen_len = len(sentence)
+
+            verb_index = labels.index('B-V')
+            mark = [0] * len(labels)
+            if verb_index > 0:
+                mark[verb_index - 1] = 1
+                ctx_n1 = sentence[verb_index - 1]
+            else:
+                ctx_n1 = 'bos'
+
+            if verb_index > 1:
+                mark[verb_index - 2] = 1
+                ctx_n2 = sentence[verb_index - 2]
+            else:
+                ctx_n2 = 'bos'
+
+            mark[verb_index] = 1
+            ctx_0 = sentence[verb_index]
+
+            if verb_index < len(labels) - 1:
+                mark[verb_index + 1] = 1
+                ctx_p1 = sentence[verb_index + 1]
+            else:
+                ctx_p1 = 'eos'
+
+            if verb_index < len(labels) - 2:
+                mark[verb_index + 2] = 1
+                ctx_p2 = sentence[verb_index + 2]
+            else:
+                ctx_p2 = 'eos'
+
+            word_idx = [word_dict.get(w, UNK_IDX) for w in sentence]
+            pred_idx = [predicate_dict.get(predicate)] * sen_len
+
+            ctx_n2_idx = [word_dict.get(ctx_n2, UNK_IDX)] * sen_len
+            ctx_n1_idx = [word_dict.get(ctx_n1, UNK_IDX)] * sen_len
+            ctx_0_idx = [word_dict.get(ctx_0, UNK_IDX)] * sen_len
+            ctx_p1_idx = [word_dict.get(ctx_p1, UNK_IDX)] * sen_len
+            ctx_p2_idx = [word_dict.get(ctx_p2, UNK_IDX)] * sen_len
+
+            label_idx = [label_dict.get(w) for w in labels]
+
+            yield word_idx, pred_idx, ctx_n2_idx, ctx_n1_idx, \
+              ctx_0_idx, ctx_p1_idx, ctx_p2_idx, mark, label_idx
+
+    return reader()
+
+
+def get_dict():
+    word_dict = load_dict(
+        common.download(WORDDICT_URL, 'conll05st', WORDDICT_MD5))
+    verb_dict = load_dict(
+        common.download(VERBDICT_URL, 'conll05st', VERBDICT_MD5))
+    label_dict = load_dict(
+        common.download(TRGDICT_URL, 'conll05st', TRGDICT_MD5))
+    return word_dict, verb_dict, label_dict
+
+
+def get_embedding():
+    return common.download(EMB_URL, 'conll05st', EMB_MD5)
+
+
+def test():
+    word_dict, verb_dict, label_dict = get_dict()
+    reader = corpus_reader(
+        common.download(DATA_URL, 'conll05st', DATA_MD5),
+        words_name='conll05st-release/test.wsj/words/test.wsj.words.gz',
+        props_name='conll05st-release/test.wsj/props/test.wsj.props.gz')
+    return reader_creator(reader, word_dict, verb_dict, label_dict)
+
+
+if __name__ == '__main__':
+    print get_embedding()
+    for f in test():
+        print f

From 0dd53294caaefdee1d7809ef08cd64db3ba8561d Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 02:32:51 +0800
Subject: [PATCH 040/153] add copyright

---
 python/paddle/v2/dataset/__init__.py          | 14 ++++++++++++++
 python/paddle/v2/dataset/cifar.py             | 14 ++++++++++++++
 python/paddle/v2/dataset/common.py            | 14 ++++++++++++++
 python/paddle/v2/dataset/conll05.py           | 14 ++++++++++++++
 python/paddle/v2/dataset/imdb.py              |  4 +---
 python/paddle/v2/dataset/imikolov.py          | 13 +++++++++++++
 python/paddle/v2/dataset/mnist.py             | 13 +++++++++++++
 python/paddle/v2/dataset/movielens.py         | 14 ++++++++++++++
 python/paddle/v2/dataset/tests/cifar_test.py  | 14 ++++++++++++++
 python/paddle/v2/dataset/tests/common_test.py | 14 ++++++++++++++
 python/paddle/v2/dataset/tests/imdb_test.py   | 14 ++++++++++++++
 python/paddle/v2/dataset/tests/mnist_test.py  | 14 ++++++++++++++
 12 files changed, 153 insertions(+), 3 deletions(-)

diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index 9647e9850332b..15460b820d86d 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import mnist
 
 __all__ = ['mnist']
diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py
index 77c54bd268b5d..5c6f5d85567fa 100644
--- a/python/paddle/v2/dataset/cifar.py
+++ b/python/paddle/v2/dataset/cifar.py
@@ -1,6 +1,20 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 """
 CIFAR dataset: https://www.cs.toronto.edu/~kriz/cifar.html
 """
+
 import cPickle
 import itertools
 import numpy
diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py
index fcf4437ffaf32..397c9e66d4954 100644
--- a/python/paddle/v2/dataset/common.py
+++ b/python/paddle/v2/dataset/common.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import requests
 import hashlib
 import os
diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py
index e9029063710f2..7c43c7c6340c2 100644
--- a/python/paddle/v2/dataset/conll05.py
+++ b/python/paddle/v2/dataset/conll05.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2.dataset.common
 import tarfile
 import gzip
diff --git a/python/paddle/v2/dataset/imdb.py b/python/paddle/v2/dataset/imdb.py
index 433e37380f840..ffd7d89049358 100644
--- a/python/paddle/v2/dataset/imdb.py
+++ b/python/paddle/v2/dataset/imdb.py
@@ -1,6 +1,3 @@
-# /usr/bin/env python
-# -*- coding:utf-8 -*-
-
 # Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,6 +14,7 @@
 """
 IMDB dataset: http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz
 """
+
 import paddle.v2.dataset.common
 import tarfile
 import Queue
diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py
index b3791ddad66e5..285d3eaca8317 100644
--- a/python/paddle/v2/dataset/imikolov.py
+++ b/python/paddle/v2/dataset/imikolov.py
@@ -1,3 +1,16 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 """
 imikolov's simple dataset: http://www.fit.vutbr.cz/~imikolov/rnnlm/
 """
diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py
index 1512a3c3189de..7cecb341647d1 100644
--- a/python/paddle/v2/dataset/mnist.py
+++ b/python/paddle/v2/dataset/mnist.py
@@ -1,3 +1,16 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 """
 MNIST dataset.
 """
diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py
index dcffcff2f58c6..c22bcfa38b5f5 100644
--- a/python/paddle/v2/dataset/movielens.py
+++ b/python/paddle/v2/dataset/movielens.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import zipfile
 from common import download
 import re
diff --git a/python/paddle/v2/dataset/tests/cifar_test.py b/python/paddle/v2/dataset/tests/cifar_test.py
index a2af45ecf5084..e0e18229da781 100644
--- a/python/paddle/v2/dataset/tests/cifar_test.py
+++ b/python/paddle/v2/dataset/tests/cifar_test.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2.dataset.cifar
 import unittest
 
diff --git a/python/paddle/v2/dataset/tests/common_test.py b/python/paddle/v2/dataset/tests/common_test.py
index 7d8406171b847..5babcef0eb434 100644
--- a/python/paddle/v2/dataset/tests/common_test.py
+++ b/python/paddle/v2/dataset/tests/common_test.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2.dataset.common
 import unittest
 import tempfile
diff --git a/python/paddle/v2/dataset/tests/imdb_test.py b/python/paddle/v2/dataset/tests/imdb_test.py
index e887af16634d2..c4d82f26895d7 100644
--- a/python/paddle/v2/dataset/tests/imdb_test.py
+++ b/python/paddle/v2/dataset/tests/imdb_test.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2.dataset.imdb
 import unittest
 import re
diff --git a/python/paddle/v2/dataset/tests/mnist_test.py b/python/paddle/v2/dataset/tests/mnist_test.py
index b4408cc2f590d..1d344cac3e748 100644
--- a/python/paddle/v2/dataset/tests/mnist_test.py
+++ b/python/paddle/v2/dataset/tests/mnist_test.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import paddle.v2.dataset.mnist
 import unittest
 

From 35ec5f0f1a5b497c0e927c98df882a1e9ab40d16 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 09:51:46 +0800
Subject: [PATCH 041/153] Support StaticInput

---
 python/paddle/v2/__init__.py             |  3 +-
 python/paddle/v2/layer.py                | 53 +++++++++++++-----------
 python/paddle/v2/networks.py             | 19 +++++++++
 python/paddle/v2/tests/test_rnn_layer.py | 41 +++++++++---------
 4 files changed, 72 insertions(+), 44 deletions(-)
 create mode 100644 python/paddle/v2/networks.py

diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py
index b31efe170dbf1..4dbcd3bb6b8b4 100644
--- a/python/paddle/v2/__init__.py
+++ b/python/paddle/v2/__init__.py
@@ -20,6 +20,7 @@
 import data_type
 import topology
 import data_feeder
+import networks
 from . import dataset
 from . import reader
 import attr
@@ -29,7 +30,7 @@
 __all__ = [
     'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer',
     'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader',
-    'topology'
+    'topology', 'networks'
 ]
 
 
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index bf5d653e8ae3e..82ccd8498a3db 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -109,9 +109,10 @@ def __real_func__():
 
 
 class Layer(object):
-    def __init__(self, name=None, parent_layers=None):
+    def __init__(self, name=None, size=None, parent_layers=None):
         assert isinstance(parent_layers, dict)
         self.name = name
+        self.size = size
         self.__parent_layers__ = parent_layers
 
     def to_proto(self, context):
@@ -173,7 +174,8 @@ def __init__(self, **kwargs):
                     other_kwargs[key] = kwargs[key]
 
             name = kwargs.get('name', None)
-            super(V2LayerImpl, self).__init__(name, parent_layers)
+            size = kwargs.get('size', None)
+            super(V2LayerImpl, self).__init__(name, size, parent_layers)
             self.__other_kwargs__ = other_kwargs
 
         if wrapper is not None:
@@ -220,9 +222,10 @@ class WithExtraParent(Layer):
     def extra_parent(self):
         return self.__extra_parent__
 
-    def __init__(self, name=None, parent_layers=None):
+    def __init__(self, name=None, size=None, parent_layers=None):
         self.__extra_parent__ = []
-        super(WithExtraParent, self).__init__(name, parent_layers)
+        super(WithExtraParent, self).__init__(
+            name=name, size=size, parent_layers=parent_layers)
 
     def append_extra_parent(self, parent):
         self.__extra_parent__.append(parent)
@@ -261,7 +264,8 @@ class MemoryV2(WithExtraParent):
     def __init__(self, name, size, **kwargs):
         self.name = name
         self.size = size
-        super(MemoryV2, self).__init__(name=name, parent_layers=dict())
+        super(MemoryV2, self).__init__(
+            name=name, size=size, parent_layers=dict())
         self.__kwargs__ = kwargs
         self.__boot_layer_name__ = None
         if 'boot_layer' in kwargs:
@@ -271,7 +275,9 @@ def __init__(self, name, size, **kwargs):
             st = inspect.stack()
             for i in xrange(len(st)):
                 locs = inspect.stack()[i][0].f_locals
-                for val in locs.viewvalues():
+                keys = locs.keys()
+                for key in keys:
+                    val = locs[key]
                     if isinstance(val, RecurrentLayerInput):
                         begin_of_current_rnn.append(val)
 
@@ -322,21 +328,15 @@ def to_proto_impl(self):
         return self.layer_output
 
 
-class StaticInputV2(Layer):
-    def __init__(self, input=None, **kwargs):
-        assert input is not None
-        self.__kwargs__ = kwargs
-        super(StaticInputV2, self).__init__(
-            name=input.name, parent_layers={'input': input})
-
-    def context_name(self):
-        return self.name + "#static_input"
-
-    def to_proto_impl(self, **kwargs):
-        args = dict()
-        args.update(kwargs)
-        args.update(self.__kwargs__)
-        return conf_helps.StaticInput(**args)
+class StaticInputV2(object):
+    def __init__(self, input, is_seq=False, size=None):
+        assert isinstance(input, LayerV2)
+        self.name = input.name
+        self.input = input
+        self.is_seq = is_seq
+        self.size = size
+        # TODO(qiaolongfei): add size
+        # assert input.size is not None or size is not None
 
 
 class MixedLayerV2(Layer):
@@ -370,9 +370,8 @@ def __init__(self,
         other_kwargs['act'] = act
         other_kwargs['bias_attr'] = bias_attr
         other_kwargs['layer_attr'] = layer_attr
-
         parent_layers = {"input": self.__inputs__}
-        super(MixedLayerV2, self).__init__(name, parent_layers)
+        super(MixedLayerV2, self).__init__(name, size, parent_layers)
         self.__other_kwargs__ = other_kwargs
 
     def __iadd__(self, other):
@@ -452,6 +451,12 @@ def recurrent_group(step, input, name=None):
     if not isinstance(input, collections.Sequence):
         input = [input]
 
+    # TODO(qiaolongfei) convert StaticInput to memory according to v2 recurrent_group
+    for i in xrange(len(input)):
+        cur_input = input[i]
+        if isinstance(cur_input, StaticInputV2):
+            input[i] = cur_input.input
+
     actual_input = [
         RecurrentLayerInput(
             recurrent_name=name,
@@ -512,7 +517,7 @@ def __layer_name_mapping_parent_names__(inname):
         lambda x: x in ['input1', 'input2', 'label', 'input', 'a', 'b',
                         'expand_as',
                         'weights', 'vectors', 'weight', 'score', 'left',
-                        'right'],
+                        'right', 'output_mem'],
         all_args)
 
 
diff --git a/python/paddle/v2/networks.py b/python/paddle/v2/networks.py
new file mode 100644
index 0000000000000..2877b56b18dc9
--- /dev/null
+++ b/python/paddle/v2/networks.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from layer import __convert_to_v2__
+
+simple_gru = __convert_to_v2__('simple_gru', ['input'])
+simple_attention = __convert_to_v2__(
+    'simple_attention', ['encoded_sequence', 'encoded_proj', 'decoder_state'])
diff --git a/python/paddle/v2/tests/test_rnn_layer.py b/python/paddle/v2/tests/test_rnn_layer.py
index 48aeb42391576..5fbbd20eb76bb 100644
--- a/python/paddle/v2/tests/test_rnn_layer.py
+++ b/python/paddle/v2/tests/test_rnn_layer.py
@@ -74,21 +74,28 @@ def test_sequence_rnn_multi_input(self):
         label_dim = 3
 
         def parse_old_rnn():
-            def step(y, wid):
-                z = conf_helps.embedding_layer(input=wid, size=word_dim)
-                mem = conf_helps.memory(name="rnn_state", size=hidden_dim)
-                out = conf_helps.fc_layer(
-                    input=[y, z, mem],
-                    size=hidden_dim,
-                    act=conf_helps.TanhActivation(),
-                    bias_attr=True,
-                    name="rnn_state")
-                return out
-
             def test():
                 data = conf_helps.data_layer(name="word", size=dict_dim)
                 label = conf_helps.data_layer(name="label", size=label_dim)
                 emb = conf_helps.embedding_layer(input=data, size=word_dim)
+                boot_layer = conf_helps.data_layer(name="boot", size=10)
+                boot_layer = conf_helps.fc_layer(
+                    name='boot_fc', input=boot_layer, size=10)
+
+                def step(y, wid):
+                    z = conf_helps.embedding_layer(input=wid, size=word_dim)
+                    mem = conf_helps.memory(
+                        name="rnn_state",
+                        size=hidden_dim,
+                        boot_layer=boot_layer)
+                    out = conf_helps.fc_layer(
+                        input=[y, z, mem],
+                        size=hidden_dim,
+                        act=conf_helps.TanhActivation(),
+                        bias_attr=True,
+                        name="rnn_state")
+                    return out
+
                 out = conf_helps.recurrent_group(
                     name="rnn", step=step, input=[emb, data])
 
@@ -111,11 +118,9 @@ def parse_new_rnn():
             label = layer.data(
                 name="label", type=data_type.dense_vector(label_dim))
             emb = layer.embedding(input=data, size=word_dim)
-
             boot_layer = layer.data(
                 name="boot", type=data_type.dense_vector(10))
-
-            boot_layer = layer.fc(name='wtf', input=boot_layer, size=10)
+            boot_layer = layer.fc(name='boot_fc', input=boot_layer, size=10)
 
             def step(y, wid):
                 z = layer.embedding(input=wid, size=word_dim)
@@ -141,11 +146,9 @@ def step(y, wid):
 
             return str(layer.parse_network(cost))
 
-        with open("/Users/baidu/old.out", 'w') as f:
-            print >> f, parse_old_rnn()
-        with open("/Users/baidu/new.out", "w") as f:
-            print >> f, parse_new_rnn()
-        # print ''.join(diff)
+        diff = difflib.unified_diff(parse_old_rnn().splitlines(1),
+                                    parse_new_rnn().splitlines(1))
+        print ''.join(diff)
 
 
 if __name__ == '__main__':

From b400c8f02c76ce74828cc999d6bef335cca18a57 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 11:47:33 +0800
Subject: [PATCH 042/153] update to latest

---
 python/paddle/v2/config_base.py | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py
index 035f96b0f2e97..be3e39a06ef9d 100644
--- a/python/paddle/v2/config_base.py
+++ b/python/paddle/v2/config_base.py
@@ -19,9 +19,10 @@
 
 
 class Layer(object):
-    def __init__(self, name=None, parent_layers=None):
+    def __init__(self, name=None, size=None, parent_layers=None):
         assert isinstance(parent_layers, dict)
         self.name = name
+        self.size = size
         self.__parent_layers__ = parent_layers
 
     def to_proto(self, context):
@@ -39,16 +40,30 @@ def to_proto(self, context):
                                self.__parent_layers__[layer_name])
             kwargs[layer_name] = v1_layer
 
-        if self.name is None:
+        if self.context_name() is None:
             return self.to_proto_impl(**kwargs)
-        elif self.name not in context:
-            context[self.name] = self.to_proto_impl(**kwargs)
+        elif self.context_name() not in context:
+            context[self.context_name()] = self.to_proto_impl(**kwargs)
 
-        return context[self.name]
+        if self.use_context_name():
+            return context[self.context_name()]
+        else:
+            return context[self.name]
 
     def to_proto_impl(self, **kwargs):
         raise NotImplementedError()
 
+    def context_name(self):
+        """
+        Context name means the context which stores `to_proto_impl` result.
+        If multiple layer share same context_name, the `to_proto_impl` of them
+        will be invoked only once.
+        """
+        return self.name
+
+    def use_context_name(self):
+        return False
+
 
 def __convert_to_v2__(method_name, parent_names, is_default_name=True):
     if is_default_name:
@@ -69,7 +84,8 @@ def __init__(self, **kwargs):
                     other_kwargs[key] = kwargs[key]
 
             name = kwargs.get('name', None)
-            super(V2LayerImpl, self).__init__(name, parent_layers)
+            size = kwargs.get('size', None)
+            super(V2LayerImpl, self).__init__(name, size, parent_layers)
             self.__other_kwargs__ = other_kwargs
 
         if wrapper is not None:

From 65aff91e863e90528eb779817e390746088f6431 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 12:51:35 +0800
Subject: [PATCH 043/153] Stash

---
 demo/recommendation/api_train_v2.py | 30 ++++++++++++++++++-----------
 python/paddle/v2/trainer.py         |  5 ++---
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py
index 3ff86c2c45e05..93e2a26f7431d 100644
--- a/demo/recommendation/api_train_v2.py
+++ b/demo/recommendation/api_train_v2.py
@@ -70,27 +70,35 @@ def main():
                                  parameters=parameters,
                                  update_equation=paddle.optimizer.Adam(
                                      learning_rate=1e-4))
+    reader_dict = {
+        'user_id': 0,
+        'gender_id': 1,
+        'age_id': 2,
+        'job_id': 3,
+        'movie_id': 4,
+        'category_id': 5,
+        'movie_title': 6,
+        'score': 7
+    }
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
             if event.batch_id % 100 == 0:
                 print "Pass %d Batch %d Cost %.2f" % (
                     event.pass_id, event.batch_id, event.cost)
+        elif isinstance(event, paddle.event.EndPass):
+            result = trainer.test(reader=paddle.reader.batched(
+                paddle.dataset.movielens.test(), batch_size=256))
+            print result.cost
 
     trainer.train(
         reader=paddle.reader.batched(
-            paddle.dataset.movielens.train(), batch_size=256),
+            paddle.reader.shuffle(
+                paddle.dataset.movielens.train(), buf_size=8192),
+            batch_size=256),
         event_handler=event_handler,
-        reader_dict={
-            'user_id': 0,
-            'gender_id': 1,
-            'age_id': 2,
-            'job_id': 3,
-            'movie_id': 4,
-            'category_id': 5,
-            'movie_title': 6,
-            'score': 7
-        })
+        reader_dict=reader_dict,
+        num_passes=10)
 
 
 if __name__ == '__main__':
diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index 5003f55f3e0d1..f45b3ec9741df 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -123,9 +123,8 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
                 for each_param in self.__gradient_machine__.getParameters():
                     updater.update(each_param)
                 # Get cost. We use numpy to calculate total cost for this batch.
-                cost_vec = out_args.getSlotValue(0)
-                cost_vec = cost_vec.copyToNumpyMat()
-                cost = cost_vec.sum() / len(data_batch)
+                cost_sum = out_args.sumCosts()
+                cost = cost_sum / len(data_batch)
                 updater.finishBatch(cost)
                 batch_evaluator.finish()
                 event_handler(

From 1524f2041ee3e5dd6bf1613afeb16ed3884939e9 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 13:03:41 +0800
Subject: [PATCH 044/153] Add testing cost.

---
 demo/mnist/api_train_v2.py  |  9 +++++----
 python/paddle/v2/event.py   |  3 ++-
 python/paddle/v2/trainer.py | 12 ++++++++----
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py
index 06beb7024d1fd..00d102217513c 100644
--- a/demo/mnist/api_train_v2.py
+++ b/demo/mnist/api_train_v2.py
@@ -30,10 +30,11 @@ def event_handler(event):
                 result = trainer.test(reader=paddle.reader.batched(
                     paddle.dataset.mnist.test(), batch_size=256))
 
-                print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % (
-                    event.pass_id, event.batch_id, event.cost, event.metrics,
-                    result.metrics)
-
+                print "Pass %d, Batch %d, Cost %.2f, %s, " \
+                      "Testing cost %.2f metrics %s" % (
+                          event.pass_id, event.batch_id, event.cost,
+                          event.metrics,
+                          result.cost, result.metrics)
         else:
             pass
 
diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py
index a78bcf076cc65..a429e36b63c9e 100644
--- a/python/paddle/v2/event.py
+++ b/python/paddle/v2/event.py
@@ -34,8 +34,9 @@ def metrics(self):
 
 
 class TestResult(WithMetric):
-    def __init__(self, evaluator):
+    def __init__(self, evaluator, cost):
         super(TestResult, self).__init__(evaluator)
+        self.cost = cost
 
 
 class BeginPass(object):
diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index 5003f55f3e0d1..58ec6dd5fe500 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -123,9 +123,8 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
                 for each_param in self.__gradient_machine__.getParameters():
                     updater.update(each_param)
                 # Get cost. We use numpy to calculate total cost for this batch.
-                cost_vec = out_args.getSlotValue(0)
-                cost_vec = cost_vec.copyToNumpyMat()
-                cost = cost_vec.sum() / len(data_batch)
+                cost_sum = out_args.sumCosts()
+                cost = cost_sum / len(data_batch)
                 updater.finishBatch(cost)
                 batch_evaluator.finish()
                 event_handler(
@@ -154,13 +153,18 @@ def test(self, reader, reader_dict=None):
         evaluator = self.__gradient_machine__.makeEvaluator()
         out_args = api.Arguments.createArguments(0)
         evaluator.start()
+        total_cost = 0
+        num_samples = 0.0
         for data_batch in reader():
+            num_samples += len(data_batch)
             self.__gradient_machine__.forward(
                 feeder(data_batch), out_args, api.PASS_TEST)
+            total_cost += out_args.sumCosts()
             self.__gradient_machine__.eval(evaluator)
 
         evaluator.finish()
-        return v2_event.TestResult(evaluator=evaluator)
+        return v2_event.TestResult(
+            evaluator=evaluator, cost=total_cost / num_samples)
 
 
 def __check_train_args__(reader, event_handler, **kwargs):

From ba1c978514c05500a858644a09033e2afc5e1f7a Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 13:41:41 +0800
Subject: [PATCH 045/153] close file and compare the result with the old way.

---
 python/paddle/v2/dataset/conll05.py | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py
index 7c43c7c6340c2..b6a4c252d12d7 100644
--- a/python/paddle/v2/dataset/conll05.py
+++ b/python/paddle/v2/dataset/conll05.py
@@ -12,7 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import paddle.v2.dataset.common
+#import paddle.v2.dataset.common
+import common
 import tarfile
 import gzip
 import itertools
@@ -49,11 +50,9 @@ def load_dict(filename):
 
 def corpus_reader(data_path, words_name, props_name):
     """
-    Read one corpus by corpus name. It returns an iterator. Each element of
+    Read one corpus. It returns an iterator. Each element of
     this iterator is a tuple including sentence and labels. The sentence is
     consist of a list of word IDs. The labels include a list of label IDs.
-    :param name: corpus name.
-    :type name: basestring
     :return: a iterator of data.
     :rtype: iterator
     """
@@ -104,7 +103,8 @@ def reader():
                                     lbl_seq.append('B-' + cur_tag)
                                     is_in_bracket = True
                                 else:
-                                    print 'error:', l
+                                    raise RuntimeError('Unexpected label: %s' %
+                                                       l)
 
                             yield sentences, verb_list[i], lbl_seq
 
@@ -115,6 +115,10 @@ def reader():
                     sentences.append(word)
                     one_seg.append(label)
 
+        pf.close()
+        wf.close()
+        tf.close()
+
     return reader
 
 

From d3c755df3fe6009ed2cde1b5dca41196e4024aa7 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Thu, 2 Mar 2017 13:41:51 +0800
Subject: [PATCH 046/153] Refine code

---
 demo/sentiment/train_v2.py | 95 ++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 56 deletions(-)

diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py
index 779bfee5b6eca..3d595fad30b71 100644
--- a/demo/sentiment/train_v2.py
+++ b/demo/sentiment/train_v2.py
@@ -1,3 +1,4 @@
+import sys
 from os.path import join as join_path
 import paddle.trainer_config_helpers.attrs as attrs
 from paddle.trainer_config_helpers.poolings import MaxPooling
@@ -188,88 +189,69 @@ def stacked_lstm_net(input_dim,
     return cost
 
 
-def data_reader():
-    data_dir = "./data/pre-imdb"
-    train_file = "train_part_000"
-    test_file = "test_part_000"
-    dict_file = "dict.txt"
-    train_file = join_path(data_dir, train_file)
-    test_file = join_path(data_dir, test_file)
-    dict_file = join_path(data_dir, dict_file)
-
-    with open(dict_file, 'r') as fdict, open(train_file, 'r') as fdata:
-        dictionary = dict()
-        for i, line in enumerate(fdict):
-            dictionary[line.split('\t')[0]] = i
-
-        for line_count, line in enumerate(fdata):
-            label, comment = line.strip().split('\t\t')
-            label = int(label)
-            words = comment.split()
-            word_slot = [dictionary[w] for w in words if w in dictionary]
-            yield (word_slot, label)
-
-
-def test_reader():
-    data_dir = "./data/pre-imdb"
-    train_file = "train_part_000"
-    test_file = "test_part_000"
-    dict_file = "dict.txt"
-    train_file = join_path(data_dir, train_file)
-    test_file = join_path(data_dir, test_file)
-    dict_file = join_path(data_dir, dict_file)
-
-    with open(dict_file, 'r') as fdict, open(test_file, 'r') as ftest:
-        dictionary = dict()
-        for i, line in enumerate(fdict):
-            dictionary[line.split('\t')[0]] = i
-
-        for line_count, line in enumerate(ftest):
-            label, comment = line.strip().split('\t\t')
-            label = int(label)
-            words = comment.split()
-            word_slot = [dictionary[w] for w in words if w in dictionary]
-            yield (word_slot, label)
+def data_reader(data_file, dict_file):
+    def reader():
+        with open(dict_file, 'r') as fdict, open(data_file, 'r') as fdata:
+            dictionary = dict()
+            for i, line in enumerate(fdict):
+                dictionary[line.split('\t')[0]] = i
+
+            for line_count, line in enumerate(fdata):
+                label, comment = line.strip().split('\t\t')
+                label = int(label)
+                words = comment.split()
+                word_slot = [dictionary[w] for w in words if w in dictionary]
+                yield (word_slot, label)
+
+    return reader
 
 
 if __name__ == '__main__':
-    data_dir = "./data/pre-imdb"
-    train_list = "train.list"
-    test_list = "test.list"
-    dict_file = "dict.txt"
-    dict_dim = len(open(join_path(data_dir, "dict.txt")).readlines())
-    class_dim = len(open(join_path(data_dir, 'labels.list')).readlines())
-    is_predict = False
+    # data file
+    train_file = "./data/pre-imdb/train_part_000"
+    test_file = "./data/pre-imdb/test_part_000"
+    dict_file = "./data/pre-imdb/dict.txt"
+    labels = "./data/pre-imdb/labels.list"
 
     # init
     paddle.init(use_gpu=True, trainer_count=4)
 
     # network config
-    # cost = convolution_net(dict_dim, class_dim=class_dim, is_predict=is_predict)
-    cost = stacked_lstm_net(
-        dict_dim, class_dim=class_dim, stacked_num=3, is_predict=is_predict)
+    dict_dim = len(open(dict_file).readlines())
+    class_dim = len(open(labels).readlines())
+
+    # 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)
 
     # create parameters
     parameters = paddle.parameters.create(cost)
 
+    # 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))
 
+    # End batch and end pass event handler
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
             if event.batch_id % 100 == 0:
-                print "Pass %d, Batch %d, Cost %f, %s" % (
+                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):
             result = trainer.test(
                 reader=paddle.reader.batched(
-                    test_reader, batch_size=128),
+                    data_reader(test_file, dict_file), batch_size=128),
                 reader_dict={'word': 0,
                              'label': 1})
-            print "Test with Pass %d, %s" % (event.pass_id, result.metrics)
+            print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
 
+    # create trainer
     trainer = paddle.trainer.SGD(cost=cost,
                                  parameters=parameters,
                                  update_equation=adam_optimizer)
@@ -277,7 +259,8 @@ def event_handler(event):
     trainer.train(
         reader=paddle.reader.batched(
             paddle.reader.shuffle(
-                data_reader, buf_size=4096), batch_size=128),
+                data_reader(train_file, dict_file), buf_size=4096),
+            batch_size=128),
         event_handler=event_handler,
         reader_dict={'word': 0,
                      'label': 1},

From 4dd2e40bd07c0ff1123d35328687f53682e67a62 Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 13:55:41 +0800
Subject: [PATCH 047/153] remove comments

---
 python/paddle/v2/dataset/conll05.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py
index b6a4c252d12d7..7874161a05968 100644
--- a/python/paddle/v2/dataset/conll05.py
+++ b/python/paddle/v2/dataset/conll05.py
@@ -12,8 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#import paddle.v2.dataset.common
-import common
+import paddle.v2.dataset.common
 import tarfile
 import gzip
 import itertools

From b250fceab5e8f9f0c763d1faa054c078fc4db669 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 14:28:15 +0800
Subject: [PATCH 048/153] Add save/load parameters.

---
 demo/mnist/.gitignore          |  1 +
 demo/mnist/api_train_v2.py     | 11 ++++++++++-
 python/paddle/v2/parameters.py | 27 +++++++++++++++++++++++++++
 python/paddle/v2/trainer.py    |  2 +-
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/demo/mnist/.gitignore b/demo/mnist/.gitignore
index 8bd9837523ccf..9c552159be6f7 100644
--- a/demo/mnist/.gitignore
+++ b/demo/mnist/.gitignore
@@ -5,3 +5,4 @@ plot.png
 train.log
 *pyc
 .ipynb_checkpoints
+params.pkl
diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py
index a59b30ccdb2ed..73fcb9d79d32c 100644
--- a/demo/mnist/api_train_v2.py
+++ b/demo/mnist/api_train_v2.py
@@ -1,4 +1,5 @@
 import paddle.v2 as paddle
+import cPickle
 
 
 def main():
@@ -16,7 +17,11 @@ def main():
                                 act=paddle.activation.Softmax())
     cost = paddle.layer.classification_cost(input=inference, label=label)
 
-    parameters = paddle.parameters.create(cost)
+    try:
+        with open('params.pkl', 'r') as f:
+            parameters = cPickle.load(f)
+    except IOError:
+        parameters = paddle.parameters.create(cost)
 
     adam_optimizer = paddle.optimizer.Adam(learning_rate=0.01)
 
@@ -34,6 +39,10 @@ def event_handler(event):
                     event.pass_id, event.batch_id, event.cost, event.metrics,
                     result.metrics)
 
+                with open('params.pkl', 'w') as f:
+                    cPickle.dump(
+                        parameters, f, protocol=cPickle.HIGHEST_PROTOCOL)
+
         else:
             pass
 
diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py
index 2a6026bcab1c8..d8c3a73b0ea9e 100644
--- a/python/paddle/v2/parameters.py
+++ b/python/paddle/v2/parameters.py
@@ -222,6 +222,33 @@ def append_gradient_machine(self, gradient_machine):
 
         self.__gradient_machines__.append(gradient_machine)
 
+    def __getstate__(self):
+        params = {}
+        for name in self.names():
+            params[name] = self.get(name)
+
+        param_conf = {}
+        for name in self.__param_conf__:
+            conf = self.__param_conf__[name]
+            assert isinstance(conf, ParameterConfig)
+            param_conf[name] = conf.SerializeToString()
+
+        return {'conf': param_conf, 'params': params}
+
+    def __setstate__(self, obj):
+        Parameters.__init__(self)
+
+        def __impl__(conf, params):
+            for name in conf:
+                p = ParameterConfig()
+                p.ParseFromString(conf[name])
+                self.__append_config__(p)
+            for name in params:
+                shape = self.get_shape(name)
+                self.set(name, params[name].reshape(shape))
+
+        __impl__(**obj)
+
 
 def __get_parameter_in_gradient_machine__(gradient_machine, name):
     """
diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index 5003f55f3e0d1..709566ca4475f 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -66,9 +66,9 @@ def __init__(self, cost, parameters, update_equation):
             self.__topology_in_proto__, api.CREATE_MODE_NORMAL,
             self.__optimizer__.enable_types())
         assert isinstance(gm, api.GradientMachine)
-        parameters.append_gradient_machine(gm)
         self.__gradient_machine__ = gm
         self.__gradient_machine__.randParameters()
+        parameters.append_gradient_machine(gm)
 
     def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
         """

From fd5778ab2368ddd47b9ab62588c3fdc2e57fd94e Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 14:41:15 +0800
Subject: [PATCH 049/153] Fix unittest

---
 .travis.yml                          | 2 +-
 paddle/scripts/docker/Dockerfile     | 2 +-
 paddle/scripts/docker/Dockerfile.gpu | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 4fb2ca938795b..28d1f51be7107 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,7 +57,7 @@ before_install:
   - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi
   # Paddle is using protobuf 3.1 currently. Protobuf 3.2 breaks the compatibility. So we specify the python 
   # protobuf version.
-  - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx_rtd_theme virtualenv pre-commit requests==2.9.2 LinkChecker
+  - pip install numpy wheel 'protobuf==3.1' sphinx recommonmark sphinx-rtd-theme==0.1.9 virtualenv pre-commit requests==2.9.2 LinkChecker
 script:
   - paddle/scripts/travis/main.sh
 notifications:
diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile
index 23f4d43588767..98eaa15a0fdf2 100644
--- a/paddle/scripts/docker/Dockerfile
+++ b/paddle/scripts/docker/Dockerfile
@@ -42,7 +42,7 @@ RUN pip install --upgrade pip && \
     pip install -U 'protobuf==3.1.0' && \
     pip install -U wheel pillow BeautifulSoup && \
     pip install -U docopt PyYAML sphinx && \
-    pip install -U sphinx_rtd_theme recommonmark && \
+    pip install -U sphinx-rtd-theme==0.1.9 recommonmark && \
     pip install -U pre-commit 'requests==2.9.2' jupyter
 
 RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \
diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu
index a975e580e4ed9..4d30ccdd2b5de 100644
--- a/paddle/scripts/docker/Dockerfile.gpu
+++ b/paddle/scripts/docker/Dockerfile.gpu
@@ -42,7 +42,7 @@ RUN pip install --upgrade pip && \
     pip install -U 'protobuf==3.1.0' && \
     pip install -U wheel pillow BeautifulSoup && \
     pip install -U docopt PyYAML sphinx && \
-    pip install -U sphinx_rtd_theme recommonmark && \
+    pip install -U sphinx-rtd-theme==0.1.9 recommonmark && \
     pip install -U pre-commit 'requests==2.9.2' jupyter
 
 RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \

From 0dc68a2c90e2432a3b5678881268fa22e1f0d990 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 14:48:51 +0800
Subject: [PATCH 050/153] add getNonStaticParameters

---
 demo/image_classification/api_v2_train.py |  4 ++--
 paddle/api/GradientMachine.cpp            | 14 ++++++++++++++
 paddle/api/PaddleAPI.h                    |  3 +++
 paddle/py_paddle/util.py                  |  6 ++++++
 4 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py
index e6e4307242057..0b4dc4d929826 100644
--- a/demo/image_classification/api_v2_train.py
+++ b/demo/image_classification/api_v2_train.py
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License
 
-from api_v2_vgg import resnet_cifar10
-from api_v2_resnet import vgg_bn_drop
+from api_v2_vgg import vgg_bn_drop
+from api_v2_resnet import resnet_cifar10
 import paddle.v2 as paddle
 
 
diff --git a/paddle/api/GradientMachine.cpp b/paddle/api/GradientMachine.cpp
index 538ca2999f8f0..dcb5fe086fdcc 100644
--- a/paddle/api/GradientMachine.cpp
+++ b/paddle/api/GradientMachine.cpp
@@ -142,6 +142,20 @@ Parameter* GradientMachine::getParameter(size_t i) throw(RangeError) {
   }
 }
 
+size_t GradientMachine::getNonStaticParameterSize() const {
+  return m->machine->getNonStaticParameters().size();
+}
+
+Parameter* GradientMachine::getNonStaticParameter(size_t i) throw(RangeError) {
+  auto params = m->machine->getNonStaticParameters();
+  if (i < params.size()) {
+    return Parameter::createFromSharedPtr(
+        &m->machine->getNonStaticParameters()[i]);
+  } else {
+    throw RangeError();
+  }
+}
+
 void GradientMachine::randParameters() { m->machine->randParameters(); }
 
 Arguments* GradientMachine::getLayerOutput(const std::string& layerName) const
diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h
index 1831b8e170087..764946cf5341c 100644
--- a/paddle/api/PaddleAPI.h
+++ b/paddle/api/PaddleAPI.h
@@ -768,6 +768,9 @@ class GradientMachine {
   size_t getParameterSize() const;
   Parameter* getParameter(size_t i) throw(RangeError);
 
+  size_t getNonStaticParameterSize() const;
+  Parameter* getNonStaticParameter(size_t i) throw(RangeError);
+
   void randParameters();
 
   Arguments* getLayerOutput(const std::string& layerName) const
diff --git a/paddle/py_paddle/util.py b/paddle/py_paddle/util.py
index a708def1d2d7f..fb337b8af378e 100644
--- a/paddle/py_paddle/util.py
+++ b/paddle/py_paddle/util.py
@@ -195,6 +195,12 @@ def getParameters(self):
 
     swig_paddle.GradientMachine.getParameters = getParameters
 
+    def getNonStaticParameters(self):
+        return (self.getNonStaticParameter(i)
+                for i in xrange(self.getNonStaticParameterSize()))
+
+    swig_paddle.GradientMachine.getParameters = getParameters
+
     def getLayerOutputs(self, layerNames):
         """
         getLayerOutputs. get outputs of layers and return a numpy matrix dict.

From ce3a399d3d5654804c8f258cb4b2d0455e013606 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 14:54:56 +0800
Subject: [PATCH 051/153] update util.py

---
 paddle/py_paddle/util.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/paddle/py_paddle/util.py b/paddle/py_paddle/util.py
index fb337b8af378e..1c9455fab5f9c 100644
--- a/paddle/py_paddle/util.py
+++ b/paddle/py_paddle/util.py
@@ -199,7 +199,7 @@ def getNonStaticParameters(self):
         return (self.getNonStaticParameter(i)
                 for i in xrange(self.getNonStaticParameterSize()))
 
-    swig_paddle.GradientMachine.getParameters = getParameters
+    swig_paddle.GradientMachine.getNonStaticParameters = getNonStaticParameters
 
     def getLayerOutputs(self, layerNames):
         """

From e4007337ae88d0874f8d7c0bc41e9aa641de38b7 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 15:09:21 +0800
Subject: [PATCH 052/153] Follow comments

---
 python/paddle/v2/trainer.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index 58ec6dd5fe500..21a1642c36a2c 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -122,7 +122,6 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
                 self.__gradient_machine__.eval(batch_evaluator)
                 for each_param in self.__gradient_machine__.getParameters():
                     updater.update(each_param)
-                # Get cost. We use numpy to calculate total cost for this batch.
                 cost_sum = out_args.sumCosts()
                 cost = cost_sum / len(data_batch)
                 updater.finishBatch(cost)

From c9bb48b308807f80b3ba238cafb97ba4b0eda983 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 15:09:26 +0800
Subject: [PATCH 053/153] support calculate size

---
 python/paddle/v2/config_base.py |   7 +-
 python/paddle/v2/layer.py       | 110 ++++++++++++++++++++------------
 2 files changed, 75 insertions(+), 42 deletions(-)

diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py
index be3e39a06ef9d..573539a30cc1d 100644
--- a/python/paddle/v2/config_base.py
+++ b/python/paddle/v2/config_base.py
@@ -22,7 +22,7 @@ class Layer(object):
     def __init__(self, name=None, size=None, parent_layers=None):
         assert isinstance(parent_layers, dict)
         self.name = name
-        self.size = size
+        self.__contex__ = {}
         self.__parent_layers__ = parent_layers
 
     def to_proto(self, context):
@@ -44,7 +44,7 @@ def to_proto(self, context):
             return self.to_proto_impl(**kwargs)
         elif self.context_name() not in context:
             context[self.context_name()] = self.to_proto_impl(**kwargs)
-
+        self.__contex__ = context
         if self.use_context_name():
             return context[self.context_name()]
         else:
@@ -64,6 +64,9 @@ def context_name(self):
     def use_context_name(self):
         return False
 
+    def calcalted_size(self):
+        return self.__contex__[self.context_name()].size
+
 
 def __convert_to_v2__(method_name, parent_names, is_default_name=True):
     if is_default_name:
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index e24244a48c96d..a97518ed52562 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -197,6 +197,10 @@ def __init__(self, name, size, **kwargs):
                     val = locs[key]
                     if isinstance(val, RecurrentLayerInput):
                         begin_of_current_rnn.append(val)
+                    elif isinstance(val, collections.Sequence):
+                        for v in val:
+                            if isinstance(v, RecurrentLayerInput):
+                                begin_of_current_rnn.append(v)
 
                 if begin_of_current_rnn:
                     break
@@ -216,7 +220,13 @@ def to_proto_impl(self, context, **kwargs):
 
         if self.__boot_layer_name__ is not None:
             args['boot_layer'] = context[self.__boot_layer_name__]
-        return conf_helps.memory(name=self.name, size=self.size, **args)
+
+        if callable(self.size):
+            real_size = self.size()
+        else:
+            real_size = self.size
+        args['size'] = real_size
+        return conf_helps.memory(name=self.name, **args)
 
     def context_name(self):
         return self.name + "#memory"
@@ -311,6 +321,12 @@ def to_proto_impl(self, **kwargs):
             args[each] = kwargs[each]
         for each in self.__other_kwargs__:
             args[each] = self.__other_kwargs__[each]
+        size = args.get('size', None)
+        if callable(size):
+            real_size = size()
+        else:
+            real_size = size
+        args['size'] = real_size
         return getattr(conf_helps, self.__method_name__)(**args)
 
 
@@ -363,53 +379,15 @@ def to_proto_impl(self, **kwargs):
         RecurrentLayerGroupEnd(name=self.__recurrent_name__)
 
 
-@wrap_name_default()
-def recurrent_group(step, input, name=None):
-    if not isinstance(input, collections.Sequence):
-        input = [input]
-
-    # TODO(qiaolongfei) convert StaticInput to memory according to v2 recurrent_group
-    for i in xrange(len(input)):
-        cur_input = input[i]
-        if isinstance(cur_input, StaticInputV2):
-            input[i] = cur_input.input
-
-    actual_input = [
-        RecurrentLayerInput(
-            recurrent_name=name,
-            index=i,
-            parent_layers={'recurrent_inputs': input})
-        for i in xrange(len(input))
-    ]
-
-    actual_output = step(*actual_input)
-
-    if not isinstance(actual_output, collections.Sequence):
-        actual_output = [actual_output]
-
-    retv = [
-        RecurrentLayerOutput(
-            recurrent_name=name,
-            index=i,
-            parent_layers={'recurrent_outputs': actual_output})
-        for i in xrange(len(actual_output))
-    ]
-    if len(retv) == 1:
-        return retv[0]
-    else:
-        return retv
-
-
 LayerV2 = Layer
 data = DataLayerV2
 AggregateLevel = conf_helps.layers.AggregateLevel
 ExpandLevel = conf_helps.layers.ExpandLevel
-recurrent_group = recurrent_group
 memory = MemoryV2
 
 
 def __layer_name_mapping__(inname):
-    if inname in ['data_layer', 'memory', 'mixed_layer']:
+    if inname in ['data_layer', 'memory', 'mixed_layer', 'recurrent_group']:
         # Do Not handle these layers
         return
     elif inname == 'maxid_layer':
@@ -469,3 +447,55 @@ def __convert_layer__(_new_name_, _old_name_, _parent_names_):
 for op in operator_list:
     globals()[op[0]] = __convert_to_v2__(
         op[0], parent_names=op[1], is_default_name=False)
+
+
+@wrap_name_default()
+def recurrent_group(step, input, name=None):
+    if not isinstance(input, collections.Sequence):
+        input = [input]
+
+    non_static_inputs = filter(lambda x: not isinstance(x, StaticInputV2),
+                               input)
+    actual_input = [
+        RecurrentLayerInput(
+            recurrent_name=name,
+            index=i,
+            parent_layers={'recurrent_inputs': non_static_inputs})
+        for i in xrange(len(non_static_inputs))
+    ]
+
+    def __real_step__(*args):
+        rnn_input = list(args)
+        static_inputs = filter(lambda x: isinstance(x, StaticInputV2), input)
+        for static_input in static_inputs:
+            mem_name = "__%s_memory__" % static_input.input.name
+            print memory
+            mem = memory(
+                name=mem_name,
+                is_seq=static_input.is_seq,
+                size=static_input.input.calcalted_size,
+                boot_layer=static_input.input)
+            with mixed(
+                    name=mem_name,
+                    size=static_input.input.calcalted_size,
+                    act=activation.Identity()) as mix:
+                mix += identity_projection(input=mem)
+            rnn_input.insert(input.index(static_input), mix)
+        return step(*rnn_input)
+
+    actual_output = __real_step__(*actual_input)
+
+    if not isinstance(actual_output, collections.Sequence):
+        actual_output = [actual_output]
+
+    retv = [
+        RecurrentLayerOutput(
+            recurrent_name=name,
+            index=i,
+            parent_layers={'recurrent_outputs': actual_output})
+        for i in xrange(len(actual_output))
+    ]
+    if len(retv) == 1:
+        return retv[0]
+    else:
+        return retv

From 69bf77fd1e71fc57bf0f15820a9dd34bd98c79b6 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 15:09:49 +0800
Subject: [PATCH 054/153] fix trainer v2 getNonStaticParameters

---
 python/paddle/v2/trainer.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index bf8b181e42064..44ba9d7ae1167 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -113,7 +113,7 @@ def train(self,
                 gm.forwardBackward(feeder(data_batch), out_args, pass_type)
                 gm.eval(pass_evaluator)
                 gm.eval(batch_evaluator)
-                for each_param in gm.getParameters():
+                for each_param in gm.getNonStaticParameters():
                     updater.update(each_param)
                 # Get cost. We use numpy to calculate total cost for this batch.
                 cost_vec = out_args.getSlotValue(0)

From 3b8a8f81142e7eaea06e8e43e41bcb7bc73b0e09 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 15:10:54 +0800
Subject: [PATCH 055/153] Follow comments

---
 demo/mnist/api_train_v2.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py
index 00d102217513c..575a32b3222a8 100644
--- a/demo/mnist/api_train_v2.py
+++ b/demo/mnist/api_train_v2.py
@@ -30,7 +30,7 @@ def event_handler(event):
                 result = trainer.test(reader=paddle.reader.batched(
                     paddle.dataset.mnist.test(), batch_size=256))
 
-                print "Pass %d, Batch %d, Cost %.2f, %s, " \
+                print "Pass %d, Batch %d, Cost %.2f, %s\n" \
                       "Testing cost %.2f metrics %s" % (
                           event.pass_id, event.batch_id, event.cost,
                           event.metrics,

From 1164c287b9db46abd9e591ddebe720bc3e08e22d Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 15:14:34 +0800
Subject: [PATCH 056/153] add datasets import

---
 python/paddle/v2/dataset/__init__.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index 9647e9850332b..d222739ba2c0f 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -1,3 +1,7 @@
 import mnist
+import imikolov
+import imdb
+import cifar
+import movielens
 
-__all__ = ['mnist']
+__all__ = ['mnist', 'imikolov', 'imdb', 'cifar', 'movielens']

From f9e6aa2c31aa6bc5269cd66eaa8705b0b98af989 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 15:23:19 +0800
Subject: [PATCH 057/153] refine code

---
 python/paddle/v2/config_base.py | 12 ++++++----
 python/paddle/v2/layer.py       | 40 +++++++++++++++++----------------
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py
index 573539a30cc1d..fa2ccec6c3270 100644
--- a/python/paddle/v2/config_base.py
+++ b/python/paddle/v2/config_base.py
@@ -19,7 +19,7 @@
 
 
 class Layer(object):
-    def __init__(self, name=None, size=None, parent_layers=None):
+    def __init__(self, name=None, parent_layers=None):
         assert isinstance(parent_layers, dict)
         self.name = name
         self.__contex__ = {}
@@ -64,7 +64,12 @@ def context_name(self):
     def use_context_name(self):
         return False
 
-    def calcalted_size(self):
+    def calculate_size(self):
+        """
+        lazy calculate size of the layer, should be called when to_proto_impl of
+        this layer is called.
+        :return:
+        """
         return self.__contex__[self.context_name()].size
 
 
@@ -87,8 +92,7 @@ def __init__(self, **kwargs):
                     other_kwargs[key] = kwargs[key]
 
             name = kwargs.get('name', None)
-            size = kwargs.get('size', None)
-            super(V2LayerImpl, self).__init__(name, size, parent_layers)
+            super(V2LayerImpl, self).__init__(name, parent_layers)
             self.__other_kwargs__ = other_kwargs
 
         if wrapper is not None:
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index a97518ed52562..0d8b59cfd29c9 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -139,10 +139,10 @@ class WithExtraParent(Layer):
     def extra_parent(self):
         return self.__extra_parent__
 
-    def __init__(self, name=None, size=None, parent_layers=None):
+    def __init__(self, name=None, parent_layers=None):
         self.__extra_parent__ = []
         super(WithExtraParent, self).__init__(
-            name=name, size=size, parent_layers=parent_layers)
+            name=name, parent_layers=parent_layers)
 
     def append_extra_parent(self, parent):
         self.__extra_parent__.append(parent)
@@ -178,11 +178,9 @@ def to_proto(self, context):
 
 
 class MemoryV2(WithExtraParent):
-    def __init__(self, name, size, **kwargs):
+    def __init__(self, name, **kwargs):
         self.name = name
-        self.size = size
-        super(MemoryV2, self).__init__(
-            name=name, size=size, parent_layers=dict())
+        super(MemoryV2, self).__init__(name=name, parent_layers=dict())
         self.__kwargs__ = kwargs
         self.__boot_layer_name__ = None
         if 'boot_layer' in kwargs:
@@ -221,11 +219,14 @@ def to_proto_impl(self, context, **kwargs):
         if self.__boot_layer_name__ is not None:
             args['boot_layer'] = context[self.__boot_layer_name__]
 
-        if callable(self.size):
-            real_size = self.size()
-        else:
-            real_size = self.size
-        args['size'] = real_size
+        size = args.get('size', None)
+        if size is not None:
+            if callable(size):
+                real_size = size()
+            else:
+                real_size = size
+            print(real_size)
+            args['size'] = real_size
         return conf_helps.memory(name=self.name, **args)
 
     def context_name(self):
@@ -298,7 +299,7 @@ def __init__(self,
         other_kwargs['bias_attr'] = bias_attr
         other_kwargs['layer_attr'] = layer_attr
         parent_layers = {"input": self.__inputs__}
-        super(MixedLayerV2, self).__init__(name, size, parent_layers)
+        super(MixedLayerV2, self).__init__(name, parent_layers)
         self.__other_kwargs__ = other_kwargs
 
     def __iadd__(self, other):
@@ -322,11 +323,12 @@ def to_proto_impl(self, **kwargs):
         for each in self.__other_kwargs__:
             args[each] = self.__other_kwargs__[each]
         size = args.get('size', None)
-        if callable(size):
-            real_size = size()
-        else:
-            real_size = size
-        args['size'] = real_size
+        if size is not None:
+            if callable(size):
+                real_size = size()
+            else:
+                real_size = size
+            args['size'] = real_size
         return getattr(conf_helps, self.__method_name__)(**args)
 
 
@@ -473,11 +475,11 @@ def __real_step__(*args):
             mem = memory(
                 name=mem_name,
                 is_seq=static_input.is_seq,
-                size=static_input.input.calcalted_size,
+                size=static_input.input.calculate_size,
                 boot_layer=static_input.input)
             with mixed(
                     name=mem_name,
-                    size=static_input.input.calcalted_size,
+                    size=static_input.input.calculate_size,
                     act=activation.Identity()) as mix:
                 mix += identity_projection(input=mem)
             rnn_input.insert(input.index(static_input), mix)

From bb66f24334eff70a045c75ef9ff5a22b77c27e81 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 15:32:01 +0800
Subject: [PATCH 058/153] remove debug code

---
 python/paddle/v2/layer.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index 0d8b59cfd29c9..2f55611aaa1d3 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -225,7 +225,6 @@ def to_proto_impl(self, context, **kwargs):
                 real_size = size()
             else:
                 real_size = size
-            print(real_size)
             args['size'] = real_size
         return conf_helps.memory(name=self.name, **args)
 
@@ -471,7 +470,6 @@ def __real_step__(*args):
         static_inputs = filter(lambda x: isinstance(x, StaticInputV2), input)
         for static_input in static_inputs:
             mem_name = "__%s_memory__" % static_input.input.name
-            print memory
             mem = memory(
                 name=mem_name,
                 is_seq=static_input.is_seq,

From 6d09f70a860f253e00f91685eb73693e3eef5a76 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 15:43:13 +0800
Subject: [PATCH 059/153] Add event_handler test and comment

---
 demo/image_classification/api_v2_train.py | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py
index 0b4dc4d929826..94bf0b5db48c5 100644
--- a/demo/image_classification/api_v2_train.py
+++ b/demo/image_classification/api_v2_train.py
@@ -12,27 +12,41 @@
 # See the License for the specific language governing permissions and
 # limitations under the License
 
+import sys
+import paddle.v2 as paddle
 from api_v2_vgg import vgg_bn_drop
 from api_v2_resnet import resnet_cifar10
-import paddle.v2 as paddle
 
 
+# End batch and end pass event handler
 def event_handler(event):
     if isinstance(event, paddle.event.EndIteration):
         if event.batch_id % 100 == 0:
-            print "Pass %d, Batch %d, Cost %f" % (event.pass_id, event.batch_id,
-                                                  event.cost)
+            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):
+        result = trainer.test(
+            reader=paddle.reader.batched(
+                paddle.dataset.cifar.test10(), batch_size=128),
+            reader_dict={'image': 0,
+                         'label': 1})
+        print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
 
 
 def main():
     datadim = 3 * 32 * 32
     classdim = 10
 
+    # PaddlePaddle init
     paddle.init(use_gpu=True, trainer_count=1)
 
     image = paddle.layer.data(
         name="image", type=paddle.data_type.dense_vector(datadim))
 
+    # Add neural network config
     # option 1. resnet
     net = resnet_cifar10(image, depth=32)
     # option 2. vgg
@@ -46,8 +60,10 @@ def main():
         name="label", type=paddle.data_type.integer_value(classdim))
     cost = paddle.layer.classification_cost(input=out, label=lbl)
 
+    # Create parameters
     parameters = paddle.parameters.create(cost)
 
+    # Create optimizer
     momentum_optimizer = paddle.optimizer.Momentum(
         momentum=0.9,
         regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
@@ -57,6 +73,7 @@ def main():
         learning_rate_schedule='discexp',
         batch_size=128)
 
+    # Create trainer
     trainer = paddle.trainer.SGD(cost=cost,
                                  parameters=parameters,
                                  update_equation=momentum_optimizer)

From 9059eea4f46cf47a9f1382b97f25ab5f4586a5da Mon Sep 17 00:00:00 2001
From: "yi.wu" 
Date: Thu, 2 Mar 2017 15:58:39 +0800
Subject: [PATCH 060/153] Fix k8s cluster job rerunable

---
 doc/howto/usage/k8s/src/k8s_train/start_paddle.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/howto/usage/k8s/src/k8s_train/start_paddle.py b/doc/howto/usage/k8s/src/k8s_train/start_paddle.py
index f1a770ccb54fb..935c12bb67e1f 100755
--- a/doc/howto/usage/k8s/src/k8s_train/start_paddle.py
+++ b/doc/howto/usage/k8s/src/k8s_train/start_paddle.py
@@ -132,7 +132,8 @@ def startPaddle(idMap={}, train_args_dict=None):
     logDir = JOB_PATH_OUTPUT + "/node_" + str(trainerId)
     if not os.path.exists(JOB_PATH_OUTPUT):
         os.makedirs(JOB_PATH_OUTPUT)
-    os.mkdir(logDir)
+    if not os.path.exists(logDir):
+        os.mkdir(logDir)
     copyCommand = 'cp -rf ' + JOB_PATH + \
         "/" + str(trainerId) + "/data/*" + " ./data/"
     os.system(copyCommand)

From 4a94f8a4473b96161b721341fd0a889d34367aed Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 16:00:59 +0800
Subject: [PATCH 061/153] refine api training

---
 demo/semantic_role_labeling/api_train_v2.py | 221 +++++++++++++-------
 demo/semantic_role_labeling/model_v2.py     | 121 -----------
 python/paddle/v2/dataset/__init__.py        |   2 +-
 python/paddle/v2/dataset/conll05.py         |   6 +-
 4 files changed, 147 insertions(+), 203 deletions(-)
 delete mode 100644 demo/semantic_role_labeling/model_v2.py

diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py
index cfbd2a022426b..8ce6faaa1b75e 100644
--- a/demo/semantic_role_labeling/api_train_v2.py
+++ b/demo/semantic_role_labeling/api_train_v2.py
@@ -1,69 +1,142 @@
+import sys
+import math
 import numpy as np
 import paddle.v2 as paddle
-from model_v2 import db_lstm
+import paddle.v2.dataset.conll05 as conll05
 
 UNK_IDX = 0
 
-word_dict_file = './data/wordDict.txt'
-label_dict_file = './data/targetDict.txt'
-predicate_file = './data/verbDict.txt'
 
-word_dict = dict()
-label_dict = dict()
-predicate_dict = dict()
-
-with open(word_dict_file, 'r') as f_word, \
-     open(label_dict_file, 'r') as f_label, \
-     open(predicate_file, 'r') as f_pre:
-    for i, line in enumerate(f_word):
-        w = line.strip()
-        word_dict[w] = i
-
-    for i, line in enumerate(f_label):
-        w = line.strip()
-        label_dict[w] = i
-
-    for i, line in enumerate(f_pre):
-        w = line.strip()
-        predicate_dict[w] = i
-
-word_dict_len = len(word_dict)
-label_dict_len = len(label_dict)
-pred_len = len(predicate_dict)
-
-
-def train_reader(file_name="data/feature"):
-    def reader():
-        with open(file_name, 'r') as fdata:
-            for line in fdata:
-                sentence, predicate, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2,  mark, label = \
-                    line.strip().split('\t')
-
-                words = sentence.split()
-                sen_len = len(words)
-                word_slot = [word_dict.get(w, UNK_IDX) for w in words]
-
-                predicate_slot = [predicate_dict.get(predicate)] * sen_len
-                ctx_n2_slot = [word_dict.get(ctx_n2, UNK_IDX)] * sen_len
-                ctx_n1_slot = [word_dict.get(ctx_n1, UNK_IDX)] * sen_len
-                ctx_0_slot = [word_dict.get(ctx_0, UNK_IDX)] * sen_len
-                ctx_p1_slot = [word_dict.get(ctx_p1, UNK_IDX)] * sen_len
-                ctx_p2_slot = [word_dict.get(ctx_p2, UNK_IDX)] * sen_len
-
-                marks = mark.split()
-                mark_slot = [int(w) for w in marks]
-
-                label_list = label.split()
-                label_slot = [label_dict.get(w) for w in label_list]
-                yield word_slot, ctx_n2_slot, ctx_n1_slot, \
-                  ctx_0_slot, ctx_p1_slot, ctx_p2_slot, predicate_slot, mark_slot, label_slot
-
-    return reader
+def db_lstm():
+    word_dict, verb_dict, label_dict = conll05.get_dict()
+    word_dict_len = len(word_dict)
+    label_dict_len = len(label_dict)
+    pred_len = len(verb_dict)
+    print 'word_dict_len,', word_dict_len
+    print 'label_dict_len,', label_dict_len
+    print 'pred_len,', pred_len
+
+    mark_dict_len = 2
+    word_dim = 32
+    mark_dim = 5
+    hidden_dim = 512
+    depth = 8
+
+    #8 features
+    def d_type(size):
+        return paddle.data_type.integer_value_sequence(size)
+
+    word = paddle.layer.data(name='word_data', type=d_type(word_dict_len))
+    predicate = paddle.layer.data(name='verb_data', type=d_type(pred_len))
+
+    ctx_n2 = paddle.layer.data(name='ctx_n2_data', type=d_type(word_dict_len))
+    ctx_n1 = paddle.layer.data(name='ctx_n1_data', type=d_type(word_dict_len))
+    ctx_0 = paddle.layer.data(name='ctx_0_data', type=d_type(word_dict_len))
+    ctx_p1 = paddle.layer.data(name='ctx_p1_data', type=d_type(word_dict_len))
+    ctx_p2 = paddle.layer.data(name='ctx_p2_data', type=d_type(word_dict_len))
+    mark = paddle.layer.data(name='mark_data', type=d_type(mark_dict_len))
+
+    target = paddle.layer.data(name='target', type=d_type(label_dict_len))
+
+    default_std = 1 / math.sqrt(hidden_dim) / 3.0
+
+    emb_para = paddle.attr.Param(name='emb', initial_std=0., learning_rate=0.)
+    std_0 = paddle.attr.Param(initial_std=0.)
+    std_default = paddle.attr.Param(initial_std=default_std)
+
+    predicate_embedding = paddle.layer.embedding(
+        size=word_dim,
+        input=predicate,
+        param_attr=paddle.attr.Param(
+            name='vemb', initial_std=default_std))
+    mark_embedding = paddle.layer.embedding(
+        size=mark_dim, input=mark, param_attr=std_0)
+
+    word_input = [word, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2]
+    emb_layers = [
+        paddle.layer.embedding(
+            size=word_dim, input=x, param_attr=emb_para) for x in word_input
+    ]
+    emb_layers.append(predicate_embedding)
+    emb_layers.append(mark_embedding)
+
+    hidden_0 = paddle.layer.mixed(
+        size=hidden_dim,
+        bias_attr=std_default,
+        input=[
+            paddle.layer.full_matrix_projection(
+                input=emb, param_attr=std_default) for emb in emb_layers
+        ])
+
+    mix_hidden_lr = 1e-3
+    lstm_para_attr = paddle.attr.Param(initial_std=0.0, learning_rate=1.0)
+    hidden_para_attr = paddle.attr.Param(
+        initial_std=default_std, learning_rate=mix_hidden_lr)
+
+    lstm_0 = paddle.layer.lstmemory(
+        input=hidden_0,
+        act=paddle.activation.Relu(),
+        gate_act=paddle.activation.Sigmoid(),
+        state_act=paddle.activation.Sigmoid(),
+        bias_attr=std_0,
+        param_attr=lstm_para_attr)
+
+    #stack L-LSTM and R-LSTM with direct edges
+    input_tmp = [hidden_0, lstm_0]
+
+    for i in range(1, depth):
+        mix_hidden = paddle.layer.mixed(
+            size=hidden_dim,
+            bias_attr=std_default,
+            input=[
+                paddle.layer.full_matrix_projection(
+                    input=input_tmp[0], param_attr=hidden_para_attr),
+                paddle.layer.full_matrix_projection(
+                    input=input_tmp[1], param_attr=lstm_para_attr)
+            ])
+
+        lstm = paddle.layer.lstmemory(
+            input=mix_hidden,
+            act=paddle.activation.Relu(),
+            gate_act=paddle.activation.Sigmoid(),
+            state_act=paddle.activation.Sigmoid(),
+            reverse=((i % 2) == 1),
+            bias_attr=std_0,
+            param_attr=lstm_para_attr)
+
+        input_tmp = [mix_hidden, lstm]
+
+    feature_out = paddle.layer.mixed(
+        size=label_dict_len,
+        bias_attr=std_default,
+        input=[
+            paddle.layer.full_matrix_projection(
+                input=input_tmp[0], param_attr=hidden_para_attr),
+            paddle.layer.full_matrix_projection(
+                input=input_tmp[1], param_attr=lstm_para_attr)
+        ], )
+
+    crf_cost = paddle.layer.crf(size=label_dict_len,
+                                input=feature_out,
+                                label=target,
+                                param_attr=paddle.attr.Param(
+                                    name='crfw',
+                                    initial_std=default_std,
+                                    learning_rate=mix_hidden_lr))
+
+    crf_dec = paddle.layer.crf_decoding(
+        name='crf_dec_l',
+        size=label_dict_len,
+        input=feature_out,
+        label=target,
+        param_attr=paddle.attr.Param(name='crfw'))
+
+    return crf_cost, crf_dec
 
 
 def load_parameter(file_name, h, w):
     with open(file_name, 'rb') as f:
-        f.read(16)  # skip header for float type.
+        f.read(16)  # skip header.
         return np.fromfile(f, dtype=np.float32).reshape(h, w)
 
 
@@ -71,44 +144,36 @@ def main():
     paddle.init(use_gpu=False, trainer_count=1)
 
     # define network topology
-    crf_cost, crf_dec = db_lstm(word_dict_len, label_dict_len, pred_len)
+    crf_cost, crf_dec = db_lstm()
 
+    # create parameters
     parameters = paddle.parameters.create([crf_cost, crf_dec])
-    optimizer = paddle.optimizer.Momentum(momentum=0.01, learning_rate=2e-2)
+
+    # create optimizer
+    optimizer = paddle.optimizer.Momentum(
+        momentum=0,
+        learning_rate=2e-2,
+        regularization=paddle.optimizer.L2Regularization(rate=8e-4),
+        model_average=paddle.optimizer.ModelAverage(
+            average_window=0.5, max_average_window=10000), )
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
             if event.batch_id % 100 == 0:
                 print "Pass %d, Batch %d, Cost %f, %s" % (
                     event.pass_id, event.batch_id, event.cost, event.metrics)
-        else:
-            pass
 
     trainer = paddle.trainer.SGD(cost=crf_cost,
                                  parameters=parameters,
                                  update_equation=optimizer)
+    parameters.set('emb', load_parameter(conll05.get_embedding(), 44068, 32))
 
-    parameters.set('emb', load_parameter("data/emb", 44068, 32))
-
-    reader_dict = {
-        'word_data': 0,
-        'ctx_n2_data': 1,
-        'ctx_n1_data': 2,
-        'ctx_0_data': 3,
-        'ctx_p1_data': 4,
-        'ctx_p2_data': 5,
-        'verb_data': 6,
-        'mark_data': 7,
-        'target': 8,
-    }
     trn_reader = paddle.reader.batched(
         paddle.reader.shuffle(
-            train_reader(), buf_size=8192), batch_size=10)
+            conll05.test, buf_size=8192), batch_size=10)
+
     trainer.train(
-        reader=trn_reader,
-        event_handler=event_handler,
-        num_passes=10000,
-        reader_dict=reader_dict)
+        reader=trn_reader, event_handler=event_handler, num_passes=10000)
 
 
 if __name__ == '__main__':
diff --git a/demo/semantic_role_labeling/model_v2.py b/demo/semantic_role_labeling/model_v2.py
deleted file mode 100644
index cec58e52c7940..0000000000000
--- a/demo/semantic_role_labeling/model_v2.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import math
-import paddle.v2 as paddle
-
-
-def db_lstm(word_dict_len, label_dict_len, pred_len):
-    mark_dict_len = 2
-    word_dim = 32
-    mark_dim = 5
-    hidden_dim = 512
-    depth = 8
-
-    #8 features
-    def d_type(size):
-        return paddle.data_type.integer_value_sequence(size)
-
-    word = paddle.layer.data(name='word_data', type=d_type(word_dict_len))
-    predicate = paddle.layer.data(name='verb_data', type=d_type(pred_len))
-
-    ctx_n2 = paddle.layer.data(name='ctx_n2_data', type=d_type(word_dict_len))
-    ctx_n1 = paddle.layer.data(name='ctx_n1_data', type=d_type(word_dict_len))
-    ctx_0 = paddle.layer.data(name='ctx_0_data', type=d_type(word_dict_len))
-    ctx_p1 = paddle.layer.data(name='ctx_p1_data', type=d_type(word_dict_len))
-    ctx_p2 = paddle.layer.data(name='ctx_p2_data', type=d_type(word_dict_len))
-    mark = paddle.layer.data(name='mark_data', type=d_type(mark_dict_len))
-
-    target = paddle.layer.data(name='target', type=d_type(label_dict_len))
-
-    default_std = 1 / math.sqrt(hidden_dim) / 3.0
-
-    emb_para = paddle.attr.Param(name='emb', initial_std=0., learning_rate=0.)
-    std_0 = paddle.attr.Param(initial_std=0.)
-    std_default = paddle.attr.Param(initial_std=default_std)
-
-    predicate_embedding = paddle.layer.embedding(
-        size=word_dim,
-        input=predicate,
-        param_attr=paddle.attr.Param(
-            name='vemb', initial_std=default_std))
-    mark_embedding = paddle.layer.embedding(
-        size=mark_dim, input=mark, param_attr=std_0)
-
-    word_input = [word, ctx_n2, ctx_n1, ctx_0, ctx_p1, ctx_p2]
-    emb_layers = [
-        paddle.layer.embedding(
-            size=word_dim, input=x, param_attr=emb_para) for x in word_input
-    ]
-    emb_layers.append(predicate_embedding)
-    emb_layers.append(mark_embedding)
-
-    hidden_0 = paddle.layer.mixed(
-        size=hidden_dim,
-        bias_attr=std_default,
-        input=[
-            paddle.layer.full_matrix_projection(
-                input=emb, param_attr=std_default) for emb in emb_layers
-        ])
-
-    mix_hidden_lr = 1e-3
-    lstm_para_attr = paddle.attr.Param(initial_std=0.0, learning_rate=1.0)
-    hidden_para_attr = paddle.attr.Param(
-        initial_std=default_std, learning_rate=mix_hidden_lr)
-
-    lstm_0 = paddle.layer.lstmemory(
-        input=hidden_0,
-        act=paddle.activation.Relu(),
-        gate_act=paddle.activation.Sigmoid(),
-        state_act=paddle.activation.Sigmoid(),
-        bias_attr=std_0,
-        param_attr=lstm_para_attr)
-
-    #stack L-LSTM and R-LSTM with direct edges
-    input_tmp = [hidden_0, lstm_0]
-
-    for i in range(1, depth):
-        mix_hidden = paddle.layer.mixed(
-            size=hidden_dim,
-            bias_attr=std_default,
-            input=[
-                paddle.layer.full_matrix_projection(
-                    input=input_tmp[0], param_attr=hidden_para_attr),
-                paddle.layer.full_matrix_projection(
-                    input=input_tmp[1], param_attr=lstm_para_attr)
-            ])
-
-        lstm = paddle.layer.lstmemory(
-            input=mix_hidden,
-            act=paddle.activation.Relu(),
-            gate_act=paddle.activation.Sigmoid(),
-            state_act=paddle.activation.Sigmoid(),
-            reverse=((i % 2) == 1),
-            bias_attr=std_0,
-            param_attr=lstm_para_attr)
-
-        input_tmp = [mix_hidden, lstm]
-
-    feature_out = paddle.layer.mixed(
-        size=label_dict_len,
-        bias_attr=std_default,
-        input=[
-            paddle.layer.full_matrix_projection(
-                input=input_tmp[0], param_attr=hidden_para_attr),
-            paddle.layer.full_matrix_projection(
-                input=input_tmp[1], param_attr=lstm_para_attr)
-        ], )
-
-    crf_cost = paddle.layer.crf(size=label_dict_len,
-                                input=feature_out,
-                                label=target,
-                                param_attr=paddle.attr.Param(
-                                    name='crfw',
-                                    initial_std=default_std,
-                                    learning_rate=mix_hidden_lr))
-
-    crf_dec = paddle.layer.crf_decoding(
-        name='crf_dec_l',
-        size=label_dict_len,
-        input=feature_out,
-        label=target,
-        param_attr=paddle.attr.Param(name='crfw'))
-
-    return crf_cost, crf_dec
diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index 15460b820d86d..90803628e3e0c 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -14,4 +14,4 @@
 
 import mnist
 
-__all__ = ['mnist']
+__all__ = ['mnist', 'cifar', 'imdb', 'conll05', 'imikolov', 'movielens']
diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py
index 7874161a05968..52f19d2115f54 100644
--- a/python/paddle/v2/dataset/conll05.py
+++ b/python/paddle/v2/dataset/conll05.py
@@ -160,7 +160,6 @@ def reader():
                 ctx_p2 = 'eos'
 
             word_idx = [word_dict.get(w, UNK_IDX) for w in sentence]
-            pred_idx = [predicate_dict.get(predicate)] * sen_len
 
             ctx_n2_idx = [word_dict.get(ctx_n2, UNK_IDX)] * sen_len
             ctx_n1_idx = [word_dict.get(ctx_n1, UNK_IDX)] * sen_len
@@ -168,10 +167,11 @@ def reader():
             ctx_p1_idx = [word_dict.get(ctx_p1, UNK_IDX)] * sen_len
             ctx_p2_idx = [word_dict.get(ctx_p2, UNK_IDX)] * sen_len
 
+            pred_idx = [predicate_dict.get(predicate)] * sen_len
             label_idx = [label_dict.get(w) for w in labels]
 
-            yield word_idx, pred_idx, ctx_n2_idx, ctx_n1_idx, \
-              ctx_0_idx, ctx_p1_idx, ctx_p2_idx, mark, label_idx
+            yield word_idx, ctx_n2_idx, ctx_n1_idx, \
+              ctx_0_idx, ctx_p1_idx, ctx_p2_idx, pred_idx, mark, label_idx
 
     return reader()
 

From 11fdb4f041250d906a115c00d4e37b76a4bf8905 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 16:11:30 +0800
Subject: [PATCH 062/153] Check system's protobuf for internal users

---
 cmake/external/protobuf.cmake | 82 ++++++++++++++++++-----------------
 cmake/external/python.cmake   |  4 --
 2 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake
index 84f459033f06f..26da7e8e384ba 100644
--- a/cmake/external/protobuf.cmake
+++ b/cmake/external/protobuf.cmake
@@ -14,46 +14,50 @@
 
 INCLUDE(ExternalProject)
 
-SET(PROTOBUF_SOURCES_DIR ${THIRD_PARTY_PATH}/protobuf)
-SET(PROTOBUF_INSTALL_DIR ${THIRD_PARTY_PATH}/install/protobuf)
-SET(PROTOBUF_INCLUDE_DIR "${PROTOBUF_INSTALL_DIR}/include" CACHE PATH "protobuf include directory." FORCE)
+FIND_PACKAGE(Protobuf)
 
-INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
+IF(NOT PROTOBUF_FOUND)
+    SET(PROTOBUF_SOURCES_DIR ${THIRD_PARTY_PATH}/protobuf)
+    SET(PROTOBUF_INSTALL_DIR ${THIRD_PARTY_PATH}/install/protobuf)
+    SET(PROTOBUF_INCLUDE_DIR "${PROTOBUF_INSTALL_DIR}/include" CACHE PATH "protobuf include directory." FORCE)
+
+    IF(WIN32)
+        SET(PROTOBUF_LITE_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite.lib" CACHE FILEPATH "protobuf lite library." FORCE)
+        SET(PROTOBUF_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf.lib" CACHE FILEPATH "protobuf library." FORCE)
+        SET(PROTOBUF_PROTOC_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.lib" CACHE FILEPATH "protoc library." FORCE)
+        SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc.exe" CACHE FILEPATH "protobuf executable." FORCE)
+    ELSE(WIN32)
+        SET(PROTOBUF_LITE_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite.a" CACHE FILEPATH "protobuf lite library." FORCE)
+        SET(PROTOBUF_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf.a" CACHE FILEPATH "protobuf library." FORCE)
+        SET(PROTOBUF_PROTOC_LIBRARY
+            "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.a" CACHE FILEPATH "protoc library." FORCE)
+        SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc" CACHE FILEPATH "protobuf executable." FORCE)
+    ENDIF(WIN32)
 
-IF(WIN32)
-  SET(PROTOBUF_LITE_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite.lib" CACHE FILEPATH "protobuf lite library." FORCE)
-  SET(PROTOBUF_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf.lib" CACHE FILEPATH "protobuf library." FORCE)
-  SET(PROTOBUF_PROTOC_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.lib" CACHE FILEPATH "protoc library." FORCE)
-  SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc.exe" CACHE FILEPATH "protobuf executable." FORCE)
-ELSE(WIN32)
-  SET(PROTOBUF_LITE_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite.a" CACHE FILEPATH "protobuf lite library." FORCE)
-  SET(PROTOBUF_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf.a" CACHE FILEPATH "protobuf library." FORCE)
-  SET(PROTOBUF_PROTOC_LIBRARY
-        "${PROTOBUF_INSTALL_DIR}/lib/libprotoc.a" CACHE FILEPATH "protoc library." FORCE)
-  SET(PROTOBUF_PROTOC_EXECUTABLE "${PROTOBUF_INSTALL_DIR}/bin/protoc" CACHE FILEPATH "protobuf executable." FORCE)
-ENDIF(WIN32)
+    ExternalProject_Add(
+        protobuf
+        ${EXTERNAL_PROJECT_LOG_ARGS}
+        PREFIX          ${PROTOBUF_SOURCES_DIR}
+        UPDATE_COMMAND  ""
+        DEPENDS         zlib
+        GIT_REPOSITORY  "https://github.com/google/protobuf.git"
+        GIT_TAG         "9f75c5aa851cd877fb0d93ccc31b8567a6706546"
+        CONFIGURE_COMMAND
+        ${CMAKE_COMMAND} ${PROTOBUF_SOURCES_DIR}/src/protobuf/cmake
+        -Dprotobuf_BUILD_TESTS=OFF
+        -DZLIB_ROOT:FILEPATH=${ZLIB_ROOT}
+        -DCMAKE_POSITION_INDEPENDENT_CODE=ON
+        -DCMAKE_BUILD_TYPE=Release
+        -DCMAKE_INSTALL_PREFIX=${PROTOBUF_INSTALL_DIR}
+        -DCMAKE_INSTALL_LIBDIR=lib
+    )
 
-ExternalProject_Add(
-  protobuf
-  ${EXTERNAL_PROJECT_LOG_ARGS}
-  PREFIX          ${PROTOBUF_SOURCES_DIR}
-  UPDATE_COMMAND  ""
-  DEPENDS         zlib
-  GIT_REPOSITORY  "https://github.com/google/protobuf.git"
-  GIT_TAG         "9f75c5aa851cd877fb0d93ccc31b8567a6706546"
-  CONFIGURE_COMMAND
-    ${CMAKE_COMMAND} ${PROTOBUF_SOURCES_DIR}/src/protobuf/cmake
-    -Dprotobuf_BUILD_TESTS=OFF
-    -DZLIB_ROOT:FILEPATH=${ZLIB_ROOT}
-    -DCMAKE_POSITION_INDEPENDENT_CODE=ON
-    -DCMAKE_BUILD_TYPE=Release
-    -DCMAKE_INSTALL_PREFIX=${PROTOBUF_INSTALL_DIR}
-    -DCMAKE_INSTALL_LIBDIR=lib
-)
+    LIST(APPEND external_project_dependencies protobuf)
+ENDIF(NOT PROTOBUF_FOUND)
 
-LIST(APPEND external_project_dependencies protobuf)
+INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
diff --git a/cmake/external/python.cmake b/cmake/external/python.cmake
index 6372a9a768e58..0accf1a8dd835 100644
--- a/cmake/external/python.cmake
+++ b/cmake/external/python.cmake
@@ -221,7 +221,3 @@ ENDIF(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND)
 
 INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR})
 INCLUDE_DIRECTORIES(${PYTHON_NUMPY_INCLUDE_DIR})
-
-MESSAGE("[Paddle] Python Executable: ${PYTHON_EXECUTABLE}")
-MESSAGE("[Paddle] Python Include: ${PYTHON_INCLUDE_DIRS}")
-MESSAGE("[Paddle] Python Libraries: ${PYTHON_LIBRARIES}")

From 69ac20c2845fa0bb988407a4cd3af7af1aaa7d0a Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Thu, 2 Mar 2017 16:53:31 +0800
Subject: [PATCH 063/153] Fix event_handler trainer

---
 demo/image_classification/api_v2_train.py | 35 +++++++++++------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py
index 94bf0b5db48c5..585f61c6fa4c8 100644
--- a/demo/image_classification/api_v2_train.py
+++ b/demo/image_classification/api_v2_train.py
@@ -18,24 +18,6 @@
 from api_v2_resnet import resnet_cifar10
 
 
-# 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):
-        result = trainer.test(
-            reader=paddle.reader.batched(
-                paddle.dataset.cifar.test10(), batch_size=128),
-            reader_dict={'image': 0,
-                         'label': 1})
-        print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
-
-
 def main():
     datadim = 3 * 32 * 32
     classdim = 10
@@ -73,6 +55,23 @@ def main():
         learning_rate_schedule='discexp',
         batch_size=128)
 
+    # 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):
+            result = trainer.test(
+                reader=paddle.reader.batched(
+                    paddle.dataset.cifar.test10(), batch_size=128),
+                reader_dict={'image': 0,
+                             'label': 1})
+            print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
+
     # Create trainer
     trainer = paddle.trainer.SGD(cost=cost,
                                  parameters=parameters,

From 66b6ae163c468f46a301d738429c359190904861 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 17:27:29 +0800
Subject: [PATCH 064/153] Complete api_train_v2

---
 demo/recommendation/api_train_v2.py   | 39 +++++++++++++++++++++------
 python/paddle/v2/dataset/movielens.py | 27 ++++++++++++++++++-
 2 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py
index 93e2a26f7431d..a7cf137a798ed 100644
--- a/demo/recommendation/api_train_v2.py
+++ b/demo/recommendation/api_train_v2.py
@@ -1,8 +1,10 @@
 import paddle.v2 as paddle
+import cPickle
+import copy
 
 
 def main():
-    paddle.init(use_gpu=False, trainer_count=3)
+    paddle.init(use_gpu=False)
     movie_title_dict = paddle.dataset.movielens.get_movie_title_dict()
     uid = paddle.layer.data(
         name='user_id',
@@ -86,19 +88,40 @@ def event_handler(event):
             if event.batch_id % 100 == 0:
                 print "Pass %d Batch %d Cost %.2f" % (
                     event.pass_id, event.batch_id, event.cost)
-        elif isinstance(event, paddle.event.EndPass):
-            result = trainer.test(reader=paddle.reader.batched(
-                paddle.dataset.movielens.test(), batch_size=256))
-            print result.cost
 
     trainer.train(
         reader=paddle.reader.batched(
-            paddle.reader.shuffle(
-                paddle.dataset.movielens.train(), buf_size=8192),
+            paddle.reader.firstn(
+                paddle.reader.shuffle(
+                    paddle.dataset.movielens.train(), buf_size=8192),
+                n=1000),
             batch_size=256),
         event_handler=event_handler,
         reader_dict=reader_dict,
-        num_passes=10)
+        num_passes=1)
+
+    user_id = 234
+    movie_id = 345
+
+    user = paddle.dataset.movielens.user_info()[user_id]
+    movie = paddle.dataset.movielens.movie_info()[movie_id]
+
+    feature = user.value() + movie.value()
+
+    def reader():
+        yield feature
+
+    infer_dict = copy.copy(reader_dict)
+    del infer_dict['score']
+    print infer_dict
+
+    prediction = paddle.infer(
+        output=inference,
+        parameters=parameters,
+        reader=paddle.reader.batched(
+            reader, batch_size=32),
+        reader_dict=infer_dict)
+    print prediction
 
 
 if __name__ == '__main__':
diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py
index 058400502fc31..5534af1145563 100644
--- a/python/paddle/v2/dataset/movielens.py
+++ b/python/paddle/v2/dataset/movielens.py
@@ -6,7 +6,7 @@
 
 __all__ = [
     'train', 'test', 'get_movie_title_dict', 'max_movie_id', 'max_user_id',
-    'age_table', 'movie_categories', 'max_job_id'
+    'age_table', 'movie_categories', 'max_job_id', 'user_info', 'movie_info'
 ]
 
 age_table = [1, 18, 25, 35, 45, 50, 56]
@@ -24,6 +24,13 @@ def value(self):
             [MOVIE_TITLE_DICT[w.lower()] for w in self.title.split()]
         ]
 
+    def __str__(self):
+        return "" % (
+            self.index, self.title, self.categories)
+
+    def __repr__(self):
+        return self.__str__()
+
 
 class UserInfo(object):
     def __init__(self, index, gender, age, job_id):
@@ -35,6 +42,14 @@ def __init__(self, index, gender, age, job_id):
     def value(self):
         return [self.index, 0 if self.is_male else 1, self.age, self.job_id]
 
+    def __str__(self):
+        return "" % (
+            self.index, "M"
+            if self.is_male else "F", age_table[self.age], self.job_id)
+
+    def __repr__(self):
+        return str(self)
+
 
 MOVIE_INFO = None
 MOVIE_TITLE_DICT = None
@@ -152,6 +167,16 @@ def movie_categories():
     return CATEGORIES_DICT
 
 
+def user_info():
+    __initialize_meta_info__()
+    return USER_INFO
+
+
+def movie_info():
+    __initialize_meta_info__()
+    return MOVIE_INFO
+
+
 def unittest():
     for train_count, _ in enumerate(train()()):
         pass

From edce6c8b6ab23c9c7fea1dee75d46fb2bb0f3e31 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 17:51:53 +0800
Subject: [PATCH 065/153] restore embedding_layer name to embedding

---
 python/paddle/trainer_config_helpers/layers.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py
index 2b95c2ed0f356..b68460b6a3ab6 100755
--- a/python/paddle/trainer_config_helpers/layers.py
+++ b/python/paddle/trainer_config_helpers/layers.py
@@ -822,7 +822,7 @@ def data_layer(name, size, height=None, width=None, layer_attr=None):
     return LayerOutput(name, LayerType.DATA, size=size)
 
 
-@wrap_name_default("embedding_layer")
+@wrap_name_default("embedding")
 @wrap_param_attr_default()
 @layer_support(ERROR_CLIPPING)
 def embedding_layer(input, size, name=None, param_attr=None, layer_attr=None):

From 465878a9d2f84910dc71ea8fa9dd53f34c10f52d Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 18:50:12 +0800
Subject: [PATCH 066/153] fit_a_line v2 api

---
 demo/introduction/api_train_v2.py       | 59 +++++++++++++++++
 python/paddle/v2/dataset/__init__.py    |  3 +-
 python/paddle/v2/dataset/uci_housing.py | 86 +++++++++++++++++++++++++
 3 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 demo/introduction/api_train_v2.py
 create mode 100644 python/paddle/v2/dataset/uci_housing.py

diff --git a/demo/introduction/api_train_v2.py b/demo/introduction/api_train_v2.py
new file mode 100644
index 0000000000000..49496c7f08572
--- /dev/null
+++ b/demo/introduction/api_train_v2.py
@@ -0,0 +1,59 @@
+import paddle.v2 as paddle
+import paddle.v2.dataset.uci_housing as uci_housing
+
+
+def main():
+    # init
+    paddle.init(use_gpu=False, trainer_count=1)
+
+    # network config
+    x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(13))
+    y_predict = paddle.layer.fc(input=x,
+                                param_attr=paddle.attr.Param(name='w'),
+                                size=1,
+                                act=paddle.activation.Linear(),
+                                bias_attr=paddle.attr.Param(name='b'))
+    y = paddle.layer.data(name='y', type=paddle.data_type.dense_vector(1))
+    cost = paddle.layer.regression_cost(input=y_predict, label=y)
+
+    # create parameters
+    parameters = paddle.parameters.create(cost)
+
+    # create optimizer
+    optimizer = paddle.optimizer.Momentum(momentum=0)
+
+    trainer = paddle.trainer.SGD(cost=cost,
+                                 parameters=parameters,
+                                 update_equation=optimizer)
+
+    # event_handler to print training and testing info
+    def event_handler(event):
+        if isinstance(event, paddle.event.EndIteration):
+            if event.batch_id % 100 == 0:
+                print "Pass %d, Batch %d, Cost %f, %s" % (
+                    event.pass_id, event.batch_id, event.cost, event.metrics)
+
+        if isinstance(event, paddle.event.EndPass):
+            result = trainer.test(
+                reader=paddle.reader.batched(
+                    uci_housing.test(), batch_size=2),
+                reader_dict={'x': 0,
+                             'y': 1})
+            if event.pass_id % 10 == 0:
+                print "Test %d, Cost %f, %s" % (event.pass_id, event.cost,
+                                                result.metrics)
+
+    # training
+    trainer.train(
+        reader=paddle.reader.batched(
+            paddle.reader.shuffle(
+                uci_housing.train(), buf_size=500),
+            batch_size=2),
+        reader_dict={'x': 0,
+                     'y': 1},
+        event_handler=event_handler,
+        num_passes=30)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index 9647e9850332b..0058e1df11080 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -1,3 +1,4 @@
 import mnist
+import uci_housing
 
-__all__ = ['mnist']
+__all__ = ['mnist', 'uci_housing']
diff --git a/python/paddle/v2/dataset/uci_housing.py b/python/paddle/v2/dataset/uci_housing.py
new file mode 100644
index 0000000000000..b5a0537af66a3
--- /dev/null
+++ b/python/paddle/v2/dataset/uci_housing.py
@@ -0,0 +1,86 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import numpy as np
+import os
+from common import download
+
+__all__ = ['train', 'test']
+
+URL = 'https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data'
+MD5 = 'd4accdce7a25600298819f8e28e8d593'
+feature_names = [
+    'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
+    'PTRATIO', 'B', 'LSTAT'
+]
+
+UCI_TRAIN_DATA = None
+UCI_TEST_DATA = None
+
+
+def feature_range(maximums, minimums):
+    import matplotlib
+    matplotlib.use('Agg')
+    import matplotlib.pyplot as plt
+    fig, ax = plt.subplots()
+    feature_num = len(maximums)
+    ax.bar(range(feature_num), maximums - minimums, color='r', align='center')
+    ax.set_title('feature scale')
+    plt.xticks(range(feature_num), feature_names)
+    plt.xlim([-1, feature_num])
+    fig.set_figheight(6)
+    fig.set_figwidth(10)
+    if not os.path.exists('./image'):
+        os.makedirs('./image')
+    fig.savefig('image/ranges.png', dpi=48)
+    plt.close(fig)
+
+
+def load_data(filename, feature_num=14, ratio=0.8):
+    global UCI_TRAIN_DATA, UCI_TEST_DATA
+    if UCI_TRAIN_DATA is not None and UCI_TEST_DATA is not None:
+        return
+
+    data = np.fromfile(filename, sep=' ')
+    data = data.reshape(data.shape[0] / feature_num, feature_num)
+    maximums, minimums, avgs = data.max(axis=0), data.min(axis=0), data.sum(
+        axis=0) / data.shape[0]
+    feature_range(maximums[:-1], minimums[:-1])
+    for i in xrange(feature_num - 1):
+        data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
+    offset = int(data.shape[0] * ratio)
+    UCI_TRAIN_DATA = data[:offset]
+    UCI_TEST_DATA = data[offset:]
+
+
+def train():
+    global UCI_TRAIN_DATA
+    load_data(download(URL, 'uci_housing', MD5))
+
+    def reader():
+        for d in UCI_TRAIN_DATA:
+            yield d[:-1], d[-1:]
+
+    return reader
+
+
+def test():
+    global UCI_TEST_DATA
+    load_data(download(URL, 'uci_housing', MD5))
+
+    def reader():
+        for d in UCI_TEST_DATA:
+            yield d[:-1], d[-1:]
+
+    return reader

From a05707ff324e59b032f8ac0c43d62f339ef78db5 Mon Sep 17 00:00:00 2001
From: Luo Tao 
Date: Thu, 2 Mar 2017 20:45:37 +0800
Subject: [PATCH 067/153] add test cost

---
 demo/mnist/api_train_v2.py  | 25 +++++++++++++++++++------
 python/paddle/v2/event.py   |  3 ++-
 python/paddle/v2/trainer.py | 10 +++++++++-
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py
index 6439d07ac6157..341a7165da4e2 100644
--- a/demo/mnist/api_train_v2.py
+++ b/demo/mnist/api_train_v2.py
@@ -63,6 +63,8 @@ def main():
     label = paddle.layer.data(
         name='label', type=paddle.data_type.integer_value(10))
 
+    # Here we can build the prediction network in different ways. Please
+    # choose one by uncomment corresponding line.
     predict = softmax_regression(images)
     #predict = multilayer_perceptron(images)
     #predict = convolutional_neural_network(images)
@@ -80,14 +82,20 @@ def main():
                                  parameters=parameters,
                                  update_equation=optimizer)
 
+    list = []
+
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
             if event.batch_id % 100 == 0:
-                result = trainer.test(reader=paddle.reader.batched(
-                    paddle.dataset.mnist.test(), batch_size=128))
-                print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % (
-                    event.pass_id, event.batch_id, event.cost, event.metrics,
-                    result.metrics)
+                print "Pass %d, Batch %d, Cost %f, %s" % (
+                    event.pass_id, event.batch_id, event.cost, event.metrics)
+        if isinstance(event, paddle.event.EndPass):
+            result = trainer.test(reader=paddle.reader.batched(
+                paddle.dataset.mnist.test(), batch_size=128))
+            print "Test with Pass %d, Cost %f, %s\n" % (
+                event.pass_id, event.cost, result.metrics)
+            list.append((event.pass_id, event.cost,
+                         result.metrics['classification_error_evaluator']))
 
     trainer.train(
         reader=paddle.reader.batched(
@@ -97,10 +105,15 @@ def event_handler(event):
         event_handler=event_handler,
         num_passes=100)
 
+    # find the best pass
+    best = sorted(list, key=lambda list: float(list[1]))[0]
+    print 'Best pass is %s, testing Avgcost is %s' % (best[0], best[1])
+    print 'The classification accuracy is %.2f%%' % (100 - float(best[2]) * 100)
+
     # output is a softmax layer. It returns probabilities.
     # Shape should be (100, 10)
     probs = paddle.infer(
-        output=inference,
+        output=predict,
         parameters=parameters,
         reader=paddle.reader.batched(
             paddle.reader.firstn(
diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py
index a78bcf076cc65..6a7bcb81879c0 100644
--- a/python/paddle/v2/event.py
+++ b/python/paddle/v2/event.py
@@ -52,8 +52,9 @@ class EndPass(WithMetric):
     Event On One Pass Training Complete.
     """
 
-    def __init__(self, pass_id, evaluator):
+    def __init__(self, pass_id, cost, evaluator):
         self.pass_id = pass_id
+        self.cost = cost
         WithMetric.__init__(self, evaluator)
 
 
diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index e743a49523ff2..a4ef0df597dd7 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -107,6 +107,8 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
             event_handler(v2_event.BeginPass(pass_id))
             pass_evaluator.start()
             updater.startPass()
+            total_cost_sum = 0
+            total_batch = 0
             for batch_id, data_batch in enumerate(reader()):
                 pass_type = updater.startBatch(len(data_batch))
                 self.__gradient_machine__.forwardBackward(
@@ -127,6 +129,8 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
                 cost_vec = out_args.getSlotValue(0)
                 cost_vec = cost_vec.copyToNumpyMat()
                 cost = cost_vec.sum() / len(data_batch)
+                total_cost_sum += cost_vec.sum()
+                total_batch += len(data_batch)
                 updater.finishBatch(cost)
                 batch_evaluator.finish()
                 event_handler(
@@ -138,7 +142,11 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
 
             updater.finishPass()
             pass_evaluator.finish()
-            event_handler(v2_event.EndPass(pass_id, evaluator=pass_evaluator))
+            event_handler(
+                v2_event.EndPass(
+                    pass_id,
+                    cost=total_cost_sum / total_batch,
+                    evaluator=pass_evaluator))
         self.__gradient_machine__.finish()
 
     def default_reader_dict(self):

From 5ce504b19b96d94dec5ceab2e2443a091b690cf0 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Thu, 2 Mar 2017 20:50:23 +0800
Subject: [PATCH 068/153] Fix duplicated forward/backward in trainer.

---
 python/paddle/v2/trainer.py | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index 5003f55f3e0d1..5cff75e39df5c 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -108,9 +108,6 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None):
             pass_evaluator.start()
             updater.startPass()
             for batch_id, data_batch in enumerate(reader()):
-                pass_type = updater.startBatch(len(data_batch))
-                self.__gradient_machine__.forwardBackward(
-                    feeder(data_batch), out_args, pass_type)
                 batch_evaluator.start()
                 event_handler(
                     v2_event.BeginIteration(

From 172ac8af7abb0b54f47abb7eb067fbd538ab5b57 Mon Sep 17 00:00:00 2001
From: dangqingqing 
Date: Thu, 2 Mar 2017 20:58:05 +0800
Subject: [PATCH 069/153] update

---
 demo/semantic_role_labeling/api_train_v2.py | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py
index 8ce6faaa1b75e..c582724185926 100644
--- a/demo/semantic_role_labeling/api_train_v2.py
+++ b/demo/semantic_role_labeling/api_train_v2.py
@@ -4,17 +4,12 @@
 import paddle.v2 as paddle
 import paddle.v2.dataset.conll05 as conll05
 
-UNK_IDX = 0
-
 
 def db_lstm():
     word_dict, verb_dict, label_dict = conll05.get_dict()
     word_dict_len = len(word_dict)
     label_dict_len = len(label_dict)
     pred_len = len(verb_dict)
-    print 'word_dict_len,', word_dict_len
-    print 'label_dict_len,', label_dict_len
-    print 'pred_len,', pred_len
 
     mark_dict_len = 2
     word_dim = 32

From 495861f55923dcd9092e74e401e50aa8deeb0fd5 Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Thu, 2 Mar 2017 21:30:47 +0800
Subject: [PATCH 070/153] add v2 demo to seqtoseq, fix __dfs_travel__ for v2
 layers

---
 demo/seqToseq/api_train_v2.py    | 106 +++++++++++++++++++++++++++++++
 demo/seqToseq/seqToseq_net_v2.py |  90 ++++++++++++++++++++++++++
 python/paddle/v2/layer.py        |   2 +-
 python/paddle/v2/topology.py     |   6 +-
 4 files changed, 202 insertions(+), 2 deletions(-)
 create mode 100644 demo/seqToseq/api_train_v2.py
 create mode 100644 demo/seqToseq/seqToseq_net_v2.py

diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py
new file mode 100644
index 0000000000000..efbab8d7b9534
--- /dev/null
+++ b/demo/seqToseq/api_train_v2.py
@@ -0,0 +1,106 @@
+import os
+
+import paddle.v2 as paddle
+
+from seqToseq_net_v2 import seqToseq_net_v2
+
+### Data Definiation
+data_dir = "./data/pre-wmt14"
+src_lang_dict = os.path.join(data_dir, 'src.dict')
+trg_lang_dict = os.path.join(data_dir, 'trg.dict')
+
+source_dict_dim = len(open(src_lang_dict, "r").readlines())
+target_dict_dim = len(open(trg_lang_dict, "r").readlines())
+
+
+def read_to_dict(dict_path):
+    with open(dict_path, "r") as fin:
+        out_dict = {
+            line.strip(): line_count
+            for line_count, line in enumerate(fin)
+        }
+    return out_dict
+
+
+src_dict = read_to_dict(src_lang_dict)
+trg_dict = read_to_dict(trg_lang_dict)
+
+train_list = os.path.join(data_dir, 'train.list')
+test_list = os.path.join(data_dir, 'test.list')
+
+UNK_IDX = 2
+START = ""
+END = ""
+
+
+def _get_ids(s, dictionary):
+    words = s.strip().split()
+    return [dictionary[START]] + \
+           [dictionary.get(w, UNK_IDX) for w in words] + \
+           [dictionary[END]]
+
+
+def train_reader(file_name):
+    def reader():
+        with open(file_name, 'r') as f:
+            for line_count, line in enumerate(f):
+                line_split = line.strip().split('\t')
+                if len(line_split) != 2:
+                    continue
+                src_seq = line_split[0]  # one source sequence
+                src_ids = _get_ids(src_seq, src_dict)
+
+                trg_seq = line_split[1]  # one target sequence
+                trg_words = trg_seq.split()
+                trg_ids = [trg_dict.get(w, UNK_IDX) for w in trg_words]
+
+                # remove sequence whose length > 80 in training mode
+                if len(src_ids) > 80 or len(trg_ids) > 80:
+                    continue
+                trg_ids_next = trg_ids + [trg_dict[END]]
+                trg_ids = [trg_dict[START]] + trg_ids
+
+                yield src_ids, trg_ids, trg_ids_next
+
+    return reader
+
+
+def main():
+    paddle.init(use_gpu=False, trainer_count=1)
+
+    # reader = train_reader("data/pre-wmt14/train/train")
+    # define network topology
+    cost = seqToseq_net_v2(source_dict_dim, target_dict_dim)
+    parameters = paddle.parameters.create(cost)
+    optimizer = paddle.optimizer.Adam(batch_size=50, learning_rate=5e-4)
+
+    def event_handler(event):
+        if isinstance(event, paddle.event.EndIteration):
+            if event.batch_id % 100 == 0:
+                print "Pass %d, Batch %d, Cost %f, %s" % (
+                    event.pass_id, event.batch_id, event.cost, event.metrics)
+
+    trainer = paddle.trainer.SGD(cost=cost,
+                                 parameters=parameters,
+                                 update_equation=optimizer)
+
+    reader_dict = {
+        'source_language_word': 0,
+        'target_language_word': 1,
+        'target_language_next_word': 2
+    }
+
+    trn_reader = paddle.reader.batched(
+        paddle.reader.shuffle(
+            train_reader("data/pre-wmt14/train/train"), buf_size=8192),
+        batch_size=10)
+
+    trainer.train(
+        reader=trn_reader,
+        event_handler=event_handler,
+        num_passes=10000,
+        reader_dict=reader_dict)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/demo/seqToseq/seqToseq_net_v2.py b/demo/seqToseq/seqToseq_net_v2.py
new file mode 100644
index 0000000000000..7e057e24405f8
--- /dev/null
+++ b/demo/seqToseq/seqToseq_net_v2.py
@@ -0,0 +1,90 @@
+import paddle.v2.activation as activation
+import paddle.v2.attr as attr
+import paddle.v2.data_type as data_type
+import paddle.v2.layer as layer
+import paddle.v2.networks as networks
+
+
+def seqToseq_net_v2(source_dict_dim, target_dict_dim):
+    ### Network Architecture
+    word_vector_dim = 512  # dimension of word vector
+    decoder_size = 512  # dimension of hidden unit in GRU Decoder network
+    encoder_size = 512  # dimension of hidden unit in GRU Encoder network
+
+    #### Encoder
+    src_word_id = layer.data(
+        name='source_language_word',
+        type=data_type.dense_vector(source_dict_dim))
+    src_embedding = layer.embedding(
+        input=src_word_id,
+        size=word_vector_dim,
+        param_attr=attr.ParamAttr(name='_source_language_embedding'))
+    src_forward = networks.simple_gru(input=src_embedding, size=encoder_size)
+    src_backward = networks.simple_gru(
+        input=src_embedding, size=encoder_size, reverse=True)
+    encoded_vector = layer.concat(input=[src_forward, src_backward])
+
+    #### Decoder
+    with layer.mixed(size=decoder_size) as encoded_proj:
+        encoded_proj += layer.full_matrix_projection(input=encoded_vector)
+
+    backward_first = layer.first_seq(input=src_backward)
+
+    with layer.mixed(size=decoder_size, act=activation.Tanh()) as decoder_boot:
+        decoder_boot += layer.full_matrix_projection(input=backward_first)
+
+    def gru_decoder_with_attention(enc_vec, enc_proj, current_word):
+
+        decoder_mem = layer.memory(
+            name='gru_decoder', size=decoder_size, boot_layer=decoder_boot)
+
+        context = networks.simple_attention(
+            encoded_sequence=enc_vec,
+            encoded_proj=enc_proj,
+            decoder_state=decoder_mem)
+
+        with layer.mixed(size=decoder_size * 3) as decoder_inputs:
+            decoder_inputs += layer.full_matrix_projection(input=context)
+            decoder_inputs += layer.full_matrix_projection(input=current_word)
+
+        gru_step = layer.gru_step(
+            name='gru_decoder',
+            input=decoder_inputs,
+            output_mem=decoder_mem,
+            size=decoder_size)
+
+        with layer.mixed(
+                size=target_dict_dim, bias_attr=True,
+                act=activation.Softmax()) as out:
+            out += layer.full_matrix_projection(input=gru_step)
+        return out
+
+    decoder_group_name = "decoder_group"
+    group_input1 = layer.StaticInputV2(input=encoded_vector, is_seq=True)
+    group_input2 = layer.StaticInputV2(input=encoded_proj, is_seq=True)
+    group_inputs = [group_input1, group_input2]
+
+    trg_embedding = layer.embedding(
+        input=layer.data(
+            name='target_language_word',
+            type=data_type.dense_vector(target_dict_dim)),
+        size=word_vector_dim,
+        param_attr=attr.ParamAttr(name='_target_language_embedding'))
+    group_inputs.append(trg_embedding)
+
+    # For decoder equipped with attention mechanism, in training,
+    # target embeding (the groudtruth) is the data input,
+    # while encoded source sequence is accessed to as an unbounded memory.
+    # Here, the StaticInput defines a read-only memory
+    # for the recurrent_group.
+    decoder = layer.recurrent_group(
+        name=decoder_group_name,
+        step=gru_decoder_with_attention,
+        input=group_inputs)
+
+    lbl = layer.data(
+        name='target_language_next_word',
+        type=data_type.dense_vector(target_dict_dim))
+    cost = layer.classification_cost(input=decoder, label=lbl)
+
+    return cost
diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py
index 2f55611aaa1d3..010773ddbd96d 100644
--- a/python/paddle/v2/layer.py
+++ b/python/paddle/v2/layer.py
@@ -262,7 +262,7 @@ def __init__(self, input, is_seq=False, size=None):
         self.input = input
         self.is_seq = is_seq
         self.size = size
-        # TODO(qiaolongfei): add size
+        # TODO(add size check)
         # assert input.size is not None or size is not None
 
 
diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py
index 4c211254319bb..f0679c5675b0c 100644
--- a/python/paddle/v2/topology.py
+++ b/python/paddle/v2/topology.py
@@ -17,6 +17,7 @@
 from paddle.proto.ModelConfig_pb2 import ModelConfig
 
 import layer as v2_layer
+from layer import WithExtraParent
 
 __all__ = ['Topology']
 
@@ -40,7 +41,10 @@ def __bfs_travel__(callback, *layers):
         __break__ = callback(each_layer)
         if __break__:
             return
-        __bfs_travel__(callback, *each_layer.__parent_layers__.values())
+        __layers__ = each_layer.__parent_layers__.values()
+        if isinstance(each_layer, WithExtraParent):
+            __layers__ = __layers__ + each_layer.extra_parent()
+        __bfs_travel__(callback, *__layers__)
 
 
 class Topology(object):

From 4a265b5200bb86ef81f08d9fce516330b2c2f41a Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Thu, 2 Mar 2017 21:42:11 +0800
Subject: [PATCH 071/153] Use reader in dataset imdb.py

---
 demo/sentiment/train_v2.py       | 38 ++++++++------------------------
 python/paddle/v2/dataset/imdb.py |  5 +++++
 2 files changed, 14 insertions(+), 29 deletions(-)

diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py
index 3d595fad30b71..0fa74948533b4 100644
--- a/demo/sentiment/train_v2.py
+++ b/demo/sentiment/train_v2.py
@@ -2,10 +2,11 @@
 from os.path import join as join_path
 import paddle.trainer_config_helpers.attrs as attrs
 from paddle.trainer_config_helpers.poolings import MaxPooling
-import paddle.v2 as paddle
 import paddle.v2.layer as layer
 import paddle.v2.activation as activation
 import paddle.v2.data_type as data_type
+import paddle.v2.dataset.imdb as imdb
+import paddle.v2 as paddle
 
 
 def sequence_conv_pool(input,
@@ -189,36 +190,15 @@ def stacked_lstm_net(input_dim,
     return cost
 
 
-def data_reader(data_file, dict_file):
-    def reader():
-        with open(dict_file, 'r') as fdict, open(data_file, 'r') as fdata:
-            dictionary = dict()
-            for i, line in enumerate(fdict):
-                dictionary[line.split('\t')[0]] = i
-
-            for line_count, line in enumerate(fdata):
-                label, comment = line.strip().split('\t\t')
-                label = int(label)
-                words = comment.split()
-                word_slot = [dictionary[w] for w in words if w in dictionary]
-                yield (word_slot, label)
-
-    return reader
-
-
 if __name__ == '__main__':
-    # data file
-    train_file = "./data/pre-imdb/train_part_000"
-    test_file = "./data/pre-imdb/test_part_000"
-    dict_file = "./data/pre-imdb/dict.txt"
-    labels = "./data/pre-imdb/labels.list"
-
     # init
     paddle.init(use_gpu=True, trainer_count=4)
 
     # network config
-    dict_dim = len(open(dict_file).readlines())
-    class_dim = len(open(labels).readlines())
+    print 'load dictionary...'
+    word_dict = imdb.word_dict()
+    dict_dim = len(word_dict)
+    class_dim = 2
 
     # Please choose the way to build the network
     # by uncommenting the corresponding line.
@@ -246,7 +226,7 @@ def event_handler(event):
         if isinstance(event, paddle.event.EndPass):
             result = trainer.test(
                 reader=paddle.reader.batched(
-                    data_reader(test_file, dict_file), batch_size=128),
+                    lambda: imdb.test(word_dict), batch_size=128),
                 reader_dict={'word': 0,
                              'label': 1})
             print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
@@ -259,8 +239,8 @@ def event_handler(event):
     trainer.train(
         reader=paddle.reader.batched(
             paddle.reader.shuffle(
-                data_reader(train_file, dict_file), buf_size=4096),
-            batch_size=128),
+                lambda: imdb.train(word_dict), buf_size=1000),
+            batch_size=100),
         event_handler=event_handler,
         reader_dict={'word': 0,
                      'label': 1},
diff --git a/python/paddle/v2/dataset/imdb.py b/python/paddle/v2/dataset/imdb.py
index 433e37380f840..db388be1e06d6 100644
--- a/python/paddle/v2/dataset/imdb.py
+++ b/python/paddle/v2/dataset/imdb.py
@@ -118,3 +118,8 @@ def test(word_idx):
     return reader_creator(
         re.compile("aclImdb/test/pos/.*\.txt$"),
         re.compile("aclImdb/test/neg/.*\.txt$"), word_idx, 1000)
+
+
+def word_dict():
+    return build_dict(
+        re.compile("aclImdb/((train)|(test))/((pos)|(neg))/.*\.txt$"), 150)

From fa3b1c465b4e2e2cc8051b8f47ed4b8f860b616e Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Thu, 2 Mar 2017 00:38:06 +0000
Subject: [PATCH 072/153] change argument name of
 data_type.integer_value/integer_value_sequence to ele_range, add
 documentation.

---
 python/paddle/trainer/PyDataProvider2.py   | 16 ++++++++++++----
 python/paddle/v2/tests/test_data_feeder.py | 15 ++++++++-------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/python/paddle/trainer/PyDataProvider2.py b/python/paddle/trainer/PyDataProvider2.py
index bd24c68b6fe88..afde7453a15fc 100644
--- a/python/paddle/trainer/PyDataProvider2.py
+++ b/python/paddle/trainer/PyDataProvider2.py
@@ -65,14 +65,18 @@ def sparse_value_slot(dim, seq_type=SequenceType.NO_SEQUENCE):
     return InputType(dim, seq_type, DataType.SparseValue)
 
 
-def index_slot(dim, seq_type=SequenceType.NO_SEQUENCE):
-    return InputType(dim, seq_type, DataType.Index)
+def index_slot(ele_range, seq_type=SequenceType.NO_SEQUENCE):
+    """Data type of integer.
+    :param ele_range: range of this integer.
+    """
+    return InputType(ele_range, seq_type, DataType.Index)
 
 
 dense_vector = dense_slot
 sparse_binary_vector = sparse_non_value_slot
 sparse_vector = sparse_value_slot
 integer_value = index_slot
+integer_value.__doc__ = index_slot.__doc__
 
 
 def dense_vector_sequence(dim):
@@ -99,8 +103,11 @@ def sparse_vector_sub_sequence(dim):
     return sparse_vector(dim, seq_type=SequenceType.SUB_SEQUENCE)
 
 
-def integer_value_sequence(dim):
-    return integer_value(dim, seq_type=SequenceType.SEQUENCE)
+def integer_value_sequence(ele_range):
+    """Data type of a sequence of integer.
+    :param ele_range: range of each element.
+    """
+    return integer_value(ele_range, seq_type=SequenceType.SEQUENCE)
 
 
 def integer_value_sub_sequence(dim):
@@ -108,6 +115,7 @@ def integer_value_sub_sequence(dim):
 
 
 integer_sequence = integer_value_sequence
+integer_sequence.__doc__ = integer_value_sequence.__doc__
 
 
 class SingleSlotWrapper(object):
diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py
index ab2bc5df76cd8..1b1f5aef8b811 100644
--- a/python/paddle/v2/tests/test_data_feeder.py
+++ b/python/paddle/v2/tests/test_data_feeder.py
@@ -110,14 +110,14 @@ def test_sparse(self):
             self.assertAlmostEqual(value.all(), w[i].all())
 
     def test_integer(self):
-        dim = 100
+        ele_range = 100
         batch_size = 32
         index = []
         for i in xrange(batch_size):
             each_sample = []
-            each_sample.append(np.random.randint(dim))
+            each_sample.append(np.random.randint(ele_range))
             index.append(each_sample)
-        feeder = DataFeeder([('input', data_type.integer_value(dim))],
+        feeder = DataFeeder([('input', data_type.integer_value(ele_range))],
                             {'input': 0})
         arg = feeder(index)
         output = arg.getSlotIds(0).copyToNumpyArray()
@@ -125,7 +125,7 @@ def test_integer(self):
         self.assertEqual(output.all(), index.flatten().all())
 
     def test_integer_sequence(self):
-        dim = 10000
+        ele_range = 10000
         batch_size = 32
         start = [0]
         data = []
@@ -133,11 +133,12 @@ def test_integer_sequence(self):
             each_sample = []
             each_sample.append(
                 self.sparse_binary_reader(
-                    dim, 30, non_empty=True))
+                    ele_range, 30, non_empty=True))
             data.append(each_sample)
             start.append(len(each_sample[0]) + start[-1])
-        feeder = DataFeeder([('input', data_type.integer_value_sequence(dim))],
-                            {'input': 0})
+        feeder = DataFeeder(
+            [('input', data_type.integer_value_sequence(ele_range))],
+            {'input': 0})
         arg = feeder(data)
         output_data = arg.getSlotIds(0).copyToNumpyArray()
         output_start = arg.getSlotSequenceStartPositions(0).copyToNumpyArray()

From e87181db8d4d67dc3c35675adf0c24d399dce88e Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Thu, 2 Mar 2017 19:47:17 +0000
Subject: [PATCH 073/153] use value_range instead of ele_range

---
 python/paddle/trainer/PyDataProvider2.py   | 12 ++++++------
 python/paddle/v2/tests/test_data_feeder.py | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/python/paddle/trainer/PyDataProvider2.py b/python/paddle/trainer/PyDataProvider2.py
index afde7453a15fc..4e3c4db853205 100644
--- a/python/paddle/trainer/PyDataProvider2.py
+++ b/python/paddle/trainer/PyDataProvider2.py
@@ -65,11 +65,11 @@ def sparse_value_slot(dim, seq_type=SequenceType.NO_SEQUENCE):
     return InputType(dim, seq_type, DataType.SparseValue)
 
 
-def index_slot(ele_range, seq_type=SequenceType.NO_SEQUENCE):
+def index_slot(value_range, seq_type=SequenceType.NO_SEQUENCE):
     """Data type of integer.
-    :param ele_range: range of this integer.
+    :param value_range: range of this integer.
     """
-    return InputType(ele_range, seq_type, DataType.Index)
+    return InputType(value_range, seq_type, DataType.Index)
 
 
 dense_vector = dense_slot
@@ -103,11 +103,11 @@ def sparse_vector_sub_sequence(dim):
     return sparse_vector(dim, seq_type=SequenceType.SUB_SEQUENCE)
 
 
-def integer_value_sequence(ele_range):
+def integer_value_sequence(value_range):
     """Data type of a sequence of integer.
-    :param ele_range: range of each element.
+    :param value_range: range of each element.
     """
-    return integer_value(ele_range, seq_type=SequenceType.SEQUENCE)
+    return integer_value(value_range, seq_type=SequenceType.SEQUENCE)
 
 
 def integer_value_sub_sequence(dim):
diff --git a/python/paddle/v2/tests/test_data_feeder.py b/python/paddle/v2/tests/test_data_feeder.py
index 1b1f5aef8b811..71eb3bf31425c 100644
--- a/python/paddle/v2/tests/test_data_feeder.py
+++ b/python/paddle/v2/tests/test_data_feeder.py
@@ -110,14 +110,14 @@ def test_sparse(self):
             self.assertAlmostEqual(value.all(), w[i].all())
 
     def test_integer(self):
-        ele_range = 100
+        value_range = 100
         batch_size = 32
         index = []
         for i in xrange(batch_size):
             each_sample = []
-            each_sample.append(np.random.randint(ele_range))
+            each_sample.append(np.random.randint(value_range))
             index.append(each_sample)
-        feeder = DataFeeder([('input', data_type.integer_value(ele_range))],
+        feeder = DataFeeder([('input', data_type.integer_value(value_range))],
                             {'input': 0})
         arg = feeder(index)
         output = arg.getSlotIds(0).copyToNumpyArray()
@@ -125,7 +125,7 @@ def test_integer(self):
         self.assertEqual(output.all(), index.flatten().all())
 
     def test_integer_sequence(self):
-        ele_range = 10000
+        value_range = 10000
         batch_size = 32
         start = [0]
         data = []
@@ -133,11 +133,11 @@ def test_integer_sequence(self):
             each_sample = []
             each_sample.append(
                 self.sparse_binary_reader(
-                    ele_range, 30, non_empty=True))
+                    value_range, 30, non_empty=True))
             data.append(each_sample)
             start.append(len(each_sample[0]) + start[-1])
         feeder = DataFeeder(
-            [('input', data_type.integer_value_sequence(ele_range))],
+            [('input', data_type.integer_value_sequence(value_range))],
             {'input': 0})
         arg = feeder(data)
         output_data = arg.getSlotIds(0).copyToNumpyArray()

From 4cbbb23fa315eb3b58929f059c59ae7498cdbf45 Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Wed, 1 Mar 2017 13:25:47 -0800
Subject: [PATCH 074/153] expose build_dict in imikolov dataset, fix bug that
 len(word_dict) is not bigger than all index in word_dict.

---
 python/paddle/v2/dataset/imikolov.py          | 31 +++++++++----------
 .../paddle/v2/dataset/tests/imikolov_test.py  | 10 ++++--
 2 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py
index 285d3eaca8317..deb556942d9b0 100644
--- a/python/paddle/v2/dataset/imikolov.py
+++ b/python/paddle/v2/dataset/imikolov.py
@@ -17,7 +17,7 @@
 import paddle.v2.dataset.common
 import tarfile
 
-__all__ = ['train', 'test']
+__all__ = ['train', 'test', 'build_dict']
 
 URL = 'http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz'
 MD5 = '30177ea32e27c525793142b6bf2c8e2d'
@@ -37,7 +37,9 @@ def word_count(f, word_freq=None):
     return word_freq
 
 
-def build_dict(train_filename, test_filename):
+def build_dict():
+    train_filename = './simple-examples/data/ptb.train.txt'
+    test_filename = './simple-examples/data/ptb.valid.txt'
     with tarfile.open(
             paddle.v2.dataset.common.download(
                 paddle.v2.dataset.imikolov.URL, 'imikolov',
@@ -45,27 +47,22 @@ def build_dict(train_filename, test_filename):
         trainf = tf.extractfile(train_filename)
         testf = tf.extractfile(test_filename)
         word_freq = word_count(testf, word_count(trainf))
+        if '' in word_freq:
+            # remove  for now, since we will set it as last index
+            del word_freq['']
 
         TYPO_FREQ = 50
         word_freq = filter(lambda x: x[1] > TYPO_FREQ, word_freq.items())
 
-        dictionary = sorted(word_freq, key=lambda x: (-x[1], x[0]))
-        words, _ = list(zip(*dictionary))
+        word_freq_sorted = sorted(word_freq, key=lambda x: (-x[1], x[0]))
+        words, _ = list(zip(*word_freq_sorted))
         word_idx = dict(zip(words, xrange(len(words))))
         word_idx[''] = len(words)
 
     return word_idx
 
 
-word_idx = {}
-
-
-def reader_creator(filename, n):
-    global word_idx
-    if len(word_idx) == 0:
-        word_idx = build_dict('./simple-examples/data/ptb.train.txt',
-                              './simple-examples/data/ptb.valid.txt')
-
+def reader_creator(filename, word_idx, n):
     def reader():
         with tarfile.open(
                 paddle.v2.dataset.common.download(
@@ -84,9 +81,9 @@ def reader():
     return reader
 
 
-def train(n):
-    return reader_creator('./simple-examples/data/ptb.train.txt', n)
+def train(word_idx, n):
+    return reader_creator('./simple-examples/data/ptb.train.txt', word_idx, n)
 
 
-def test(n):
-    return reader_creator('./simple-examples/data/ptb.valid.txt', n)
+def test(word_idx, n):
+    return reader_creator('./simple-examples/data/ptb.valid.txt', word_idx, n)
diff --git a/python/paddle/v2/dataset/tests/imikolov_test.py b/python/paddle/v2/dataset/tests/imikolov_test.py
index 9b1748eaaa7f9..009e55243a594 100644
--- a/python/paddle/v2/dataset/tests/imikolov_test.py
+++ b/python/paddle/v2/dataset/tests/imikolov_test.py
@@ -1,6 +1,8 @@
 import paddle.v2.dataset.imikolov
 import unittest
 
+WORD_DICT = paddle.v2.dataset.imikolov.build_dict()
+
 
 class TestMikolov(unittest.TestCase):
     def check_reader(self, reader, n):
@@ -9,11 +11,15 @@ def check_reader(self, reader, n):
 
     def test_train(self):
         n = 5
-        self.check_reader(paddle.v2.dataset.imikolov.train(n), n)
+        self.check_reader(paddle.v2.dataset.imikolov.train(WORD_DICT, n), n)
 
     def test_test(self):
         n = 5
-        self.check_reader(paddle.v2.dataset.imikolov.test(n), n)
+        self.check_reader(paddle.v2.dataset.imikolov.test(WORD_DICT, n), n)
+
+    def test_total(self):
+        _, idx = zip(*WORD_DICT.items())
+        self.assertEqual(sorted(idx)[-1], len(WORD_DICT) - 1)
 
 
 if __name__ == '__main__':

From a8a25238bbde726834955db9cc9c2deeed36e33d Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Wed, 1 Mar 2017 23:14:36 +0000
Subject: [PATCH 075/153] remove ITrainer interface since parameters for train
 is already getting out of sync. Currently there is no benefit of having a
 interface.

---
 python/paddle/v2/trainer.py | 23 ++---------------------
 1 file changed, 2 insertions(+), 21 deletions(-)

diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py
index e743a49523ff2..6652a1e8fec57 100644
--- a/python/paddle/v2/trainer.py
+++ b/python/paddle/v2/trainer.py
@@ -8,7 +8,7 @@
 from . import optimizer as v2_optimizer
 from . import parameters as v2_parameters
 
-__all__ = ['ITrainer', 'SGD']
+__all__ = ['SGD']
 
 
 def default_event_handler(event):
@@ -22,26 +22,7 @@ def default_event_handler(event):
     pass
 
 
-class ITrainer(object):
-    """
-    The interface of Trainer. The only exposed method is `train`.
-    """
-
-    def train(self, reader, topology, parameters, event_handler=None):
-        """
-        train method.
-
-        :param reader:
-        :param topology:
-        :param parameters:
-        :param event_handler:
-        :return:
-        """
-
-        raise NotImplementedError()
-
-
-class SGD(ITrainer):
+class SGD():
     def __init__(self, cost, parameters, update_equation):
         """
         Simple SGD Trainer.

From 8ebfe554bda96e2ff64d64fe9ae6ca461938411a Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Thu, 2 Mar 2017 15:38:48 -0800
Subject: [PATCH 076/153] add batch reader into reader design doc

---
 doc/design/reader/README.md | 91 +++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 25 deletions(-)

diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md
index 17d52b9e20b81..03119fdd74502 100644
--- a/doc/design/reader/README.md
+++ b/doc/design/reader/README.md
@@ -4,9 +4,10 @@ At training and testing time, PaddlePaddle programs need to read data. To ease t
 
 - A *reader* is a function that reads data (from file, network, random number generator, etc) and yields data items.
 - A *reader creator* is a function that returns a reader function.
-- A *reader* decorator is a function, which accepts one or more readers, and returns a reader.
+- A *reader decorator* is a function, which accepts one or more readers, and returns a reader.
+- A *batch reader* is a function that reads data (from *reader*, file, network, random number generator, etc) and yields a batch of data items.
 
-and provide frequently used reader creators and reader decorators.
+and provide function which converts reader to batch reader, frequently used reader creators and reader decorators.
 
 ## Data Reader Interface
 
@@ -37,9 +38,54 @@ def reader_creator_random_imageand_label(widht, height, label):
 	return reader
 ```
 
+## Batch Reader Interface
+
+*batch reader* can be any function with no parameter that creates a iterable (anything can be used in `for x in iterable`). The output of the iterable should be a batch (list) of data items. Each item inside the list must be a tuple.
+
+Here are valid outputs:
+```python
+# a mini batch of three data items. Each data item consist three columns of data, each of which is 1.
+[(1, 1, 1),
+(2, 2, 2),
+(3, 3, 3)]
+
+# a mini batch of three data items, each data item is a list (single column).
+[([1,1,1],),
+([2,2,2],),
+([3,3,3],),
+```
+
+Please note that each item inside the list must be a tuple, below is an invalid output:
+```python
+ # wrong, [1,1,1] needs to be inside a tuple: ([1,1,1],).
+ # Otherwise it's ambiguous whether [1,1,1] means a single column of data [1, 1, 1],
+ # or three column of datas, each of which is 1.
+[[1,1,1],
+[2,2,2],
+[3,3,3]]
+```
+
+It's easy to convert from reader to batch reader:
+```python
+mnist_train = paddle.dataset.mnist.train()
+mnist_train_batch_reader = paddle.batch(mnist_train, 128)
+```
+
+Also easy to create custom batch reader:
+```python
+def custom_batch_reader():
+	while True:
+		batch = []
+		for i in xrange(128):
+			batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended.
+		yield batch
+
+mnist_random_image_batch_reader = custom_batch_reader
+```
+
 ## Usage
 
-data reader, mapping from item(s) read to data layer, batch size and number of total pass will be passed into `paddle.train`:
+batch reader, mapping from item(s) read to data layer, batch size and number of total pass will be passed into `paddle.train`:
 
 ```python
 # two data layer is created:
@@ -47,8 +93,8 @@ image_layer = paddle.layer.data("image", ...)
 label_layer = paddle.layer.data("label", ...)
 
 # ...
-
-paddle.train(paddle.dataset.mnist, {"image":0, "label":1}, 128, 10, ...)
+batch_reader = paddle.batch(paddle.dataset.mnist.train(), 128)
+paddle.train(batch_reader, {"image":0, "label":1}, 128, 10, ...)
 ```
 
 ## Data Reader Decorator
@@ -64,7 +110,7 @@ Since reading data may take time and training can not proceed without data. It i
 Use `paddle.reader.buffered` to prefetch data:
 
 ```python
-buffered_reader = paddle.reader.buffered(paddle.dataset.mnist, 100)
+buffered_reader = paddle.reader.buffered(paddle.dataset.mnist.train(), 100)
 ```
 
 `buffered_reader` will try to buffer (prefetch) `100` data entries.
@@ -91,10 +137,10 @@ def reader_creator_bool(t):
 true_reader = reader_creator_bool(True)
 false_reader = reader_creator_bool(False)
 
-reader = paddle.reader.compose(paddle.dataset.mnist, data_reader_creator_random_image(20, 20), true_reader, false_reader)
-# Skipped 1 because paddle.dataset.mnist produces two items per data entry.
+reader = paddle.reader.compose(paddle.dataset.mnist.train(), data_reader_creator_random_image(20, 20), true_reader, false_reader)
+# Skipped 1 because paddle.dataset.mnist.train() produces two items per data entry.
 # And we don't care second item at this time.
-paddle.train(reader, {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...)
+paddle.train(paddle.batch(reader, 128), {"true_image":0, "fake_image": 2, "true_label": 3, "false_label": 4}, ...)
 ```
 
 ### Shuffle
@@ -103,16 +149,20 @@ Given shuffle buffer size `n`, `paddle.reader.shuffle` will return a data reader
 
 Example:
 ```python
-reader = paddle.reader.shuffle(paddle.dataset.mnist, 512)
+reader = paddle.reader.shuffle(paddle.dataset.mnist.train(), 512)
 ```
 
 ## Q & A
 
-### Why return only a single entry, but not a mini batch?
+### Why reader return only a single entry, but not a mini batch?
+
+Always returning a single entry make reusing existing data readers much easier (e.g., if existing reader return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2).
+
+We provide function `paddle.batch` to turn (single entry) reader into batch reader.
 
-If a mini batch is returned, data reader need to take care of batch size. But batch size is a concept for training, it makes more sense for user to specify batch size as a parameter for `train`.
+### Why do we need batch reader, isn't train take reader and batch_size as arguments sufficient?
 
-Practically, always return a single entry make reusing existing data readers much easier (e.g., if existing reader return not a single entry but 3 entries, training code will be more complex because it need to handle cases like batch size 2).
+In most of the case, train taking reader and batch_size as arguments would be sufficent. However sometimes user want to customize order of data entries inside a mini batch. Or even change batch size dynamically.
 
 ### Why use a dictionary but not a list to provide mapping?
 
@@ -137,7 +187,7 @@ def image_reader_creator(image_path, label_path, n):
 
 # images_reader_creator creates a reader
 reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024)
-paddle.train(reader, {"image":0, "label":1}, ...)
+paddle.train(paddle.batch(reader, 128), {"image":0, "label":1}, ...)
 ```
 
 ### How is `paddle.train` implemented
@@ -145,17 +195,8 @@ paddle.train(reader, {"image":0, "label":1}, ...)
 An example implementation of paddle.train could be:
 
 ```python
-def make_minibatch(reader, minibatch_size):
-	def ret():
-		r = reader()
-		buf = [r.next() for x in xrange(minibatch_size)]
-		while len(buf) > 0:
-			yield buf
-			buf = [r.next() for x in xrange(minibatch_size)]
-	return ret
-
-def train(reader, mapping, batch_size, total_pass):
+def train(batch_reader, mapping, batch_size, total_pass):
 	for pass_idx in range(total_pass):
-		for mini_batch in make_minibatch(reader): # this loop will never end in online learning.
+		for mini_batch in batch_reader(): # this loop will never end in online learning.
 			do_forward_backward(mini_batch, mapping)
 ```

From f9ea339dd03bdf8df068e6936801db82ffd39bcd Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Thu, 2 Mar 2017 22:14:14 +0000
Subject: [PATCH 077/153] remove osx build from CI

We don't officially support OSX.
And Travis CI takes a lot of time to build osx. (long time in pending state.
Probably because travis ci don't have enough osx machines.
---
 .travis.yml                                 |  9 --------
 paddle/scripts/travis/before_install.osx.sh |  4 ----
 paddle/scripts/travis/build_and_test.sh     | 23 +++++++--------------
 3 files changed, 8 insertions(+), 28 deletions(-)
 delete mode 100755 paddle/scripts/travis/before_install.osx.sh

diff --git a/.travis.yml b/.travis.yml
index 28d1f51be7107..5a7f45a748ac7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,22 +4,14 @@ cache:
     - $HOME/third_party
     - $HOME/.ccache
     - $HOME/.cache/pip
-    - $HOME/Library/Caches/Homebrew
 sudo: required
 dist: trusty
 os:
   - linux
-  - osx
 env:
   - JOB=DOCS
   - JOB=BUILD_AND_TEST
   - JOB=PRE_COMMIT
-matrix:
-  exclude:
-    - os: osx
-      env: JOB=DOCS  # Only generate documentation in linux.
-    - os: osx
-      env: JOB=PRE_COMMIT # Only check pre-commit hook in linux
 
 addons:
   apt:
@@ -53,7 +45,6 @@ before_install:
         fi
       fi
     fi
-  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then paddle/scripts/travis/before_install.osx.sh; fi
   - if [[ "$JOB" == "PRE_COMMIT" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; fi
   # Paddle is using protobuf 3.1 currently. Protobuf 3.2 breaks the compatibility. So we specify the python 
   # protobuf version.
diff --git a/paddle/scripts/travis/before_install.osx.sh b/paddle/scripts/travis/before_install.osx.sh
deleted file mode 100755
index 80f031a74e705..0000000000000
--- a/paddle/scripts/travis/before_install.osx.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-brew update
-brew tap homebrew/science
-brew install openblas swig md5sha1sum
diff --git a/paddle/scripts/travis/build_and_test.sh b/paddle/scripts/travis/build_and_test.sh
index 5e6350b574585..7deb3e62e88de 100755
--- a/paddle/scripts/travis/build_and_test.sh
+++ b/paddle/scripts/travis/build_and_test.sh
@@ -2,18 +2,11 @@
 source ./common.sh
 
 NPROC=1
-if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
-  export PYTHONPATH=/opt/python/2.7.12/lib/python2.7/site-packages
-  export PYTHONHOME=/opt/python/2.7.12
-  export PATH=/opt/python/2.7.12/bin:${PATH}
-  cmake .. -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DON_TRAVIS=ON -DON_COVERALLS=ON -DCOVERALLS_UPLOAD=ON ${EXTRA_CMAKE_OPTS}
-  NRPOC=`nproc`
-  make -j $NPROC
-  make coveralls
-  sudo make install
-elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
-  export PYTHONPATH=/usr/local/lib/python2.7/site-packages
-  cmake .. -DON_TRAVIS=ON -DON_COVERALLS=ON -DCOVERALLS_UPLOAD=ON ${EXTRA_CMAKE_OPTS}
-  NPROC=`sysctl -n hw.ncpu`
-  make -j $NPROC
-fi
+export PYTHONPATH=/opt/python/2.7.12/lib/python2.7/site-packages
+export PYTHONHOME=/opt/python/2.7.12
+export PATH=/opt/python/2.7.12/bin:${PATH}
+cmake .. -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DON_TRAVIS=ON -DON_COVERALLS=ON -DCOVERALLS_UPLOAD=ON ${EXTRA_CMAKE_OPTS}
+NRPOC=`nproc`
+make -j $NPROC
+make coveralls
+sudo make install

From 4157e009c1fb2c0e12e806ce52da0f9e4890084d Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Fri, 3 Mar 2017 01:48:35 +0000
Subject: [PATCH 078/153] dataset: print download progress

---
 python/paddle/v2/dataset/common.py | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py
index 397c9e66d4954..0944fe973d5b9 100644
--- a/python/paddle/v2/dataset/common.py
+++ b/python/paddle/v2/dataset/common.py
@@ -16,6 +16,7 @@
 import hashlib
 import os
 import shutil
+import sys
 
 __all__ = ['DATA_HOME', 'download', 'md5file']
 
@@ -35,6 +36,7 @@ def md5file(fname):
 
 
 def download(url, module_name, md5sum):
+    print "downloading %s" % url
     dirname = os.path.join(DATA_HOME, module_name)
     if not os.path.exists(dirname):
         os.makedirs(dirname)
@@ -42,8 +44,22 @@ def download(url, module_name, md5sum):
     filename = os.path.join(dirname, url.split('/')[-1])
     if not (os.path.exists(filename) and md5file(filename) == md5sum):
         r = requests.get(url, stream=True)
-        with open(filename, 'w') as f:
-            shutil.copyfileobj(r.raw, f)
+        total_length = r.headers.get('content-length')
+
+        if total_length is None:
+            with open(filename, 'w') as f:
+                shutil.copyfileobj(r.raw, f)
+        else:
+            with open(filename, 'w') as f:
+                dl = 0
+                total_length = int(total_length)
+                for data in r.iter_content(chunk_size=4096):
+                    dl += len(data)
+                    f.write(data)
+                    done = int(50 * dl / total_length)
+                    sys.stdout.write("\r[%s%s]" % ('=' * done,
+                                                   ' ' * (50 - done)))
+                    sys.stdout.flush()
 
     return filename
 

From 1996d4de74d328bbb6fa2f9544955763a4eb2d2e Mon Sep 17 00:00:00 2001
From: Helin Wang 
Date: Fri, 3 Mar 2017 03:38:43 +0000
Subject: [PATCH 079/153] fix according to comment

---
 python/paddle/v2/dataset/common.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/common.py b/python/paddle/v2/dataset/common.py
index 0944fe973d5b9..3021b68ddb02e 100644
--- a/python/paddle/v2/dataset/common.py
+++ b/python/paddle/v2/dataset/common.py
@@ -36,13 +36,13 @@ def md5file(fname):
 
 
 def download(url, module_name, md5sum):
-    print "downloading %s" % url
     dirname = os.path.join(DATA_HOME, module_name)
     if not os.path.exists(dirname):
         os.makedirs(dirname)
 
     filename = os.path.join(dirname, url.split('/')[-1])
     if not (os.path.exists(filename) and md5file(filename) == md5sum):
+        print "Cache file %s not found, downloading %s" % (filename, url)
         r = requests.get(url, stream=True)
         total_length = r.headers.get('content-length')
 

From e76264f97e09c47edc78ef811cff57f8382df51c Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Fri, 3 Mar 2017 13:24:35 +0800
Subject: [PATCH 080/153] redirect code coverage to /dev/null

---
 cmake/coverallsGcovJsons.cmake | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/cmake/coverallsGcovJsons.cmake b/cmake/coverallsGcovJsons.cmake
index ae3530c3a0eeb..7dfe0c8bf9b12 100644
--- a/cmake/coverallsGcovJsons.cmake
+++ b/cmake/coverallsGcovJsons.cmake
@@ -110,14 +110,15 @@ endmacro()
 
 # Get the coverage data.
 file(GLOB_RECURSE GCDA_FILES "${COV_PATH}" "*.gcda")
-message("GCDA files:")
+message("Process GCDA files:")
+message("===============================")
 
 # Get a list of all the object directories needed by gcov
 # (The directories the .gcda files and .o files are found in)
 # and run gcov on those.
 foreach(GCDA ${GCDA_FILES})
-	message("Process: ${GCDA}")
-	message("------------------------------------------------------------------------------")
+	# message("Process: ${GCDA}")
+	# message("------------------------------------------------------------------------------")
 	get_filename_component(GCDA_DIR ${GCDA} PATH)
 
 	#
@@ -135,7 +136,7 @@ foreach(GCDA ${GCDA_FILES})
 	# If -p is not specified then the file is named only "the_file.c.gcov"
 	#
 	execute_process(
-		COMMAND ${GCOV_EXECUTABLE} -p -o ${GCDA_DIR} ${GCDA}
+		COMMAND "${GCOV_EXECUTABLE} -p -o ${GCDA_DIR} ${GCDA} >/dev/null"
 		WORKING_DIRECTORY ${GCDA_DIR}
 	)
 endforeach()
@@ -383,7 +384,7 @@ foreach(NOT_COVERED_SRC ${COVERAGE_SRCS_REMAINING})
 	set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
 
 	# Generate the final JSON for this file.
-	message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
+	# message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
 	string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
 	set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
 endforeach()

From 19ab464b8b89d0373c6e7729756a27cf8ca94148 Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Fri, 3 Mar 2017 13:33:57 +0800
Subject: [PATCH 081/153] Disable test_ProtoServer on Travis CI

---
 paddle/pserver/test/CMakeLists.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/paddle/pserver/test/CMakeLists.txt b/paddle/pserver/test/CMakeLists.txt
index 64654f67d0c2c..6e8f9c37f64b7 100644
--- a/paddle/pserver/test/CMakeLists.txt
+++ b/paddle/pserver/test/CMakeLists.txt
@@ -10,9 +10,11 @@ add_test(NAME socket_test
 add_unittest_without_exec(test_ProtoServer
     test_ProtoServer.cpp)
 
-add_test(NAME test_ProtoServer
-    COMMAND ${PROJ_ROOT}/paddle/.set_port.sh -p port
-        ${CMAKE_CURRENT_BINARY_DIR}/test_ProtoServer)
+IF(NOT ON_TRAVIS)
+    add_test(NAME test_ProtoServer
+        COMMAND ${PROJ_ROOT}/paddle/.set_port.sh -p port
+            ${CMAKE_CURRENT_BINARY_DIR}/test_ProtoServer)
+ENDIF(NOT ON_TRAVIS)
 
 # TODO(yuyang18): Run test_ProtoServer when with rdma
 # add_test(NAME test_ProtoServerRDMA

From a6f25f3d2a27e2ef434bd399fd9e0c8c1971638d Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Sat, 25 Feb 2017 04:09:20 +0800
Subject: [PATCH 082/153] add sentiment data package

---
 paddle/setup.py.in              |  2 +
 paddle/v2/data_set/config.py    |  8 ++++
 paddle/v2/data_set/sentiment.py | 81 +++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+)
 create mode 100644 paddle/v2/data_set/config.py
 create mode 100644 paddle/v2/data_set/sentiment.py

diff --git a/paddle/setup.py.in b/paddle/setup.py.in
index 38621af065913..8dc3ff6acd5bf 100644
--- a/paddle/setup.py.in
+++ b/paddle/setup.py.in
@@ -72,6 +72,8 @@ setup(name="py_paddle",
   packages=['py_paddle'],
   include_dirs = include_dirs,
   install_requires = [
+    'h5py',
+    'nltk',
     'numpy>=1.8.0',      # The numpy is required.
     'protobuf>=3.0.0'    # The paddle protobuf version
   ],
diff --git a/paddle/v2/data_set/config.py b/paddle/v2/data_set/config.py
new file mode 100644
index 0000000000000..69e96d65ef1ef
--- /dev/null
+++ b/paddle/v2/data_set/config.py
@@ -0,0 +1,8 @@
+import os
+
+__all__ = ['DATA_HOME']
+
+DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set')
+
+if not os.path.exists(DATA_HOME):
+    os.makedirs(DATA_HOME)
diff --git a/paddle/v2/data_set/sentiment.py b/paddle/v2/data_set/sentiment.py
new file mode 100644
index 0000000000000..323fc214dd317
--- /dev/null
+++ b/paddle/v2/data_set/sentiment.py
@@ -0,0 +1,81 @@
+import random
+import nltk
+import numpy as np
+from nltk.corpus import movie_reviews
+from config import DATA_HOME
+
+__all__ = ['train', 'test', 'get_label_dict', 'get_word_dict']
+SPLIT_NUM = 800
+TOTAL_DATASET_NUM = 1000
+
+
+def get_label_dict():
+    label_dict = {'neg': 0, 'pos': 1}
+    return label_dict
+
+
+def is_download_data():
+    try:
+        nltk.data.path.append(DATA_HOME)
+        movie_reviews.categories()
+    except LookupError:
+        print "dd"
+        nltk.download('movie_reviews', download_dir=DATA_HOME)
+        nltk.data.path.append(DATA_HOME)
+
+
+def get_word_dict():
+    words_freq_sorted = list()
+    is_download_data()
+    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
+    words_sort_list = words_freq.items()
+    words_sort_list.sort(cmp=lambda a, b: b[1] - a[1])
+    print words_sort_list
+    for index, word in enumerate(words_sort_list):
+        words_freq_sorted.append(word[0])
+    return words_freq_sorted
+
+
+def load_sentiment_data():
+    label_dict = get_label_dict()
+    is_download_data()
+    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
+    data_set = [([words_freq[word]
+                for word in movie_reviews.words(fileid)], label_dict[category])
+                for category in movie_reviews.categories()
+                for fileid in movie_reviews.fileids(category)]
+    random.shuffle(data_set)
+    return data_set
+
+
+data_set = load_sentiment_data()
+
+
+def reader_creator(data_type):
+    if data_type == 'train':
+        for each in data_set[0:SPLIT_NUM]:
+            train_sentences = np.array(each[0], dtype=np.int32)
+            train_label = np.array(each[1], dtype=np.int8)
+            yield train_sentences, train_label
+    else:
+        for each in data_set[SPLIT_NUM:]:
+            test_sentences = np.array(each[0], dtype=np.int32)
+            test_label = np.array(each[1], dtype=np.int8)
+            yield test_sentences, test_label
+
+
+def train():
+    return reader_creator('train')
+
+
+def test():
+    return reader_creator('test')
+
+
+if __name__ == '__main__':
+    for train in train():
+        print "train"
+        print train
+    for test in test():
+        print "test"
+        print test

From 55d19fc4f029105661ddd30aa838e1100d03ee54 Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Sun, 26 Feb 2017 21:41:42 +0800
Subject: [PATCH 083/153] fix bugs

---
 paddle/setup.py.in                        |   1 -
 paddle/v2/data_set/sentiment.py           |  81 --------------
 paddle/v2/{data_set => dataset}/config.py |   2 +-
 paddle/v2/dataset/sentiment.py            | 127 ++++++++++++++++++++++
 4 files changed, 128 insertions(+), 83 deletions(-)
 delete mode 100644 paddle/v2/data_set/sentiment.py
 rename paddle/v2/{data_set => dataset}/config.py (62%)
 create mode 100644 paddle/v2/dataset/sentiment.py

diff --git a/paddle/setup.py.in b/paddle/setup.py.in
index 8dc3ff6acd5bf..d44f1145dfd2b 100644
--- a/paddle/setup.py.in
+++ b/paddle/setup.py.in
@@ -72,7 +72,6 @@ setup(name="py_paddle",
   packages=['py_paddle'],
   include_dirs = include_dirs,
   install_requires = [
-    'h5py',
     'nltk',
     'numpy>=1.8.0',      # The numpy is required.
     'protobuf>=3.0.0'    # The paddle protobuf version
diff --git a/paddle/v2/data_set/sentiment.py b/paddle/v2/data_set/sentiment.py
deleted file mode 100644
index 323fc214dd317..0000000000000
--- a/paddle/v2/data_set/sentiment.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import random
-import nltk
-import numpy as np
-from nltk.corpus import movie_reviews
-from config import DATA_HOME
-
-__all__ = ['train', 'test', 'get_label_dict', 'get_word_dict']
-SPLIT_NUM = 800
-TOTAL_DATASET_NUM = 1000
-
-
-def get_label_dict():
-    label_dict = {'neg': 0, 'pos': 1}
-    return label_dict
-
-
-def is_download_data():
-    try:
-        nltk.data.path.append(DATA_HOME)
-        movie_reviews.categories()
-    except LookupError:
-        print "dd"
-        nltk.download('movie_reviews', download_dir=DATA_HOME)
-        nltk.data.path.append(DATA_HOME)
-
-
-def get_word_dict():
-    words_freq_sorted = list()
-    is_download_data()
-    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
-    words_sort_list = words_freq.items()
-    words_sort_list.sort(cmp=lambda a, b: b[1] - a[1])
-    print words_sort_list
-    for index, word in enumerate(words_sort_list):
-        words_freq_sorted.append(word[0])
-    return words_freq_sorted
-
-
-def load_sentiment_data():
-    label_dict = get_label_dict()
-    is_download_data()
-    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
-    data_set = [([words_freq[word]
-                for word in movie_reviews.words(fileid)], label_dict[category])
-                for category in movie_reviews.categories()
-                for fileid in movie_reviews.fileids(category)]
-    random.shuffle(data_set)
-    return data_set
-
-
-data_set = load_sentiment_data()
-
-
-def reader_creator(data_type):
-    if data_type == 'train':
-        for each in data_set[0:SPLIT_NUM]:
-            train_sentences = np.array(each[0], dtype=np.int32)
-            train_label = np.array(each[1], dtype=np.int8)
-            yield train_sentences, train_label
-    else:
-        for each in data_set[SPLIT_NUM:]:
-            test_sentences = np.array(each[0], dtype=np.int32)
-            test_label = np.array(each[1], dtype=np.int8)
-            yield test_sentences, test_label
-
-
-def train():
-    return reader_creator('train')
-
-
-def test():
-    return reader_creator('test')
-
-
-if __name__ == '__main__':
-    for train in train():
-        print "train"
-        print train
-    for test in test():
-        print "test"
-        print test
diff --git a/paddle/v2/data_set/config.py b/paddle/v2/dataset/config.py
similarity index 62%
rename from paddle/v2/data_set/config.py
rename to paddle/v2/dataset/config.py
index 69e96d65ef1ef..304c4bc5cd464 100644
--- a/paddle/v2/data_set/config.py
+++ b/paddle/v2/dataset/config.py
@@ -2,7 +2,7 @@
 
 __all__ = ['DATA_HOME']
 
-DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set')
+DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset')
 
 if not os.path.exists(DATA_HOME):
     os.makedirs(DATA_HOME)
diff --git a/paddle/v2/dataset/sentiment.py b/paddle/v2/dataset/sentiment.py
new file mode 100644
index 0000000000000..83581eadf225c
--- /dev/null
+++ b/paddle/v2/dataset/sentiment.py
@@ -0,0 +1,127 @@
+# /usr/bin/env python
+# -*- coding:utf-8 -*-
+
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+The script fetch and preprocess movie_reviews data set
+
+that provided by NLTK
+"""
+
+
+import nltk
+import numpy as np
+from nltk.corpus import movie_reviews
+from config import DATA_HOME
+
+__all__ = ['train', 'test', 'get_label_dict', 'get_word_dict']
+NUM_TRAINING_INSTANCES = 1600
+NUM_TOTAL_INSTANCES = 2000
+
+
+def get_label_dict():
+    """
+    Define the labels dict for dataset
+    """
+    label_dict = {'neg': 0, 'pos': 1}
+    return label_dict
+
+
+def download_data_if_not_yet():
+    """
+    Download the data set, if the data set is not download.
+    """
+    try:
+        # make sure that nltk can find the data
+        nltk.data.path.append(DATA_HOME)
+        movie_reviews.categories()
+    except LookupError:
+        print "Downloading movie_reviews data set, please wait....."
+        nltk.download('movie_reviews', download_dir=DATA_HOME)
+        print "Download data set success......"
+        # make sure that nltk can find the data
+        nltk.data.path.append(DATA_HOME)
+
+
+def get_word_dict():
+    """
+    Sorted the words by the frequency of words which occur in sample
+    :return:
+        words_freq_sorted
+    """
+    words_freq_sorted = list()
+    download_data_if_not_yet()
+    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
+    words_sort_list = words_freq.items()
+    words_sort_list.sort(cmp=lambda a, b: b[1] - a[1])
+    for index, word in enumerate(words_sort_list):
+        words_freq_sorted.append(word[0])
+    return words_freq_sorted
+
+
+def load_sentiment_data():
+    """
+    Load the data set
+    :return:
+        data_set
+    """
+    label_dict = get_label_dict()
+    download_data_if_not_yet()
+    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
+    data_set = [([words_freq[word.lower()]
+                  for word in movie_reviews.words(fileid)],
+                 label_dict[category])
+                for category in movie_reviews.categories()
+                for fileid in movie_reviews.fileids(category)]
+    return data_set
+
+
+data_set = load_sentiment_data()
+
+
+def reader_creator(data):
+    """
+    Reader creator, it format data set to numpy
+    :param data:
+        train data set or test data set
+    """
+    for each in data:
+        sentences = np.array(each[0], dtype=np.int32)
+        labels = np.array(each[1], dtype=np.int8)
+        yield sentences, labels
+
+
+def train():
+    """
+    Default train set reader creator
+    """
+    return reader_creator(data_set[0:NUM_TRAINING_INSTANCES])
+
+
+def test():
+    """
+    Default test set reader creator
+    """
+    return reader_creator(data_set[NUM_TRAINING_INSTANCES:])
+
+
+def unittest():
+    assert len(data_set) == NUM_TOTAL_INSTANCES
+    assert len(list(train())) == NUM_TRAINING_INSTANCES
+    assert len(list(test())) == NUM_TOTAL_INSTANCES - NUM_TRAINING_INSTANCES
+
+
+if __name__ == '__main__':
+    unittest()

From 812e21f3c4c14b8cf215fb1221b74814b132f301 Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Mon, 27 Feb 2017 17:43:28 +0800
Subject: [PATCH 084/153] add cross reading sample files and fix bugs

---
 paddle/setup.py.in                            |  2 +-
 paddle/v2/dataset/config.py                   |  8 ----
 .../paddle}/v2/dataset/sentiment.py           | 42 +++++++++++++------
 3 files changed, 30 insertions(+), 22 deletions(-)
 delete mode 100644 paddle/v2/dataset/config.py
 rename {paddle => python/paddle}/v2/dataset/sentiment.py (73%)

diff --git a/paddle/setup.py.in b/paddle/setup.py.in
index d44f1145dfd2b..382d5be6ecfc2 100644
--- a/paddle/setup.py.in
+++ b/paddle/setup.py.in
@@ -72,7 +72,7 @@ setup(name="py_paddle",
   packages=['py_paddle'],
   include_dirs = include_dirs,
   install_requires = [
-    'nltk',
+    'nltk>=3.2.2',
     'numpy>=1.8.0',      # The numpy is required.
     'protobuf>=3.0.0'    # The paddle protobuf version
   ],
diff --git a/paddle/v2/dataset/config.py b/paddle/v2/dataset/config.py
deleted file mode 100644
index 304c4bc5cd464..0000000000000
--- a/paddle/v2/dataset/config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import os
-
-__all__ = ['DATA_HOME']
-
-DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset')
-
-if not os.path.exists(DATA_HOME):
-    os.makedirs(DATA_HOME)
diff --git a/paddle/v2/dataset/sentiment.py b/python/paddle/v2/dataset/sentiment.py
similarity index 73%
rename from paddle/v2/dataset/sentiment.py
rename to python/paddle/v2/dataset/sentiment.py
index 83581eadf225c..9825d2ef96ade 100644
--- a/paddle/v2/dataset/sentiment.py
+++ b/python/paddle/v2/dataset/sentiment.py
@@ -20,9 +20,9 @@
 that provided by NLTK
 """
 
-
 import nltk
 import numpy as np
+from itertools import chain
 from nltk.corpus import movie_reviews
 from config import DATA_HOME
 
@@ -50,9 +50,10 @@ def download_data_if_not_yet():
     except LookupError:
         print "Downloading movie_reviews data set, please wait....."
         nltk.download('movie_reviews', download_dir=DATA_HOME)
-        print "Download data set success......"
         # make sure that nltk can find the data
         nltk.data.path.append(DATA_HOME)
+        print "Download data set success....."
+        print "Path is " + nltk.data.find('corpora/movie_reviews').path
 
 
 def get_word_dict():
@@ -67,24 +68,39 @@ def get_word_dict():
     words_sort_list = words_freq.items()
     words_sort_list.sort(cmp=lambda a, b: b[1] - a[1])
     for index, word in enumerate(words_sort_list):
-        words_freq_sorted.append(word[0])
+        words_freq_sorted.append((word[0], index + 1))
     return words_freq_sorted
 
 
+def sort_files():
+    """
+    Sorted the sample for cross reading the sample
+    :return:
+        files_list
+    """
+    files_list = list()
+    download_data_if_not_yet()
+    neg_file_list = movie_reviews.fileids('neg')
+    pos_file_list = movie_reviews.fileids('pos')
+    files_list = list(chain.from_iterable(zip(neg_file_list, pos_file_list)))
+    return files_list
+
+
 def load_sentiment_data():
     """
     Load the data set
     :return:
         data_set
     """
-    label_dict = get_label_dict()
+    data_set = list()
     download_data_if_not_yet()
-    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
-    data_set = [([words_freq[word.lower()]
-                  for word in movie_reviews.words(fileid)],
-                 label_dict[category])
-                for category in movie_reviews.categories()
-                for fileid in movie_reviews.fileids(category)]
+    words_ids = dict(get_word_dict())
+    for sample_file in sort_files():
+        words_list = list()
+        category = 0 if 'neg' in sample_file else 1
+        for word in movie_reviews.words(sample_file):
+            words_list.append(words_ids[word.lower()])
+        data_set.append((words_list, category))
     return data_set
 
 
@@ -98,9 +114,9 @@ def reader_creator(data):
         train data set or test data set
     """
     for each in data:
-        sentences = np.array(each[0], dtype=np.int32)
-        labels = np.array(each[1], dtype=np.int8)
-        yield sentences, labels
+        list_of_int = np.array(each[0], dtype=np.int32)
+        label = each[1]
+        yield list_of_int, label
 
 
 def train():

From 6115fcc5a73497157718eadb3bd596311ea83a55 Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Thu, 2 Mar 2017 04:11:11 +0000
Subject: [PATCH 085/153] format by yapf

---
 python/paddle/v2/dataset/sentiment.py         | 51 ++++++------------
 .../paddle/v2/dataset/tests/test_sentiment.py | 52 +++++++++++++++++++
 2 files changed, 69 insertions(+), 34 deletions(-)
 create mode 100644 python/paddle/v2/dataset/tests/test_sentiment.py

diff --git a/python/paddle/v2/dataset/sentiment.py b/python/paddle/v2/dataset/sentiment.py
index 9825d2ef96ade..1e7f222f4d299 100644
--- a/python/paddle/v2/dataset/sentiment.py
+++ b/python/paddle/v2/dataset/sentiment.py
@@ -20,38 +20,30 @@
 that provided by NLTK
 """
 
+import paddle.v2.dataset.common as common
+import collections
 import nltk
 import numpy as np
 from itertools import chain
 from nltk.corpus import movie_reviews
-from config import DATA_HOME
 
-__all__ = ['train', 'test', 'get_label_dict', 'get_word_dict']
+__all__ = ['train', 'test', 'get_word_dict']
 NUM_TRAINING_INSTANCES = 1600
 NUM_TOTAL_INSTANCES = 2000
 
 
-def get_label_dict():
-    """
-    Define the labels dict for dataset
-    """
-    label_dict = {'neg': 0, 'pos': 1}
-    return label_dict
-
-
 def download_data_if_not_yet():
     """
     Download the data set, if the data set is not download.
     """
     try:
         # make sure that nltk can find the data
-        nltk.data.path.append(DATA_HOME)
+        if common.DATA_HOME not in nltk.data.path:
+            nltk.data.path.append(common.DATA_HOME)
         movie_reviews.categories()
     except LookupError:
         print "Downloading movie_reviews data set, please wait....."
-        nltk.download('movie_reviews', download_dir=DATA_HOME)
-        # make sure that nltk can find the data
-        nltk.data.path.append(DATA_HOME)
+        nltk.download('movie_reviews', download_dir=common.DATA_HOME)
         print "Download data set success....."
         print "Path is " + nltk.data.find('corpora/movie_reviews').path
 
@@ -63,12 +55,17 @@ def get_word_dict():
         words_freq_sorted
     """
     words_freq_sorted = list()
+    word_freq_dict = collections.defaultdict(int)
     download_data_if_not_yet()
-    words_freq = nltk.FreqDist(w.lower() for w in movie_reviews.words())
-    words_sort_list = words_freq.items()
+
+    for category in movie_reviews.categories():
+        for field in movie_reviews.fileids(category):
+            for words in movie_reviews.words(field):
+                word_freq_dict[words] += 1
+    words_sort_list = word_freq_dict.items()
     words_sort_list.sort(cmp=lambda a, b: b[1] - a[1])
     for index, word in enumerate(words_sort_list):
-        words_freq_sorted.append((word[0], index + 1))
+        words_freq_sorted.append((word[0], index))
     return words_freq_sorted
 
 
@@ -79,7 +76,6 @@ def sort_files():
         files_list
     """
     files_list = list()
-    download_data_if_not_yet()
     neg_file_list = movie_reviews.fileids('neg')
     pos_file_list = movie_reviews.fileids('pos')
     files_list = list(chain.from_iterable(zip(neg_file_list, pos_file_list)))
@@ -104,9 +100,6 @@ def load_sentiment_data():
     return data_set
 
 
-data_set = load_sentiment_data()
-
-
 def reader_creator(data):
     """
     Reader creator, it format data set to numpy
@@ -114,15 +107,14 @@ def reader_creator(data):
         train data set or test data set
     """
     for each in data:
-        list_of_int = np.array(each[0], dtype=np.int32)
-        label = each[1]
-        yield list_of_int, label
+        yield each[0], each[1]
 
 
 def train():
     """
     Default train set reader creator
     """
+    data_set = load_sentiment_data()
     return reader_creator(data_set[0:NUM_TRAINING_INSTANCES])
 
 
@@ -130,14 +122,5 @@ def test():
     """
     Default test set reader creator
     """
+    data_set = load_sentiment_data()
     return reader_creator(data_set[NUM_TRAINING_INSTANCES:])
-
-
-def unittest():
-    assert len(data_set) == NUM_TOTAL_INSTANCES
-    assert len(list(train())) == NUM_TRAINING_INSTANCES
-    assert len(list(test())) == NUM_TOTAL_INSTANCES - NUM_TRAINING_INSTANCES
-
-
-if __name__ == '__main__':
-    unittest()
diff --git a/python/paddle/v2/dataset/tests/test_sentiment.py b/python/paddle/v2/dataset/tests/test_sentiment.py
new file mode 100644
index 0000000000000..48a14aad2a9fd
--- /dev/null
+++ b/python/paddle/v2/dataset/tests/test_sentiment.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import nltk
+import paddle.v2.dataset.sentiment as st
+from nltk.corpus import movie_reviews
+
+
+class TestSentimentMethods(unittest.TestCase):
+    def test_get_word_dict(self):
+        word_dict = st.get_word_dict()[0:10]
+        test_word_list = [(u',', 0), (u'the', 1), (u'.', 2), (u'a', 3),
+                          (u'and', 4), (u'of', 5), (u'to', 6), (u"'", 7),
+                          (u'is', 8), (u'in', 9)]
+        for idx, each in enumerate(word_dict):
+            self.assertEqual(each, test_word_list[idx])
+        self.assertTrue("/root/.cache/paddle/dataset" in nltk.data.path)
+
+    def test_sort_files(self):
+        last_label = ''
+        for sample_file in st.sort_files():
+            current_label = sample_file.split("/")[0]
+            self.assertNotEqual(current_label, last_label)
+            last_label = current_label
+
+    def test_data_set(self):
+        data_set = st.load_sentiment_data()
+        last_label = -1
+        for each in st.test():
+            self.assertNotEqual(each[1], last_label)
+            last_label = each[1]
+        self.assertEqual(len(data_set), st.NUM_TOTAL_INSTANCES)
+        self.assertEqual(len(list(st.train())), st.NUM_TRAINING_INSTANCES)
+        self.assertEqual(
+            len(list(st.test())),
+            (st.NUM_TOTAL_INSTANCES - st.NUM_TRAINING_INSTANCES))
+
+
+if __name__ == '__main__':
+    unittest.main()

From a846ef664002a91c949f383d273e0539768198e6 Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Thu, 2 Mar 2017 08:13:13 +0000
Subject: [PATCH 086/153] modify doc

---
 python/paddle/v2/dataset/sentiment.py            | 2 +-
 python/paddle/v2/dataset/tests/test_sentiment.py | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/sentiment.py b/python/paddle/v2/dataset/sentiment.py
index 1e7f222f4d299..137aa6aea768f 100644
--- a/python/paddle/v2/dataset/sentiment.py
+++ b/python/paddle/v2/dataset/sentiment.py
@@ -102,7 +102,7 @@ def load_sentiment_data():
 
 def reader_creator(data):
     """
-    Reader creator, it format data set to numpy
+    Reader creator, generate an iterator for data set
     :param data:
         train data set or test data set
     """
diff --git a/python/paddle/v2/dataset/tests/test_sentiment.py b/python/paddle/v2/dataset/tests/test_sentiment.py
index 48a14aad2a9fd..4074052907346 100644
--- a/python/paddle/v2/dataset/tests/test_sentiment.py
+++ b/python/paddle/v2/dataset/tests/test_sentiment.py
@@ -1,3 +1,6 @@
+# /usr/bin/env python
+# -*- coding:utf-8 -*-
+
 # Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
 #
 # Licensed under the Apache License, Version 2.0 (the "License");

From 3feebce2095ebe7002e86081de0a76d573319129 Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Fri, 3 Mar 2017 05:45:59 +0000
Subject: [PATCH 087/153] add sentiment in __init__.py

---
 python/paddle/v2/dataset/__init__.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index a1b21bab3bac8..e823f5631613d 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -18,5 +18,8 @@
 import cifar
 import movielens
 import conll05
+import sentiment
 
-__all__ = ['mnist', 'imikolov', 'imdb', 'cifar', 'movielens', 'conll05']
+__all__ = [
+    'mnist', 'imikolov', 'imdb', 'cifar', 'movielens', 'conll05', 'sentiment'
+]

From 615e41240c0083de10d938f28834d0933ea27bdc Mon Sep 17 00:00:00 2001
From: liaogang 
Date: Fri, 3 Mar 2017 14:55:16 +0800
Subject: [PATCH 088/153] remove comment messages

---
 cmake/coverallsGcovJsons.cmake | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/cmake/coverallsGcovJsons.cmake b/cmake/coverallsGcovJsons.cmake
index 7dfe0c8bf9b12..ad9a10cb86161 100644
--- a/cmake/coverallsGcovJsons.cmake
+++ b/cmake/coverallsGcovJsons.cmake
@@ -117,8 +117,6 @@ message("===============================")
 # (The directories the .gcda files and .o files are found in)
 # and run gcov on those.
 foreach(GCDA ${GCDA_FILES})
-	# message("Process: ${GCDA}")
-	# message("------------------------------------------------------------------------------")
 	get_filename_component(GCDA_DIR ${GCDA} PATH)
 
 	#
@@ -384,7 +382,6 @@ foreach(NOT_COVERED_SRC ${COVERAGE_SRCS_REMAINING})
 	set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
 
 	# Generate the final JSON for this file.
-	# message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
 	string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
 	set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
 endforeach()

From c9f379ed805d7459fd5333706c0496dee662112d Mon Sep 17 00:00:00 2001
From: wen-bo-yang 
Date: Fri, 3 Mar 2017 07:05:37 +0000
Subject: [PATCH 089/153] modify code

---
 python/paddle/v2/dataset/sentiment.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/sentiment.py b/python/paddle/v2/dataset/sentiment.py
index 137aa6aea768f..cbd08fa73684b 100644
--- a/python/paddle/v2/dataset/sentiment.py
+++ b/python/paddle/v2/dataset/sentiment.py
@@ -20,7 +20,7 @@
 that provided by NLTK
 """
 
-import paddle.v2.dataset.common as common
+import common
 import collections
 import nltk
 import numpy as np

From 5b24583f63ff25f9f652bd1a1d9e9bc3f930f263 Mon Sep 17 00:00:00 2001
From: Luo Tao 
Date: Fri, 3 Mar 2017 15:12:42 +0800
Subject: [PATCH 090/153] fix merge conflict

---
 python/paddle/v2/event.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py
index 8cbf9b9b1faac..a429e36b63c9e 100644
--- a/python/paddle/v2/event.py
+++ b/python/paddle/v2/event.py
@@ -53,9 +53,8 @@ class EndPass(WithMetric):
     Event On One Pass Training Complete.
     """
 
-    def __init__(self, pass_id, cost, evaluator):
+    def __init__(self, pass_id, evaluator):
         self.pass_id = pass_id
-        self.cost = cost
         WithMetric.__init__(self, evaluator)
 
 

From e60d94b3d89233d8272a98a67cd980f6b837c40b Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Fri, 3 Mar 2017 15:13:45 +0800
Subject: [PATCH 091/153] correct data_type

---
 demo/seqToseq/api_train_v2.py    | 12 ++++++------
 demo/seqToseq/seqToseq_net_v2.py |  6 +++---
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py
index efbab8d7b9534..bdcf3a5af074d 100644
--- a/demo/seqToseq/api_train_v2.py
+++ b/demo/seqToseq/api_train_v2.py
@@ -4,7 +4,8 @@
 
 from seqToseq_net_v2 import seqToseq_net_v2
 
-### Data Definiation
+# Data Definiation.
+# TODO:This code should be merged to dataset package.
 data_dir = "./data/pre-wmt14"
 src_lang_dict = os.path.join(data_dir, 'src.dict')
 trg_lang_dict = os.path.join(data_dir, 'trg.dict')
@@ -68,15 +69,14 @@ def reader():
 def main():
     paddle.init(use_gpu=False, trainer_count=1)
 
-    # reader = train_reader("data/pre-wmt14/train/train")
     # define network topology
     cost = seqToseq_net_v2(source_dict_dim, target_dict_dim)
     parameters = paddle.parameters.create(cost)
-    optimizer = paddle.optimizer.Adam(batch_size=50, learning_rate=5e-4)
+    optimizer = paddle.optimizer.Adam(learning_rate=1e-4)
 
     def event_handler(event):
         if isinstance(event, paddle.event.EndIteration):
-            if event.batch_id % 100 == 0:
+            if event.batch_id % 10 == 0:
                 print "Pass %d, Batch %d, Cost %f, %s" % (
                     event.pass_id, event.batch_id, event.cost, event.metrics)
 
@@ -93,12 +93,12 @@ def event_handler(event):
     trn_reader = paddle.reader.batched(
         paddle.reader.shuffle(
             train_reader("data/pre-wmt14/train/train"), buf_size=8192),
-        batch_size=10)
+        batch_size=10000)
 
     trainer.train(
         reader=trn_reader,
         event_handler=event_handler,
-        num_passes=10000,
+        num_passes=10,
         reader_dict=reader_dict)
 
 
diff --git a/demo/seqToseq/seqToseq_net_v2.py b/demo/seqToseq/seqToseq_net_v2.py
index 7e057e24405f8..1ac95686b4352 100644
--- a/demo/seqToseq/seqToseq_net_v2.py
+++ b/demo/seqToseq/seqToseq_net_v2.py
@@ -14,7 +14,7 @@ def seqToseq_net_v2(source_dict_dim, target_dict_dim):
     #### Encoder
     src_word_id = layer.data(
         name='source_language_word',
-        type=data_type.dense_vector(source_dict_dim))
+        type=data_type.integer_value_sequence(source_dict_dim))
     src_embedding = layer.embedding(
         input=src_word_id,
         size=word_vector_dim,
@@ -67,7 +67,7 @@ def gru_decoder_with_attention(enc_vec, enc_proj, current_word):
     trg_embedding = layer.embedding(
         input=layer.data(
             name='target_language_word',
-            type=data_type.dense_vector(target_dict_dim)),
+            type=data_type.integer_value_sequence(target_dict_dim)),
         size=word_vector_dim,
         param_attr=attr.ParamAttr(name='_target_language_embedding'))
     group_inputs.append(trg_embedding)
@@ -84,7 +84,7 @@ def gru_decoder_with_attention(enc_vec, enc_proj, current_word):
 
     lbl = layer.data(
         name='target_language_next_word',
-        type=data_type.dense_vector(target_dict_dim))
+        type=data_type.integer_value_sequence(target_dict_dim))
     cost = layer.classification_cost(input=decoder, label=lbl)
 
     return cost

From 61619580355d37c1ef817c98995dfce8a6556fc0 Mon Sep 17 00:00:00 2001
From: wenboyang 
Date: Fri, 3 Mar 2017 15:56:43 +0800
Subject: [PATCH 092/153] update __init__.py

I use pre-commit check all file and report is the passed.
But it is not passed in Travis, so I update __init__.py
---
 python/paddle/v2/dataset/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py
index fba76b202e7e6..82f11a7c41149 100644
--- a/python/paddle/v2/dataset/__init__.py
+++ b/python/paddle/v2/dataset/__init__.py
@@ -24,4 +24,4 @@
 __all__ = [
     'mnist', 'imikolov', 'imdb', 'cifar', 'movielens', 'conll05', 'sentiment'
     'uci_housing'
-]
\ No newline at end of file
+]

From a6364f9e6a84f3d29876c5ad286acc1e86f7fe1f Mon Sep 17 00:00:00 2001
From: qiaolongfei 
Date: Fri, 3 Mar 2017 16:27:29 +0800
Subject: [PATCH 093/153] change batch_size to 5

---
 demo/seqToseq/api_train_v2.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py
index bdcf3a5af074d..74ae1cf9ec81b 100644
--- a/demo/seqToseq/api_train_v2.py
+++ b/demo/seqToseq/api_train_v2.py
@@ -93,12 +93,12 @@ def event_handler(event):
     trn_reader = paddle.reader.batched(
         paddle.reader.shuffle(
             train_reader("data/pre-wmt14/train/train"), buf_size=8192),
-        batch_size=10000)
+        batch_size=5)
 
     trainer.train(
         reader=trn_reader,
         event_handler=event_handler,
-        num_passes=10,
+        num_passes=10000,
         reader_dict=reader_dict)
 
 

From 1d2025c99cd7b21f3c6657244b7cdce8b8465380 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Fri, 3 Mar 2017 18:00:26 +0800
Subject: [PATCH 094/153] Use the sequence_conv_pool define inside the
 networks.py

---
 demo/sentiment/train_v2.py      | 195 ++++++++++----------------------
 python/paddle/v2/config_base.py |   2 +
 2 files changed, 59 insertions(+), 138 deletions(-)

diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py
index 0fa74948533b4..3a266e74ea930 100644
--- a/demo/sentiment/train_v2.py
+++ b/demo/sentiment/train_v2.py
@@ -1,126 +1,40 @@
+# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import sys
-from os.path import join as join_path
 import paddle.trainer_config_helpers.attrs as attrs
 from paddle.trainer_config_helpers.poolings import MaxPooling
-import paddle.v2.layer as layer
-import paddle.v2.activation as activation
-import paddle.v2.data_type as data_type
-import paddle.v2.dataset.imdb as imdb
 import paddle.v2 as paddle
 
 
-def sequence_conv_pool(input,
-                       input_size,
-                       context_len,
-                       hidden_size,
-                       name=None,
-                       context_start=None,
-                       pool_type=None,
-                       context_proj_layer_name=None,
-                       context_proj_param_attr=False,
-                       fc_layer_name=None,
-                       fc_param_attr=None,
-                       fc_bias_attr=None,
-                       fc_act=None,
-                       pool_bias_attr=None,
-                       fc_attr=None,
-                       context_attr=None,
-                       pool_attr=None):
-    """
-    Text convolution pooling layers helper.
-
-    Text input => Context Projection => FC Layer => Pooling => Output.
-
-    :param name: name of output layer(pooling layer name)
-    :type name: basestring
-    :param input: name of input layer
-    :type input: LayerOutput
-    :param context_len: context projection length. See
-                        context_projection's document.
-    :type context_len: int
-    :param hidden_size: FC Layer size.
-    :type hidden_size: int
-    :param context_start: context projection length. See
-                          context_projection's context_start.
-    :type context_start: int or None
-    :param pool_type: pooling layer type. See pooling_layer's document.
-    :type pool_type: BasePoolingType.
-    :param context_proj_layer_name: context projection layer name.
-                                    None if user don't care.
-    :type context_proj_layer_name: basestring
-    :param context_proj_param_attr: context projection parameter attribute.
-                                    None if user don't care.
-    :type context_proj_param_attr: ParameterAttribute or None.
-    :param fc_layer_name: fc layer name. None if user don't care.
-    :type fc_layer_name: basestring
-    :param fc_param_attr: fc layer parameter attribute. None if user don't care.
-    :type fc_param_attr: ParameterAttribute or None
-    :param fc_bias_attr: fc bias parameter attribute. False if no bias,
-                         None if user don't care.
-    :type fc_bias_attr: ParameterAttribute or None
-    :param fc_act: fc layer activation type. None means tanh
-    :type fc_act: BaseActivation
-    :param pool_bias_attr: pooling layer bias attr. None if don't care.
-                           False if no bias.
-    :type pool_bias_attr: ParameterAttribute or None.
-    :param fc_attr: fc layer extra attribute.
-    :type fc_attr: ExtraLayerAttribute
-    :param context_attr: context projection layer extra attribute.
-    :type context_attr: ExtraLayerAttribute
-    :param pool_attr: pooling layer extra attribute.
-    :type pool_attr: ExtraLayerAttribute
-    :return: output layer name.
-    :rtype: LayerOutput
-    """
-    # Set Default Value to param
-    context_proj_layer_name = "%s_conv_proj" % name \
-        if context_proj_layer_name is None else context_proj_layer_name
-
-    with layer.mixed(
-            name=context_proj_layer_name,
-            size=input_size * context_len,
-            act=activation.Linear(),
-            layer_attr=context_attr) as m:
-        m += layer.context_projection(
-            input=input,
-            context_len=context_len,
-            context_start=context_start,
-            padding_attr=context_proj_param_attr)
-
-    fc_layer_name = "%s_conv_fc" % name \
-        if fc_layer_name is None else fc_layer_name
-    fl = layer.fc(name=fc_layer_name,
-                  input=m,
-                  size=hidden_size,
-                  act=fc_act,
-                  layer_attr=fc_attr,
-                  param_attr=fc_param_attr,
-                  bias_attr=fc_bias_attr)
-
-    return layer.pooling(
-        name=name,
-        input=fl,
-        pooling_type=pool_type,
-        bias_attr=pool_bias_attr,
-        layer_attr=pool_attr)
-
-
 def convolution_net(input_dim,
                     class_dim=2,
                     emb_dim=128,
                     hid_dim=128,
                     is_predict=False):
-    data = layer.data("word", data_type.integer_value_sequence(input_dim))
-    emb = layer.embedding(input=data, size=emb_dim)
-    conv_3 = sequence_conv_pool(
-        input=emb, input_size=emb_dim, context_len=3, hidden_size=hid_dim)
-    conv_4 = sequence_conv_pool(
-        input=emb, input_size=emb_dim, context_len=4, hidden_size=hid_dim)
-    output = layer.fc(input=[conv_3, conv_4],
-                      size=class_dim,
-                      act=activation.Softmax())
-    lbl = layer.data("label", data_type.integer_value(2))
-    cost = layer.classification_cost(input=output, label=lbl)
+    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
 
 
@@ -152,24 +66,28 @@ def stacked_lstm_net(input_dim,
     lstm_para_attr = attrs.ParameterAttribute(initial_std=0., learning_rate=1.)
     para_attr = [fc_para_attr, lstm_para_attr]
     bias_attr = attrs.ParameterAttribute(initial_std=0., l2_rate=0.)
-    relu = activation.Relu()
-    linear = activation.Linear()
-
-    data = layer.data("word", data_type.integer_value_sequence(input_dim))
-    emb = layer.embedding(input=data, size=emb_dim)
-
-    fc1 = layer.fc(input=emb, size=hid_dim, act=linear, bias_attr=bias_attr)
-    lstm1 = layer.lstmemory(
+    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(
         input=fc1, act=relu, bias_attr=bias_attr, layer_attr=layer_attr)
 
     inputs = [fc1, lstm1]
     for i in range(2, stacked_num + 1):
-        fc = layer.fc(input=inputs,
-                      size=hid_dim,
-                      act=linear,
-                      param_attr=para_attr,
-                      bias_attr=bias_attr)
-        lstm = layer.lstmemory(
+        fc = paddle.layer.fc(input=inputs,
+                             size=hid_dim,
+                             act=linear,
+                             param_attr=para_attr,
+                             bias_attr=bias_attr)
+        lstm = paddle.layer.lstmemory(
             input=fc,
             reverse=(i % 2) == 0,
             act=relu,
@@ -177,16 +95,16 @@ def stacked_lstm_net(input_dim,
             layer_attr=layer_attr)
         inputs = [fc, lstm]
 
-    fc_last = layer.pooling(input=inputs[0], pooling_type=MaxPooling())
-    lstm_last = layer.pooling(input=inputs[1], pooling_type=MaxPooling())
-    output = layer.fc(input=[fc_last, lstm_last],
-                      size=class_dim,
-                      act=activation.Softmax(),
-                      bias_attr=bias_attr,
-                      param_attr=para_attr)
+    fc_last = paddle.layer.pooling(input=inputs[0], pooling_type=MaxPooling())
+    lstm_last = paddle.layer.pooling(input=inputs[1], pooling_type=MaxPooling())
+    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 = layer.data("label", data_type.integer_value(2))
-    cost = layer.classification_cost(input=output, label=lbl)
+    lbl = paddle.layer.data("label", paddle.data_type.integer_value(2))
+    cost = paddle.layer.classification_cost(input=output, label=lbl)
     return cost
 
 
@@ -196,7 +114,7 @@ def stacked_lstm_net(input_dim,
 
     # network config
     print 'load dictionary...'
-    word_dict = imdb.word_dict()
+    word_dict = paddle.dataset.imdb.word_dict()
     dict_dim = len(word_dict)
     class_dim = 2
 
@@ -226,7 +144,8 @@ def event_handler(event):
         if isinstance(event, paddle.event.EndPass):
             result = trainer.test(
                 reader=paddle.reader.batched(
-                    lambda: imdb.test(word_dict), batch_size=128),
+                    lambda: paddle.dataset.imdb.test(word_dict),
+                    batch_size=128),
                 reader_dict={'word': 0,
                              'label': 1})
             print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)
@@ -239,7 +158,7 @@ def event_handler(event):
     trainer.train(
         reader=paddle.reader.batched(
             paddle.reader.shuffle(
-                lambda: imdb.train(word_dict), buf_size=1000),
+                lambda: paddle.dataset.imdb.train(word_dict), buf_size=1000),
             batch_size=100),
         event_handler=event_handler,
         reader_dict={'word': 0,
diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py
index fa2ccec6c3270..0fc711e99a18a 100644
--- a/python/paddle/v2/config_base.py
+++ b/python/paddle/v2/config_base.py
@@ -93,6 +93,8 @@ def __init__(self, **kwargs):
 
             name = kwargs.get('name', None)
             super(V2LayerImpl, self).__init__(name, parent_layers)
+            if kwargs.has_key('size'):
+                self.size = kwargs['size']
             self.__other_kwargs__ = other_kwargs
 
         if wrapper is not None:

From 84ce706750ba4e75e55fe75cb13467c5545ad945 Mon Sep 17 00:00:00 2001
From: hedaoyuan 
Date: Fri, 3 Mar 2017 18:14:11 +0800
Subject: [PATCH 095/153] Restore config_base.py

---
 python/paddle/v2/config_base.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py
index 0fc711e99a18a..fa2ccec6c3270 100644
--- a/python/paddle/v2/config_base.py
+++ b/python/paddle/v2/config_base.py
@@ -93,8 +93,6 @@ def __init__(self, **kwargs):
 
             name = kwargs.get('name', None)
             super(V2LayerImpl, self).__init__(name, parent_layers)
-            if kwargs.has_key('size'):
-                self.size = kwargs['size']
             self.__other_kwargs__ = other_kwargs
 
         if wrapper is not None:

From 6b0961a3c17f3f9a32a7faf063731e05732f23a1 Mon Sep 17 00:00:00 2001
From: Yu Yang 
Date: Fri, 3 Mar 2017 14:41:45 +0800
Subject: [PATCH 096/153] auto deployment paddle documentation

* Change build process to generate v2 documentation
* Add directory for v2 api
* Correct sphinx index soft-link
---
 cmake/FindSphinx.cmake                        |  2 +-
 doc/api/index_cn.rst                          | 39 +----------
 doc/api/index_en.rst                          | 29 +-------
 .../data_provider/dataprovider_cn.rst         |  0
 .../data_provider/dataprovider_en.rst         |  0
 .../data_provider/pydataprovider2_cn.rst      |  0
 .../data_provider/pydataprovider2_en.rst      |  0
 .../data_provider/src/mnist_config.py         |  0
 .../data_provider/src/mnist_provider.dict.py  |  0
 .../data_provider/src/mnist_train.txt         |  0
 .../data_provider/src/sentimental_config.py   |  0
 .../data_provider/src/sentimental_provider.py |  0
 .../data_provider/src/sentimental_train.txt   |  0
 doc/api/{ => v1}/data_provider/src/train.list |  0
 doc/api/v1/index_cn.rst                       | 37 ++++++++++
 doc/api/v1/index_en.rst                       | 37 ++++++++++
 .../{ => v1}/predict/src/predict_sample.py    |  0
 .../{ => v1}/predict/swig_py_paddle_cn.rst    |  0
 .../{ => v1}/predict/swig_py_paddle_en.rst    |  0
 .../trainer_config_helpers/activations.rst    |  0
 .../{ => v1}/trainer_config_helpers/attrs.rst |  0
 .../trainer_config_helpers/data_sources.rst   |  0
 .../trainer_config_helpers/evaluators.rst     |  0
 .../trainer_config_helpers/layers.rst         |  0
 .../trainer_config_helpers/networks.rst       |  0
 .../trainer_config_helpers/optimizers.rst     |  0
 .../trainer_config_helpers/poolings.rst       |  0
 doc/api/v2/model_configs.rst                  |  6 ++
 doc/templates/conf.py.cn.in                   |  8 ++-
 doc/templates/conf.py.en.in                   | 10 ++-
 doc/tutorials/quick_start/index_en.md         |  8 +--
 paddle/scripts/travis/docs.sh                 | 46 +++++++++----
 python/paddle/v2/layer.py                     | 69 +++++--------------
 33 files changed, 152 insertions(+), 139 deletions(-)
 rename doc/api/{ => v1}/data_provider/dataprovider_cn.rst (100%)
 rename doc/api/{ => v1}/data_provider/dataprovider_en.rst (100%)
 rename doc/api/{ => v1}/data_provider/pydataprovider2_cn.rst (100%)
 rename doc/api/{ => v1}/data_provider/pydataprovider2_en.rst (100%)
 rename doc/api/{ => v1}/data_provider/src/mnist_config.py (100%)
 rename doc/api/{ => v1}/data_provider/src/mnist_provider.dict.py (100%)
 rename doc/api/{ => v1}/data_provider/src/mnist_train.txt (100%)
 rename doc/api/{ => v1}/data_provider/src/sentimental_config.py (100%)
 rename doc/api/{ => v1}/data_provider/src/sentimental_provider.py (100%)
 rename doc/api/{ => v1}/data_provider/src/sentimental_train.txt (100%)
 rename doc/api/{ => v1}/data_provider/src/train.list (100%)
 create mode 100644 doc/api/v1/index_cn.rst
 create mode 100644 doc/api/v1/index_en.rst
 rename doc/api/{ => v1}/predict/src/predict_sample.py (100%)
 rename doc/api/{ => v1}/predict/swig_py_paddle_cn.rst (100%)
 rename doc/api/{ => v1}/predict/swig_py_paddle_en.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/activations.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/attrs.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/data_sources.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/evaluators.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/layers.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/networks.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/optimizers.rst (100%)
 rename doc/api/{ => v1}/trainer_config_helpers/poolings.rst (100%)
 create mode 100644 doc/api/v2/model_configs.rst

diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake
index d319442ef10b3..1c29cb22a31f1 100644
--- a/cmake/FindSphinx.cmake
+++ b/cmake/FindSphinx.cmake
@@ -72,7 +72,7 @@ function( Sphinx_add_target target_name builder conf cache source destination )
     ${source}
     ${destination}
     COMMENT "Generating sphinx documentation: ${builder}"
-    COMMAND ln -sf ${destination}/index_*.html ${destination}/index.html
+    COMMAND cd ${destination} && ln -s ./index_*.html index.html
     )
 
   set_property(
diff --git a/doc/api/index_cn.rst b/doc/api/index_cn.rst
index 3718cd73a2003..874dd9cb2278c 100644
--- a/doc/api/index_cn.rst
+++ b/doc/api/index_cn.rst
@@ -1,37 +1,2 @@
-API中文手册
-============
-
-DataProvider API
-----------------
-
-..  toctree::
-    :maxdepth: 1
-
-    data_provider/dataprovider_cn.rst
-    data_provider/pydataprovider2_cn.rst
-
-..  _api_trainer_config:
-
-Model Config API
-----------------
-
-..  toctree::
-    :maxdepth: 1
-
-    trainer_config_helpers/optimizers.rst
-    trainer_config_helpers/data_sources.rst
-    trainer_config_helpers/layers.rst
-    trainer_config_helpers/activations.rst 
-    trainer_config_helpers/poolings.rst
-    trainer_config_helpers/networks.rst
-    trainer_config_helpers/evaluators.rst
-    trainer_config_helpers/attrs.rst
-
-
-Applications API
-----------------
-
-..  toctree::
-    :maxdepth: 1
-
-    predict/swig_py_paddle_cn.rst
+API
+===
\ No newline at end of file
diff --git a/doc/api/index_en.rst b/doc/api/index_en.rst
index 10c297a71d698..b7f470e1f8a9a 100644
--- a/doc/api/index_en.rst
+++ b/doc/api/index_en.rst
@@ -1,37 +1,10 @@
 API
 ===
 
-DataProvider API
-----------------
-
-..  toctree::
-    :maxdepth: 1
-
-    data_provider/dataprovider_en.rst
-    data_provider/pydataprovider2_en.rst
-
-..  _api_trainer_config:
-
 Model Config API
 ----------------
 
 ..  toctree::
     :maxdepth: 1
 
-    trainer_config_helpers/optimizers.rst
-    trainer_config_helpers/data_sources.rst
-    trainer_config_helpers/layers.rst
-    trainer_config_helpers/activations.rst 
-    trainer_config_helpers/poolings.rst
-    trainer_config_helpers/networks.rst
-    trainer_config_helpers/evaluators.rst
-    trainer_config_helpers/attrs.rst
-
-
-Applications API
-----------------
-
-..  toctree::
-    :maxdepth: 1
-
-    predict/swig_py_paddle_en.rst
+    v2/model_configs.rst
\ No newline at end of file
diff --git a/doc/api/data_provider/dataprovider_cn.rst b/doc/api/v1/data_provider/dataprovider_cn.rst
similarity index 100%
rename from doc/api/data_provider/dataprovider_cn.rst
rename to doc/api/v1/data_provider/dataprovider_cn.rst
diff --git a/doc/api/data_provider/dataprovider_en.rst b/doc/api/v1/data_provider/dataprovider_en.rst
similarity index 100%
rename from doc/api/data_provider/dataprovider_en.rst
rename to doc/api/v1/data_provider/dataprovider_en.rst
diff --git a/doc/api/data_provider/pydataprovider2_cn.rst b/doc/api/v1/data_provider/pydataprovider2_cn.rst
similarity index 100%
rename from doc/api/data_provider/pydataprovider2_cn.rst
rename to doc/api/v1/data_provider/pydataprovider2_cn.rst
diff --git a/doc/api/data_provider/pydataprovider2_en.rst b/doc/api/v1/data_provider/pydataprovider2_en.rst
similarity index 100%
rename from doc/api/data_provider/pydataprovider2_en.rst
rename to doc/api/v1/data_provider/pydataprovider2_en.rst
diff --git a/doc/api/data_provider/src/mnist_config.py b/doc/api/v1/data_provider/src/mnist_config.py
similarity index 100%
rename from doc/api/data_provider/src/mnist_config.py
rename to doc/api/v1/data_provider/src/mnist_config.py
diff --git a/doc/api/data_provider/src/mnist_provider.dict.py b/doc/api/v1/data_provider/src/mnist_provider.dict.py
similarity index 100%
rename from doc/api/data_provider/src/mnist_provider.dict.py
rename to doc/api/v1/data_provider/src/mnist_provider.dict.py
diff --git a/doc/api/data_provider/src/mnist_train.txt b/doc/api/v1/data_provider/src/mnist_train.txt
similarity index 100%
rename from doc/api/data_provider/src/mnist_train.txt
rename to doc/api/v1/data_provider/src/mnist_train.txt
diff --git a/doc/api/data_provider/src/sentimental_config.py b/doc/api/v1/data_provider/src/sentimental_config.py
similarity index 100%
rename from doc/api/data_provider/src/sentimental_config.py
rename to doc/api/v1/data_provider/src/sentimental_config.py
diff --git a/doc/api/data_provider/src/sentimental_provider.py b/doc/api/v1/data_provider/src/sentimental_provider.py
similarity index 100%
rename from doc/api/data_provider/src/sentimental_provider.py
rename to doc/api/v1/data_provider/src/sentimental_provider.py
diff --git a/doc/api/data_provider/src/sentimental_train.txt b/doc/api/v1/data_provider/src/sentimental_train.txt
similarity index 100%
rename from doc/api/data_provider/src/sentimental_train.txt
rename to doc/api/v1/data_provider/src/sentimental_train.txt
diff --git a/doc/api/data_provider/src/train.list b/doc/api/v1/data_provider/src/train.list
similarity index 100%
rename from doc/api/data_provider/src/train.list
rename to doc/api/v1/data_provider/src/train.list
diff --git a/doc/api/v1/index_cn.rst b/doc/api/v1/index_cn.rst
new file mode 100644
index 0000000000000..3718cd73a2003
--- /dev/null
+++ b/doc/api/v1/index_cn.rst
@@ -0,0 +1,37 @@
+API中文手册
+============
+
+DataProvider API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    data_provider/dataprovider_cn.rst
+    data_provider/pydataprovider2_cn.rst
+
+..  _api_trainer_config:
+
+Model Config API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    trainer_config_helpers/optimizers.rst
+    trainer_config_helpers/data_sources.rst
+    trainer_config_helpers/layers.rst
+    trainer_config_helpers/activations.rst 
+    trainer_config_helpers/poolings.rst
+    trainer_config_helpers/networks.rst
+    trainer_config_helpers/evaluators.rst
+    trainer_config_helpers/attrs.rst
+
+
+Applications API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    predict/swig_py_paddle_cn.rst
diff --git a/doc/api/v1/index_en.rst b/doc/api/v1/index_en.rst
new file mode 100644
index 0000000000000..10c297a71d698
--- /dev/null
+++ b/doc/api/v1/index_en.rst
@@ -0,0 +1,37 @@
+API
+===
+
+DataProvider API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    data_provider/dataprovider_en.rst
+    data_provider/pydataprovider2_en.rst
+
+..  _api_trainer_config:
+
+Model Config API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    trainer_config_helpers/optimizers.rst
+    trainer_config_helpers/data_sources.rst
+    trainer_config_helpers/layers.rst
+    trainer_config_helpers/activations.rst 
+    trainer_config_helpers/poolings.rst
+    trainer_config_helpers/networks.rst
+    trainer_config_helpers/evaluators.rst
+    trainer_config_helpers/attrs.rst
+
+
+Applications API
+----------------
+
+..  toctree::
+    :maxdepth: 1
+
+    predict/swig_py_paddle_en.rst
diff --git a/doc/api/predict/src/predict_sample.py b/doc/api/v1/predict/src/predict_sample.py
similarity index 100%
rename from doc/api/predict/src/predict_sample.py
rename to doc/api/v1/predict/src/predict_sample.py
diff --git a/doc/api/predict/swig_py_paddle_cn.rst b/doc/api/v1/predict/swig_py_paddle_cn.rst
similarity index 100%
rename from doc/api/predict/swig_py_paddle_cn.rst
rename to doc/api/v1/predict/swig_py_paddle_cn.rst
diff --git a/doc/api/predict/swig_py_paddle_en.rst b/doc/api/v1/predict/swig_py_paddle_en.rst
similarity index 100%
rename from doc/api/predict/swig_py_paddle_en.rst
rename to doc/api/v1/predict/swig_py_paddle_en.rst
diff --git a/doc/api/trainer_config_helpers/activations.rst b/doc/api/v1/trainer_config_helpers/activations.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/activations.rst
rename to doc/api/v1/trainer_config_helpers/activations.rst
diff --git a/doc/api/trainer_config_helpers/attrs.rst b/doc/api/v1/trainer_config_helpers/attrs.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/attrs.rst
rename to doc/api/v1/trainer_config_helpers/attrs.rst
diff --git a/doc/api/trainer_config_helpers/data_sources.rst b/doc/api/v1/trainer_config_helpers/data_sources.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/data_sources.rst
rename to doc/api/v1/trainer_config_helpers/data_sources.rst
diff --git a/doc/api/trainer_config_helpers/evaluators.rst b/doc/api/v1/trainer_config_helpers/evaluators.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/evaluators.rst
rename to doc/api/v1/trainer_config_helpers/evaluators.rst
diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/v1/trainer_config_helpers/layers.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/layers.rst
rename to doc/api/v1/trainer_config_helpers/layers.rst
diff --git a/doc/api/trainer_config_helpers/networks.rst b/doc/api/v1/trainer_config_helpers/networks.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/networks.rst
rename to doc/api/v1/trainer_config_helpers/networks.rst
diff --git a/doc/api/trainer_config_helpers/optimizers.rst b/doc/api/v1/trainer_config_helpers/optimizers.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/optimizers.rst
rename to doc/api/v1/trainer_config_helpers/optimizers.rst
diff --git a/doc/api/trainer_config_helpers/poolings.rst b/doc/api/v1/trainer_config_helpers/poolings.rst
similarity index 100%
rename from doc/api/trainer_config_helpers/poolings.rst
rename to doc/api/v1/trainer_config_helpers/poolings.rst
diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst
new file mode 100644
index 0000000000000..a9f33b33ef61b
--- /dev/null
+++ b/doc/api/v2/model_configs.rst
@@ -0,0 +1,6 @@
+======
+Layers
+======
+
+..  automodule:: paddle.v2.layer
+    :members:
diff --git a/doc/templates/conf.py.cn.in b/doc/templates/conf.py.cn.in
index 418d718fbd9c6..6dc48704bc230 100644
--- a/doc/templates/conf.py.cn.in
+++ b/doc/templates/conf.py.cn.in
@@ -15,13 +15,19 @@ import sys
 import os, subprocess
 import shlex
 from recommonmark import parser, transform
+try:
+   import py_paddle
+   import paddle
+   import paddle.v2
+except ImportError:
+   print("Must install paddle python package before generating documentation")
+   sys.exit(1)
 
 MarkdownParser = parser.CommonMarkParser
 AutoStructify = transform.AutoStructify
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, '@PROJ_ROOT@/python')
 templates_path = ["@PROJ_ROOT@/doc_theme/templates"]
 
 # -- General configuration ------------------------------------------------
diff --git a/doc/templates/conf.py.en.in b/doc/templates/conf.py.en.in
index e96c25cb75bee..b477f0120c4fa 100644
--- a/doc/templates/conf.py.en.in
+++ b/doc/templates/conf.py.en.in
@@ -15,14 +15,20 @@ import sys
 import os, subprocess
 import shlex
 from recommonmark import parser, transform
+try:
+   import py_paddle
+   import paddle
+   import paddle.v2
+except ImportError:
+   print("Must install paddle python package before generating documentation")
+   sys.exit(1)
+
 
 MarkdownParser = parser.CommonMarkParser
 AutoStructify = transform.AutoStructify
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, '@PROJ_ROOT@/python')
-
 templates_path = ["@PROJ_ROOT@/doc_theme/templates"]
 
 # -- General configuration ------------------------------------------------
diff --git a/doc/tutorials/quick_start/index_en.md b/doc/tutorials/quick_start/index_en.md
index 70dec2eb2a8c3..ca110431cf921 100644
--- a/doc/tutorials/quick_start/index_en.md
+++ b/doc/tutorials/quick_start/index_en.md
@@ -156,14 +156,14 @@ define_py_data_sources2(train_list='data/train.list',
                         obj="process",
                         args={"dictionary": word_dict})
 ```
-You can refer to the following link for more detailed examples and data formats: PyDataProvider2.
+You can refer to the following link for more detailed examples and data formats: PyDataProvider2.
 
 ## Network Architecture
 We will describe four kinds of network architectures in this section.
 
![](./src/PipelineNetwork_en.jpg)
First, you will build a logistic regression model. Later, you will also get chance to build other more powerful network architectures. -For more detailed documentation, you could refer to: layer documentation. All configuration files are in `demo/quick_start` directory. +For more detailed documentation, you could refer to: layer documentation. All configuration files are in `demo/quick_start` directory. ### Logistic Regression The architecture is illustrated in the following picture: @@ -366,7 +366,7 @@ You can use single layer LSTM model with Dropout for our text classification pro
## Optimization Algorithm -Optimization algorithms include Momentum, RMSProp, AdaDelta, AdaGrad, Adam, and Adamax. You can use Adam optimization method here, with L2 regularization and gradient clipping, because Adam has been proved to work very well for training recurrent neural network. +Optimization algorithms include Momentum, RMSProp, AdaDelta, AdaGrad, Adam, and Adamax. You can use Adam optimization method here, with L2 regularization and gradient clipping, because Adam has been proved to work very well for training recurrent neural network. ```python settings(batch_size=128, @@ -407,7 +407,7 @@ paddle train \ --init_model_path=./output/pass-0000x ``` -We will give an example of performing prediction using Recurrent model on a dataset with no labels. You can refer to Python Prediction API tutorial,or other demo for the prediction process using Python. You can also use the following script for inference or evaluation. +We will give an example of performing prediction using Recurrent model on a dataset with no labels. You can refer to Python Prediction API tutorial,or other demo for the prediction process using Python. You can also use the following script for inference or evaluation. inference script (predict.sh): diff --git a/paddle/scripts/travis/docs.sh b/paddle/scripts/travis/docs.sh index 6b43cad20b76e..53e998ef6c1b9 100755 --- a/paddle/scripts/travis/docs.sh +++ b/paddle/scripts/travis/docs.sh @@ -2,8 +2,12 @@ # Add set -e, cd to directory. source ./common.sh - # Compile Documentation only. +cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DWITH_GPU=OFF -DWITH_DOC=OFF -DWITH_STYLE_CHECK=OFF ${EXTRA_CMAKE_OPTS} +mkdir output +make DESTDIR=./output install -j `nproc` +pip install ./output/usr/local/opt/paddle/share/wheels/* +rm -rf * cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran-4.8 -DWITH_GPU=OFF -DWITH_DOC=ON ${EXTRA_CMAKE_OPTS} make paddle_docs paddle_docs_cn @@ -25,26 +29,41 @@ TARGET_BRANCH="gh-pages" # Only deploy master branch to build latest documentation. SOURCE_BRANCH="master" -# If is not a Github pull request, and in master branch. -if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then - exit 0 -fi - # Clone the repo to output directory git clone $REPO output cd output -# checkout github page branch -git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH +function deploy_docs() { + SOURCE_BRANCH=$1 + DIR=$2 + # If is not a Github pull request + if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + exit 0 + fi + # If it is not watched branch. + if [ "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then + return + fi -# remove old docs. mv new docs. -rm -rf doc doc_cn -mv ../doc/cn/html doc_cn -mv ../doc/en/html doc + # checkout github page branch + git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH + + mkdir -p ${DIR} + # remove old docs. mv new docs. + set +e + rm -rf ${DIR}/doc ${DIR}/doc_cn + set -e + mv ../doc/cn/html ${DIR}/doc_cn + mv ../doc/en/html ${DIR}/doc + git add . +} + +deploy_docs "master" "." +deploy_docs "develop" "./develop/" # Check is there anything changed. set +e -git diff --exit-code >/dev/null +git diff --cached --exit-code >/dev/null if [ $? -eq 0 ]; then echo "No changes to the output on this push; exiting." exit 0 @@ -57,7 +76,6 @@ if [ -n $SSL_KEY ]; then # Only push updated docs for github.com/PaddlePaddle/P git config user.name "Travis CI" git config user.email "paddle-dev@baidu.com" git commit -m "Deploy to GitHub Pages: ${SHA}" - # Set ssh private key openssl aes-256-cbc -K $SSL_KEY -iv $SSL_IV -in ../../paddle/scripts/travis/deploy_key.enc -out deploy_key -d chmod 600 deploy_key diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 67111f1315fbb..0aa5391910078 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -12,58 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Before this new package paddle.v2.layer, users would need to use functions -in paddle.trainer_config_helpers.layers to configure networks. - -The Old Way: -========= -This old way requires that the creation of a network be defined in a Python -function, say network_config, and that this Python function being passed to -paddle.trainer_config_helpers.parse_network_config for the creation of -protobuf message description of this network. - -```python -def network_config(): - img = paddle.trainer_config_helpers.data_layer(name="pixel", size=784) - inference = paddle.trainer_config_helpers.fc_layer( - input=img, - size=10, - act=paddle.trainer_config_helpers.SoftmaxActivation()) - cost = paddle.trainer_config_helpers.classification_cost( - input=inference, - label=paddle.trainer_config_helpers.data_layer(name="label", size=10)) - -proto_desc = parse_network_config(network_config) -``` - -When parse_network_config executes network_config, those layer definition -functions like data_layer and fc_layer would change some Python global variables, -so that after the execution, parse_network_config could collect information from -these global variables and generates the protobuf message. - - - -The New Way: -========= -In this PR, we define a function in paddle.v2.layer which creates a Python -class for each layer creation function in paddle.trainer_config_helpers.layers. -Users can use create a network as follows: - -```python -img = paddle.v2.layer.data(name="pixel", size=784) -inference = paddle.v2.layer.fc(input=img, size=10, act=paddle.v2.layer.Softmax()) -cost = paddle.v2.layer.classification( - input=inference, - label=paddle.v2.layer.data(name="label", size=10)) - -parameters = paddle.v2.parameters.create(cost) -``` - -This new way doesn't require those invocations to layer definition functions -to be in a Python function but could be anywhere. - -Also, the creation of a protobuf message is hidden in the invocation of -paddle.v2.parameters.create, no longer exposed to users. +`paddle.v2.layer` is a part of model config packages in paddle.v2. In API v2, +we want to make Paddle a plain Python package. The model config package defined +the way how to configure a neural network topology in Paddle Python code. + +The primary usage shows below. + +.. code-block:: python + + import paddle.v2 as paddle + + img = paddle.layer.data(name='img', type=paddle.data_type.dense_vector(784)) + hidden = paddle.layer.fc(input=img, size=200) + prediction = paddle.layer.fc(input=hidden, size=10, + act=paddle.activation.Softmax()) + + # use prediction instance where needed. + parameters = paddle.v2.parameters.create(cost) """ from config_base import Layer, __convert_to_v2__ import paddle.trainer_config_helpers as conf_helps From 0f7126f2cf939de7d30550a695aa279fad6d34f5 Mon Sep 17 00:00:00 2001 From: Yancey1989 Date: Fri, 3 Mar 2017 20:11:16 +0800 Subject: [PATCH 097/153] Add prepare training data and efk paddle logs --- doc/howto/usage/k8s/k8s_distributed_cn.md | 82 ++++++++++++++------ doc/howto/usage/k8s/src/efk-paddle-logs.png | Bin 0 -> 215352 bytes 2 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 doc/howto/usage/k8s/src/efk-paddle-logs.png diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 7213a977b8a2a..8ca158e608be9 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -43,22 +43,55 @@ docker push [YOUR_REPO]/paddle:mypaddle 注意上述命令中`[YOUR_REPO]`表示读者所使用的Docker镜像仓库地址,读者需要替换成自己使用的仓库地址。下文使用`[YOUR_REPO]/paddle:mypaddle`这个地址来表示此步骤所构建出的镜像。 -### 上传训练文件 +### 准备训练数据 -本文使用PaddlePaddle官方的[recommendation demo](http://www.paddlepaddle.org/doc/demo/index.html#recommendation)作为这次训练的内容,我们将训练文件与数据放在一个job name命名的目录中,上传到volume所在的共享存储(使用不同分布式存储会有不同的挂载方式,需要要先挂载这个目录,然后拷贝数据)。完成后volume中的文件内容大致如下: +这里我们通过在Kubernetes集群上启动一个Job来下载并切割数据,也可以通过修改[k8s_train](./k8s_train)的内容来定制image. -```bash -[root@paddle-kubernetes-node0 mfs]# tree -d +在启动Job之前,需要根据不同的分布式存储来绑定一个[persistentVolumeClaim](https://kubernetes.io/docs/user-guide/persistent-volumes/),生成的数据将会存储在这个volume下. + +```yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: paddle-data +spec: + template: + metadata: + name: pi + spec: + hostNetwork: true + containers: + - name: paddle-data + image: paddledev/paddle-tutorial:k8s_data + imagePullPolicy: Always + volumeMounts: + - mountPath: "/mnt" + name: nfs + env: + - name: OUT_DIR + value: /mnt/paddle-cluster-job + - name: SPLIT_COUNT + value: "3" + volumes: + - name: nfs + persistentVolumeClaim: + claimName: mfs + restartPolicy: Never +``` + +完成后volume中的文件内容大致如下: +```base +[root@paddle-kubernetes-node0 nfsdir]$ tree -d . -└── paddle-cluster-job - ├── data - │   ├── 0 - │   │ - │   ├── 1 - │   │ - │   └── 2 - ├── output - └── recommendation +`-- paddle-cluster-job + |-- 0 + | `-- data + |-- 1 + | `-- data + |-- 2 + | `-- data + |-- output + |-- quick_start ``` 目录中paddle-cluster-job是本次训练对应的job name,本次训练要求有3个PaddlePaddle节点,在paddle-cluster-job/data目录中存放切分好的数据,文件夹0,1,2分别代表3个节点的trainer_id。recommendation文件夹内存放训练文件,output文件夹存放训练结果与日志。 @@ -118,15 +151,16 @@ spec: `env`字段表示容器的环境变量,我们将`paddle`运行的一些参数通过这种方式传递到容器内。 -`JOB_PATH`表示共享存储挂载的路径,`JOB_NAME`表示job名字,`TRAIN_CONFIG_DIR`表示本次训练文件所在目录,这三个变量组合就可以找到本次训练需要的文件路径。 - -`CONF_PADDLE_NIC`表示`paddle pserver`进程需要的`--nics`参数,即网卡名 - -`CONF_PADDLE_PORT`表示`paddle pserver`的`--port`参数,`CONF_PADDLE_PORTS_NUM`则表示稠密更新的端口数量,也就是`--ports_num`参数。 - -`CONF_PADDLE_PORTS_NUM_SPARSE`表示稀疏更新的端口数量,也就是`--ports_num_for_sparse`参数。 - -`CONF_PADDLE_GRADIENT_NUM`表示训练节点数量,即`--num_gradient_servers`参数 +环境变量 | 说明 +--- | --- +JOB_PATH | 共享存储挂在的路径 +JOB_NAME | Job的名字 +TRAIN_CONFIG_DIR | 本次训练文件所在目录,与JOB_PATH,JOB_NAME组合可以找到本次训练需要的文件路径 +CONF_PADDLE_NIC | `paddle pserver`进程需要的`--nics`参数,即网卡名 +CONF_PADDLE_PORT | `paddle paserver`的`--port`参数 +CONF_PADDLE_PORTS_NUM | 稠密更新的端口数量,即`--ports_num`参数 +CONF_PADDLE_PORTS_NUM_SPARSE | 稀疏更新的端口数量,即`--ports_num_for_sparse`参数 +CONF_PADDLE_GRADIENT_NUM | 训练节点数量,即`--num_gradient_servers参数` 这些参数的具体描述,读者可以查看[这里](http://www.paddlepaddle.org/doc/ui/cmd_argument/detail_introduction.html#parameter-server-and-distributed-communication)。 @@ -279,3 +313,7 @@ def getIdMap(podlist): args += " " + args_ext + " --trainer_id=" + \ str(trainerId) + " --save_dir=" + JOB_PATH_OUTPUT ``` + +### 使用EFK查询训练日志 +首先需要在集群中[部署EFK(Elasticsearch+Fluentd+Kibana)](https://github.com/k8sp/efk)套件,在Kibana中根据POD或者Container名字来搜索相应日志 +![EFK下的Paddle训练日志](./src/efk-paddle-logs.png) diff --git a/doc/howto/usage/k8s/src/efk-paddle-logs.png b/doc/howto/usage/k8s/src/efk-paddle-logs.png new file mode 100644 index 0000000000000000000000000000000000000000..e78ec689efb3e2077ba7850ad722878952dcdad3 GIT binary patch literal 215352 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 mB<)xv-wXjIrezx@@c#qFV-fVk&Z?gP0000 Date: Fri, 3 Mar 2017 20:21:58 +0800 Subject: [PATCH 098/153] update efk logs png --- doc/howto/usage/k8s/src/efk-paddle-logs.png | Bin 215352 -> 276278 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/howto/usage/k8s/src/efk-paddle-logs.png b/doc/howto/usage/k8s/src/efk-paddle-logs.png index e78ec689efb3e2077ba7850ad722878952dcdad3..e88d85dcecee090f2597c8f719ad2a1837de0cc2 100644 GIT binary patch literal 276278 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%0ALhxM{3*fCUTuBVPNEDY07Tv6nS@`{orauL# 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 mB<)xv-wXjIrezx@@c#qFV-fVk&Z?gP0000 Date: Fri, 3 Mar 2017 20:47:49 +0800 Subject: [PATCH 099/153] fix invalid url --- doc/howto/usage/k8s/k8s_distributed_cn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 8ca158e608be9..97595db9ddfed 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -45,7 +45,7 @@ docker push [YOUR_REPO]/paddle:mypaddle ### 准备训练数据 -这里我们通过在Kubernetes集群上启动一个Job来下载并切割数据,也可以通过修改[k8s_train](./k8s_train)的内容来定制image. +这里我们通过在Kubernetes集群上启动一个Job来下载并切割数据,也可以通过修改[k8s_train](./src/k8s_train)的内容来定制image. 在启动Job之前,需要根据不同的分布式存储来绑定一个[persistentVolumeClaim](https://kubernetes.io/docs/user-guide/persistent-volumes/),生成的数据将会存储在这个volume下. From af9e221d67924258c24d7c29b86e63174a2ebbe0 Mon Sep 17 00:00:00 2001 From: Yancey1989 Date: Fri, 3 Mar 2017 21:00:08 +0800 Subject: [PATCH 100/153] fix invalid url --- doc/howto/usage/k8s/k8s_distributed_cn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 97595db9ddfed..9a30b3ed5c2c6 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -45,7 +45,7 @@ docker push [YOUR_REPO]/paddle:mypaddle ### 准备训练数据 -这里我们通过在Kubernetes集群上启动一个Job来下载并切割数据,也可以通过修改[k8s_train](./src/k8s_train)的内容来定制image. +这里我们通过在Kubernetes集群上启动一个Job来下载并切割数据,也可以通过修改[k8s_train](./src/k8s_train/README.md)的内容来定制image. 在启动Job之前,需要根据不同的分布式存储来绑定一个[persistentVolumeClaim](https://kubernetes.io/docs/user-guide/persistent-volumes/),生成的数据将会存储在这个volume下. From d498174c9aa6439207c9789a140f8d610352be74 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Fri, 3 Mar 2017 00:18:00 +0000 Subject: [PATCH 101/153] move paddle.reader.batch to paddle.batch --- demo/image_classification/api_v2_train.py | 4 +-- demo/mnist/api_train_v2.py | 4 +-- python/paddle/v2/__init__.py | 2 ++ python/paddle/v2/batch.py | 35 +++++++++++++++++++++++ python/paddle/v2/reader/decorator.py | 24 +--------------- 5 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 python/paddle/v2/batch.py diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py index 585f61c6fa4c8..e0fc0e04bbd21 100644 --- a/demo/image_classification/api_v2_train.py +++ b/demo/image_classification/api_v2_train.py @@ -66,7 +66,7 @@ def event_handler(event): sys.stdout.flush() if isinstance(event, paddle.event.EndPass): result = trainer.test( - reader=paddle.reader.batched( + reader=paddle.batch( paddle.dataset.cifar.test10(), batch_size=128), reader_dict={'image': 0, 'label': 1}) @@ -77,7 +77,7 @@ def event_handler(event): parameters=parameters, update_equation=momentum_optimizer) trainer.train( - reader=paddle.reader.batched( + reader=paddle.batch( paddle.reader.shuffle( paddle.dataset.cifar.train10(), buf_size=50000), batch_size=128), diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 9b7ebde500704..4fb1808ca11a6 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -98,7 +98,7 @@ def event_handler(event): result.metrics['classification_error_evaluator'])) trainer.train( - reader=paddle.reader.batched( + reader=paddle.batch( paddle.reader.shuffle( paddle.dataset.mnist.train(), buf_size=8192), batch_size=128), @@ -115,7 +115,7 @@ def event_handler(event): probs = paddle.infer( output=predict, parameters=parameters, - reader=paddle.reader.batched( + reader=paddle.batch( paddle.reader.firstn( paddle.reader.map_readers(lambda item: (item[0], ), paddle.dataset.mnist.test()), diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 8ab8cd2f85d5d..a023e3ea06e2f 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -28,6 +28,7 @@ import inferencer import networks import py_paddle.swig_paddle as api +import batch __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', @@ -45,3 +46,4 @@ def init(**kwargs): infer = inferencer.infer +batch = batch.batch diff --git a/python/paddle/v2/batch.py b/python/paddle/v2/batch.py new file mode 100644 index 0000000000000..f01815a0ce068 --- /dev/null +++ b/python/paddle/v2/batch.py @@ -0,0 +1,35 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def batch(reader, batch_size): + """ + Create a batch reader. + :param reader: the data reader to read from. + :param batch_size: batch_size + :return: the batch reader. + """ + + def batch_reader(): + r = reader() + batch = [] + for instance in r: + batch.append(instance) + if len(batch) == batch_size: + yield batch + batch = [] + if batch: + yield batch + + return batch_reader diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index b7657e27764f0..c4ba110205a3c 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -14,7 +14,7 @@ __all__ = [ 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', - 'ComposeNotAligned', 'batched', 'firstn' + 'ComposeNotAligned', 'firstn' ] import itertools @@ -193,28 +193,6 @@ def data_reader(): return data_reader -def batched(reader, batch_size): - """ - Create a batched reader. - :param reader: the data reader to read from. - :param batch_size: batch_size - :return: the batched reader. - """ - - def batched_reader(): - r = reader() - batch = [] - for instance in r: - batch.append(instance) - if len(batch) == batch_size: - yield batch - batch = [] - if batch: - yield batch - - return batched_reader - - def firstn(reader, n): """ Limit the max number of samples that reader could return. From 24e1c536dab60164eaecadabcf64fbebcde20cf6 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Fri, 3 Mar 2017 01:06:58 +0000 Subject: [PATCH 102/153] fix according to comment --- python/paddle/v2/__init__.py | 4 ++-- python/paddle/v2/{batch.py => minibatch.py} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename python/paddle/v2/{batch.py => minibatch.py} (100%) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index a023e3ea06e2f..05227ca334594 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -28,7 +28,7 @@ import inferencer import networks import py_paddle.swig_paddle as api -import batch +import minibatch __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', @@ -46,4 +46,4 @@ def init(**kwargs): infer = inferencer.infer -batch = batch.batch +batch = minibatch.batch diff --git a/python/paddle/v2/batch.py b/python/paddle/v2/minibatch.py similarity index 100% rename from python/paddle/v2/batch.py rename to python/paddle/v2/minibatch.py From 3219c831a140303e7e03de70e38ae7ebda2f2c26 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 2 Mar 2017 22:27:46 +0000 Subject: [PATCH 103/153] Rename Argument::sumCost to Argument::cost since Argument should not know about cost. cost is Argument, but argument does not have to be cost. --- paddle/api/Arguments.cpp | 4 +--- paddle/api/PaddleAPI.h | 2 +- paddle/api/test/testArguments.py | 2 +- paddle/gserver/tests/LayerGradUtil.cpp | 6 +++--- paddle/parameter/Argument.h | 2 +- paddle/trainer/Tester.cpp | 2 +- paddle/trainer/Trainer.cpp | 8 ++++---- paddle/trainer/TrainerInternal.cpp | 2 +- 8 files changed, 13 insertions(+), 15 deletions(-) diff --git a/paddle/api/Arguments.cpp b/paddle/api/Arguments.cpp index a3f4bfffc9f07..d49b189e253f7 100644 --- a/paddle/api/Arguments.cpp +++ b/paddle/api/Arguments.cpp @@ -144,9 +144,7 @@ void Arguments::setSlotSequenceDim(size_t idx, IVector* vec) throw(RangeError) { a.cpuSequenceDims = m->cast(vec->getSharedPtr()); } -float Arguments::sumCosts() const { - return paddle::Argument::sumCosts(m->outputs); -} +float Arguments::sum() const { return paddle::Argument::sum(m->outputs); } int64_t Arguments::getBatchSize(size_t idx) const throw(RangeError) { auto& a = m->getArg(idx); diff --git a/paddle/api/PaddleAPI.h b/paddle/api/PaddleAPI.h index 762f86ac79461..c4f5dca26cc6a 100644 --- a/paddle/api/PaddleAPI.h +++ b/paddle/api/PaddleAPI.h @@ -453,7 +453,7 @@ class Arguments { IVector* vec) throw(RangeError); void setSlotSequenceDim(size_t idx, IVector* vec) throw(RangeError); - float sumCosts() const; + float sum() const; private: static Arguments* createByPaddleArgumentVector(void* ptr); diff --git a/paddle/api/test/testArguments.py b/paddle/api/test/testArguments.py index a04a805d7a64e..9fe44de94ea6d 100644 --- a/paddle/api/test/testArguments.py +++ b/paddle/api/test/testArguments.py @@ -22,7 +22,7 @@ def test_load_arguments(self): args = swig_paddle.Arguments.createArguments(1) args.setSlotValue(0, m) - self.assertAlmostEqual(27.0, args.sumCosts()) + self.assertAlmostEqual(27.0, args.sum()) mat = args.getSlotValue(0) assert isinstance(mat, swig_paddle.Matrix) diff --git a/paddle/gserver/tests/LayerGradUtil.cpp b/paddle/gserver/tests/LayerGradUtil.cpp index ae016e74eaa84..7617af10ba719 100644 --- a/paddle/gserver/tests/LayerGradUtil.cpp +++ b/paddle/gserver/tests/LayerGradUtil.cpp @@ -24,7 +24,7 @@ real getCostSum(LayerPtr& testLayer, MatrixPtr weights) { if (weights) { outArgs[0].value->dotMul(*outArgs[0].value, *weights); } - return Argument::sumCosts(outArgs); + return Argument::sum(outArgs); } real getDiffAndPrint(real newCost1, @@ -241,7 +241,7 @@ void testBatchState(LayerPtr testLayer, std::vector args; args.push_back(out); - EXPECT_EQ(0, Argument::sumCosts(args)) << "testBatchState failed"; + EXPECT_EQ(0, Argument::sum(args)) << "testBatchState failed"; for (size_t seqId = 0; seqId < numSequences; ++seqId) { start[seqId] += seqLens[seqId]; } @@ -672,7 +672,7 @@ void testLayerGradKernel(TestConfig testConf, outArgs[0].value->dotMul(*testLayer->getOutput().value, *weights); } - real cost = Argument::sumCosts(outArgs); + real cost = Argument::sum(outArgs); LOG(INFO) << " cost " << cost; EXPECT_FALSE(std::isnan(cost)); diff --git a/paddle/parameter/Argument.h b/paddle/parameter/Argument.h index 178c068b93ac5..9ef44be0cb3b9 100644 --- a/paddle/parameter/Argument.h +++ b/paddle/parameter/Argument.h @@ -163,7 +163,7 @@ struct Argument { : sequenceStartPositions->getData(false); } - static inline real sumCosts(const std::vector& arguments) { + static inline real sum(const std::vector& arguments) { real cost = 0; for (auto& arg : arguments) { if (arg.value) { diff --git a/paddle/trainer/Tester.cpp b/paddle/trainer/Tester.cpp index 13aa28ae5d969..80664fa877b32 100644 --- a/paddle/trainer/Tester.cpp +++ b/paddle/trainer/Tester.cpp @@ -208,7 +208,7 @@ real Tester::forwardOneBatch(const DataBatch& dataBatch, return 0.0; // In this case, there is no meaning to calculate cost } - return Argument::sumCosts(outArgs); + return Argument::sum(outArgs); } void Tester::testOnePassBatch(int passId) { diff --git a/paddle/trainer/Trainer.cpp b/paddle/trainer/Trainer.cpp index bd84545375117..b68e29cd5ea22 100644 --- a/paddle/trainer/Trainer.cpp +++ b/paddle/trainer/Trainer.cpp @@ -310,7 +310,7 @@ real Trainer::checkGradient() { std::vector outArgs; trainerInternal_.getGradientMachine()->forward(inArgs, &outArgs, PASS_GC); - real cost = Argument::sumCosts(outArgs); + real cost = Argument::sum(outArgs); LOG(INFO) << "original cost=" << cost; trainerInternal_.getGradientMachine()->backward(); @@ -340,7 +340,7 @@ real Trainer::checkGradient() { parameter->getBuf(PARAMETER_VALUE)->copyFrom(newPara); parameter->setValueUpdated(); trainerInternal_.getGradientMachine()->forward(inArgs, &outArgs, PASS_GC); - real newCost1 = Argument::sumCosts(outArgs); + real newCost1 = Argument::sum(outArgs); for (size_t i = 0; i < dim; ++i) { newp[i] = oldp[i] - step * d[i]; @@ -349,7 +349,7 @@ real Trainer::checkGradient() { parameter->getBuf(PARAMETER_VALUE)->copyFrom(newPara); parameter->setValueUpdated(); trainerInternal_.getGradientMachine()->forward(inArgs, &outArgs, PASS_GC); - real newCost2 = Argument::sumCosts(outArgs); + real newCost2 = Argument::sum(outArgs); real trueDelta = 0.5 * (newCost1 - newCost2); real diff = (1e-20 + trueDelta) / (1e-20 + delta) - 1; @@ -575,7 +575,7 @@ real Trainer::calcGradient(const DataBatch& dataBatch, trainerInternal_.getGradientMachine()->forwardBackward( inArgs, &outArgs, PASS_TRAIN); - real cost = Argument::sumCosts(outArgs); + real cost = Argument::sum(outArgs); offset = 0; for (auto& para : parameters) { diff --git a/paddle/trainer/TrainerInternal.cpp b/paddle/trainer/TrainerInternal.cpp index f3b465b444167..4c5d4a0913aaf 100644 --- a/paddle/trainer/TrainerInternal.cpp +++ b/paddle/trainer/TrainerInternal.cpp @@ -134,7 +134,7 @@ void TrainerInternal::trainOneBatch(int64_t batchId, real cost = 0; { REGISTER_TIMER("sumCost"); - cost = Argument::sumCosts(*outArgs); + cost = Argument::sum(*outArgs); } if (batchId % intconfig_->log_period == 0) { From 61b4c7170a7f55bdd2c6db57b58e9d797fc3522f Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Thu, 2 Mar 2017 22:01:42 +0000 Subject: [PATCH 104/153] remove inferencer and Inference from __All__, since infer is sufficent, they are implementation detail. rename inferencer.py to inference.py --- python/paddle/v2/__init__.py | 6 +++--- python/paddle/v2/{inferencer.py => inference.py} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename python/paddle/v2/{inferencer.py => inference.py} (98%) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 8ab8cd2f85d5d..f663ef735d642 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -25,14 +25,14 @@ from . import reader import attr import pooling -import inferencer +import inference import networks import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader', - 'topology', 'networks', 'inferencer', 'infer' + 'topology', 'networks', 'infer' ] @@ -44,4 +44,4 @@ def init(**kwargs): api.initPaddle(*args) -infer = inferencer.infer +infer = inference.infer diff --git a/python/paddle/v2/inferencer.py b/python/paddle/v2/inference.py similarity index 98% rename from python/paddle/v2/inferencer.py rename to python/paddle/v2/inference.py index ac03b016c9b8b..476fd3fa4523a 100644 --- a/python/paddle/v2/inferencer.py +++ b/python/paddle/v2/inference.py @@ -5,7 +5,7 @@ import itertools import numpy -__all__ = ['Inference', 'infer'] +__all__ = ['infer'] class Inference(object): From d6c6a996b1d872a4ee845ee662364a7974635f73 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Sat, 4 Mar 2017 02:28:53 +0000 Subject: [PATCH 105/153] dataset reader for wmt14 example usage: import paddle.v2 as paddle if __name__ == '__main__': dict_en, dict_fr = paddle.dataset.wmt14.build_dict() train = paddle.dataset.wmt14.train(dict_en, dict_fr) test = paddle.dataset.wmt14.test(dict_en, dict_fr) total_train = 0 for i in train(): total_train += 1 total_test = 0 for i in test(): total_test += 1 print total_train, total_test --- python/paddle/v2/dataset/__init__.py | 3 +- python/paddle/v2/dataset/wmt14.py | 142 +++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/dataset/wmt14.py diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py index 82f11a7c41149..6c371d3c9bdee 100644 --- a/python/paddle/v2/dataset/__init__.py +++ b/python/paddle/v2/dataset/__init__.py @@ -20,8 +20,9 @@ import conll05 import uci_housing import sentiment +import wmt14 __all__ = [ 'mnist', 'imikolov', 'imdb', 'cifar', 'movielens', 'conll05', 'sentiment' - 'uci_housing' + 'uci_housing', 'wmt14' ] diff --git a/python/paddle/v2/dataset/wmt14.py b/python/paddle/v2/dataset/wmt14.py new file mode 100644 index 0000000000000..9904848b5d3ef --- /dev/null +++ b/python/paddle/v2/dataset/wmt14.py @@ -0,0 +1,142 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +wmt14 dataset +""" +import paddle.v2.dataset.common +import tarfile +import os.path +import itertools + +__all__ = ['train', 'test', 'build_dict'] + +URL_DEV_TEST = 'http://www-lium.univ-lemans.fr/~schwenk/cslm_joint_paper/data/dev+test.tgz' +MD5_DEV_TEST = '7d7897317ddd8ba0ae5c5fa7248d3ff5' +URL_TRAIN = 'http://localhost:8000/train.tgz' +MD5_TRAIN = '72de99da2830ea5a3a2c4eb36092bbc7' + + +def word_count(f, word_freq=None): + add = paddle.v2.dataset.common.dict_add + if word_freq == None: + word_freq = {} + + for l in f: + for w in l.strip().split(): + add(word_freq, w) + add(word_freq, '') + add(word_freq, '') + + return word_freq + + +def get_word_dix(word_freq): + TYPO_FREQ = 50 + word_freq = filter(lambda x: x[1] > TYPO_FREQ, word_freq.items()) + word_freq_sorted = sorted(word_freq, key=lambda x: (-x[1], x[0])) + words, _ = list(zip(*word_freq_sorted)) + word_idx = dict(zip(words, xrange(len(words)))) + word_idx[''] = len(words) + return word_idx + + +def get_word_freq(train, dev): + word_freq = word_count(train, word_count(dev)) + if '' in word_freq: + # remove for now, since we will set it as last index + del word_freq[''] + return word_freq + + +def build_dict(): + base_dir = './wmt14-data' + train_en_filename = base_dir + '/train/train.en' + train_fr_filename = base_dir + '/train/train.fr' + dev_en_filename = base_dir + '/dev/ntst1213.en' + dev_fr_filename = base_dir + '/dev/ntst1213.fr' + + if not os.path.exists(train_en_filename) or not os.path.exists( + train_fr_filename): + with tarfile.open( + paddle.v2.dataset.common.download(URL_TRAIN, 'wmt14', + MD5_TRAIN)) as tf: + tf.extractall(base_dir) + + if not os.path.exists(dev_en_filename) or not os.path.exists( + dev_fr_filename): + with tarfile.open( + paddle.v2.dataset.common.download(URL_DEV_TEST, 'wmt14', + MD5_DEV_TEST)) as tf: + tf.extractall(base_dir) + + f_en = open(train_en_filename) + f_fr = open(train_fr_filename) + f_en_dev = open(dev_en_filename) + f_fr_dev = open(dev_fr_filename) + + word_freq_en = get_word_freq(f_en, f_en_dev) + word_freq_fr = get_word_freq(f_fr, f_fr_dev) + + f_en.close() + f_fr.close() + f_en_dev.close() + f_fr_dev.close() + + return get_word_dix(word_freq_en), get_word_dix(word_freq_fr) + + +def reader_creator(directory, path_en, path_fr, URL, MD5, dict_en, dict_fr): + def reader(): + if not os.path.exists(path_en) or not os.path.exists(path_fr): + with tarfile.open( + paddle.v2.dataset.common.download(URL, 'wmt14', MD5)) as tf: + tf.extractall(directory) + + f_en = open(path_en) + f_fr = open(path_fr) + UNK_en = dict_en[''] + UNK_fr = dict_fr[''] + + for en, fr in itertools.izip(f_en, f_fr): + src_ids = [dict_en.get(w, UNK_en) for w in en.strip().split()] + tar_ids = [ + dict_fr.get(w, UNK_fr) + for w in [''] + fr.strip().split() + [''] + ] + + # remove sequence whose length > 80 in training mode + if len(src_ids) == 0 or len(tar_ids) <= 1 or len( + src_ids) > 80 or len(tar_ids) > 80: + continue + + yield src_ids, tar_ids[:-1], tar_ids[1:] + + f_en.close() + f_fr.close() + + return reader + + +def train(dict_en, dict_fr): + directory = './wmt14-data' + return reader_creator(directory, directory + '/train/train.en', + directory + '/train/train.fr', URL_TRAIN, MD5_TRAIN, + dict_en, dict_fr) + + +def test(dict_en, dict_fr): + directory = './wmt14-data' + return reader_creator(directory, directory + '/dev/ntst1213.en', + directory + '/dev/ntst1213.fr', URL_DEV_TEST, + MD5_DEV_TEST, dict_en, dict_fr) From c28b812edfc7b3b158665fa9d63d35dd83f4b474 Mon Sep 17 00:00:00 2001 From: Yancey1989 Date: Sat, 4 Mar 2017 10:36:41 +0800 Subject: [PATCH 106/153] cancel efk; correct hostpath --- doc/howto/usage/k8s/k8s_distributed_cn.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/howto/usage/k8s/k8s_distributed_cn.md b/doc/howto/usage/k8s/k8s_distributed_cn.md index 9a30b3ed5c2c6..2a7a6c8c17882 100644 --- a/doc/howto/usage/k8s/k8s_distributed_cn.md +++ b/doc/howto/usage/k8s/k8s_distributed_cn.md @@ -69,7 +69,7 @@ spec: name: nfs env: - name: OUT_DIR - value: /mnt/paddle-cluster-job + value: /home/work/mfs/paddle-cluster-job - name: SPLIT_COUNT value: "3" volumes: @@ -313,7 +313,3 @@ def getIdMap(podlist): args += " " + args_ext + " --trainer_id=" + \ str(trainerId) + " --save_dir=" + JOB_PATH_OUTPUT ``` - -### 使用EFK查询训练日志 -首先需要在集群中[部署EFK(Elasticsearch+Fluentd+Kibana)](https://github.com/k8sp/efk)套件,在Kibana中根据POD或者Container名字来搜索相应日志 -![EFK下的Paddle训练日志](./src/efk-paddle-logs.png) From 8ed74636040498a33a733b0f979479f2f76ae060 Mon Sep 17 00:00:00 2001 From: Yancey1989 Date: Sat, 4 Mar 2017 11:58:34 +0800 Subject: [PATCH 107/153] delete unused png --- doc/howto/usage/k8s/src/efk-paddle-logs.png | Bin 276278 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 doc/howto/usage/k8s/src/efk-paddle-logs.png diff --git a/doc/howto/usage/k8s/src/efk-paddle-logs.png b/doc/howto/usage/k8s/src/efk-paddle-logs.png deleted file mode 100644 index e88d85dcecee090f2597c8f719ad2a1837de0cc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 276278 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%0ALhxM{3*fCUTuBVPNEDY07Tv6nS@`{orauL# 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 Date: Sat, 4 Mar 2017 15:55:35 +0800 Subject: [PATCH 108/153] Complete Layers documentation --- .../paddle/trainer_config_helpers/layers.py | 7 +- python/paddle/v2/config_base.py | 41 +++++++++- python/paddle/v2/layer.py | 82 +++++++++++++------ 3 files changed, 100 insertions(+), 30 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index b68460b6a3ab6..b94f8f9a78355 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -795,17 +795,16 @@ def data_layer(name, size, height=None, width=None, layer_attr=None): .. code-block:: python - data = data_layer(name="input", - size=1000) + data = data_layer(name="input", size=1000) :param name: Name of this data layer. :type name: basestring :param size: Size of this data layer. :type size: int :param height: Height of this data layer, used for image - :type size: int|None + :type height: int|None :param width: Width of this data layer, used for image - :type size: int|None + :type width: int|None :param layer_attr: Extra Layer Attribute. :type layer_attr: ExtraLayerAttribute. :return: LayerOutput object. diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index fa2ccec6c3270..64de568fcc74c 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -13,12 +13,49 @@ # limitations under the License. import collections - +import re from paddle.trainer_config_helpers.default_decorators import wrap_name_default import paddle.trainer_config_helpers as conf_helps +class LayerType(type): + def __new__(cls, name, bases, attrs): + method_name = attrs.get('METHOD_NAME', None) + if method_name is not None: + method = getattr(conf_helps, method_name) + if method.__doc__ is not None: + mapper = attrs.get("__map_docstr__", None) + if mapper is not None: + attrs['__doc__'] = LayerType.__map_docstr__( + mapper(method.__doc__), + method_name=method_name, + name=name) + else: + attrs['__doc__'] = LayerType.__map_docstr__( + method.__doc__, method_name=method_name, name=name) + return super(LayerType, cls).__new__(cls, name, bases, attrs) + + @staticmethod + def __map_docstr__(doc, name, method_name): + assert isinstance(doc, basestring) + + # replace LayerOutput to paddle.v2.config_base.Layer + doc = doc.replace("LayerOutput", "paddle.v2.config_base.Layer") + + # xxx_layer to xxx + doc = re.sub(r"(?P[a-z]+)_layer", r"\g", doc) + + # XxxxActivation to paddle.v2.Activation.Xxxx + doc = re.sub(r"(?P[A-Z][a-zA-Z]+)Activation", + r"paddle.v2.Activation.\g", doc) + + # TODO(yuyang18): Add more rules if needed. + return doc + + class Layer(object): + __metaclass__ = LayerType + def __init__(self, name=None, parent_layers=None): assert isinstance(parent_layers, dict) self.name = name @@ -80,6 +117,8 @@ def __convert_to_v2__(method_name, parent_names, is_default_name=True): wrapper = None class V2LayerImpl(Layer): + METHOD_NAME = method_name + def __init__(self, **kwargs): parent_layers = dict() other_kwargs = dict() diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 711226d659d49..1608aa3f7147d 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -47,26 +47,32 @@ RecurrentLayerGroupEnd, model_type import activation +import re import data_type __all__ = ['parse_network', 'data'] -__projection_names__ = filter(lambda x: x.endswith('_projection'), - dir(conf_helps)) -__all__ += __projection_names__ - -__operator_names__ = filter(lambda x: x.endswith('_operator'), dir(conf_helps)) -__all__ += __operator_names__ - def parse_network(*outputs): """ - parse all output layers and then generate a model config proto. - :param outputs: - :return: + Parse all output layers and then generate a ModelConfig object. + + .. note:: + + This function is used internally in paddle.v2 module. User should never + invoke this method. + + :param outputs: Output layers. + :type outputs: Layer + :return: A ModelConfig object instance. + :rtype: ModelConfig """ def __real_func__(): + """ + __real_func__ is the function that config_parser.parse invoked. It is + the plain old paddle configuration function. + """ context = dict() real_output = [each.to_proto(context=context) for each in outputs] conf_helps.outputs(real_output) @@ -81,6 +87,8 @@ def __real_func__(): class DataLayerV2(Layer): + METHOD_NAME = 'data_layer' + def __init__(self, name, type, **kwargs): assert isinstance(type, data_type.InputType) @@ -99,6 +107,17 @@ def to_proto_impl(self, **kwargs): args[each] = self.__kwargs__[each] return getattr(conf_helps, self.__method_name__)(name=self.name, **args) + def __map_docstr__(doc): + doc = re.sub(r'(data = [^\)]+)\).*', + "data = paddle.layer.data(name=\"input\", " + "type=paddle.data_type.dense_vector(1000))", doc) + + doc = re.sub(r':param size:.*', + ':param type: Data type of this data layer', doc) + doc = re.sub(r':type size:.*', + ":type size: paddle.v2.data_type.InputType", doc) + return doc + class WithExtraParent(Layer): def extra_parent(self): @@ -347,6 +366,7 @@ def to_proto_impl(self, **kwargs): LayerV2 = Layer data = DataLayerV2 +data.__name__ = 'data' AggregateLevel = conf_helps.layers.AggregateLevel ExpandLevel = conf_helps.layers.ExpandLevel memory = MemoryV2 @@ -386,6 +406,7 @@ def __convert_layer__(_new_name_, _old_name_, _parent_names_): global __all__ __all__.append(_new_name_) globals()[new_name] = __convert_to_v2__(_old_name_, _parent_names_) + globals()[new_name].__name__ = new_name for each_layer_name in dir(conf_helps): @@ -399,21 +420,6 @@ def __convert_layer__(_new_name_, _old_name_, _parent_names_): del new_name del each_layer_name -# convert projection -for prj in __projection_names__: - globals()[prj] = __convert_to_v2__( - prj, parent_names=['input'], is_default_name=False) - -# convert operator -operator_list = [ - # [V1_method_name, parent_names], - ['dotmul_operator', ['a', 'b']], - ['conv_operator', ['img', 'filter']] -] -for op in operator_list: - globals()[op[0]] = __convert_to_v2__( - op[0], parent_names=op[1], is_default_name=False) - @wrap_name_default() def recurrent_group(step, input, name=None): @@ -464,3 +470,29 @@ def __real_step__(*args): return retv[0] else: return retv + + +__projection_names__ = filter(lambda x: x.endswith('_projection'), + dir(conf_helps)) + +__all__ += __projection_names__ + +__operator_names__ = filter(lambda x: x.endswith('_operator'), dir(conf_helps)) +__all__ += __operator_names__ + +# convert projection +for prj in __projection_names__: + globals()[prj] = __convert_to_v2__( + prj, parent_names=['input'], is_default_name=False) + globals()[prj].__name__ = prj + +# convert operator +operator_list = [ + # [V1_method_name, parent_names], + ['dotmul_operator', ['a', 'b']], + ['conv_operator', ['img', 'filter']] +] +for op in operator_list: + globals()[op[0]] = __convert_to_v2__( + op[0], parent_names=op[1], is_default_name=False) + globals()[op[0]].__name__ = op[0] From 38de3a6cab8d6a05d1a6e1c07ae415a229953de6 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 16:08:54 +0800 Subject: [PATCH 109/153] Complete docs of attr --- doc/api/v2/model_configs.rst | 8 ++++++++ python/paddle/v2/attr.py | 10 +++++++--- python/paddle/v2/config_base.py | 6 ++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst index a9f33b33ef61b..4ca28315d5564 100644 --- a/doc/api/v2/model_configs.rst +++ b/doc/api/v2/model_configs.rst @@ -4,3 +4,11 @@ Layers .. automodule:: paddle.v2.layer :members: + + +========== +Attributes +========== + +.. automodule:: paddle.v2.attr + :members: diff --git a/python/paddle/v2/attr.py b/python/paddle/v2/attr.py index 40c64f621b443..32f78614e7f8a 100644 --- a/python/paddle/v2/attr.py +++ b/python/paddle/v2/attr.py @@ -12,12 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.trainer_config_helpers.attrs import * +import paddle.trainer_config_helpers.attrs __all__ = [ "Param", "Extra", ] -Param = ParameterAttribute -Extra = ExtraLayerAttribute +Param = paddle.trainer_config_helpers.attrs.ParameterAttribute +Extra = paddle.trainer_config_helpers.attrs.ExtraLayerAttribute + +for each in paddle.trainer_config_helpers.attrs.__all__: + globals()[each] = getattr(paddle.trainer_config_helpers.attrs, each) + __all__.append(each) diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index 64de568fcc74c..1ec1d7bbdf912 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -42,6 +42,12 @@ def __map_docstr__(doc, name, method_name): # replace LayerOutput to paddle.v2.config_base.Layer doc = doc.replace("LayerOutput", "paddle.v2.config_base.Layer") + doc = doc.replace('ParameterAttribute', + 'paddle.v2.attr.ParameterAttribute') + + doc = re.sub(r'ExtraLayerAttribute[^\s]?', + 'paddle.v2.attr.ExtraAttribute', doc) + # xxx_layer to xxx doc = re.sub(r"(?P[a-z]+)_layer", r"\g", doc) From 4ea3fa623d8411eb54635509c3a415ec1088d755 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 16:13:41 +0800 Subject: [PATCH 110/153] Complete doc of activations --- doc/api/v2/model_configs.rst | 7 +++++++ python/paddle/v2/activation.py | 31 ++++++++++--------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst index 4ca28315d5564..26a1669d4363f 100644 --- a/doc/api/v2/model_configs.rst +++ b/doc/api/v2/model_configs.rst @@ -12,3 +12,10 @@ Attributes .. automodule:: paddle.v2.attr :members: + +=========== +Activations +=========== + +.. automodule:: paddle.v2.activation + :members: diff --git a/python/paddle/v2/activation.py b/python/paddle/v2/activation.py index 1f3aab9ef3c5f..21261a178203b 100644 --- a/python/paddle/v2/activation.py +++ b/python/paddle/v2/activation.py @@ -12,26 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.trainer_config_helpers.activations import * +import paddle.trainer_config_helpers.activations +import copy -__all__ = [ - "Base", "Tanh", "Sigmoid", "Softmax", "Identity", "Linear", - 'SequenceSoftmax', "Exp", "Relu", "BRelu", "SoftRelu", "STanh", "Abs", - "Square", "Log" -] +__all__ = [] -Base = BaseActivation -Tanh = TanhActivation -Sigmoid = SigmoidActivation -Softmax = SoftmaxActivation -SequenceSoftmax = SequenceSoftmaxActivation -Identity = IdentityActivation -Linear = Identity -Relu = ReluActivation -BRelu = BReluActivation -SoftRelu = SoftReluActivation -STanh = STanhActivation -Abs = AbsActivation -Square = SquareActivation -Exp = ExpActivation -Log = LogActivation +suffix = 'Activation' +for act in paddle.trainer_config_helpers.activations.__all__: + new_name = act[:-len(suffix)] + globals()[new_name] = copy.copy( + getattr(paddle.trainer_config_helpers.activations, act)) + globals()[new_name].__name__ = new_name + __all__.append(new_name) From 91cc461aa5c20bc73f61b89b11220e098e27456c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 16:24:19 +0800 Subject: [PATCH 111/153] Complete model_configs's docs --- doc/api/v2/model_configs.rst | 14 ++++++++++++++ python/paddle/v2/networks.py | 1 + python/paddle/v2/pooling.py | 18 ++++++++++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst index 26a1669d4363f..b848bd7045a70 100644 --- a/doc/api/v2/model_configs.rst +++ b/doc/api/v2/model_configs.rst @@ -19,3 +19,17 @@ Activations .. automodule:: paddle.v2.activation :members: + +======== +Poolings +======== + +.. automodule:: paddle.v2.pooling + :members: + +======== +Networks +======== + +.. automodule:: paddle.v2.networks + :members: diff --git a/python/paddle/v2/networks.py b/python/paddle/v2/networks.py index 74d91593d8551..9e6644196c824 100644 --- a/python/paddle/v2/networks.py +++ b/python/paddle/v2/networks.py @@ -38,6 +38,7 @@ def __initialize__(): parent_names=parents, is_default_name='name' in argspec.args) globals()[each_subnetwork] = v2_subnet + globals()[each_subnetwork].__name__ = each_subnetwork global __all__ __all__.append(each_subnetwork) diff --git a/python/paddle/v2/pooling.py b/python/paddle/v2/pooling.py index 9076a159bb4f2..4881c27d1d6d3 100644 --- a/python/paddle/v2/pooling.py +++ b/python/paddle/v2/pooling.py @@ -12,13 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.trainer_config_helpers.poolings import * +import paddle.trainer_config_helpers.poolings +import copy -__all__ = ["Max", "CudnnMax", "Avg", "CudnnAvg", "Sum", "SquareRootN"] +__all__ = [] +suffix = 'Pooling' -Max = MaxPooling -CudnnMax = CudnnMaxPooling -Avg = AvgPooling -CudnnAvg = CudnnAvgPooling -Sum = SumPooling -SquareRootN = SquareRootNPooling +for name in paddle.trainer_config_helpers.poolings.__all__: + new_name = name[:-len(suffix)] + globals()[new_name] = copy.copy( + getattr(paddle.trainer_config_helpers.poolings, name)) + globals()[new_name].__name__ = new_name + __all__.append(new_name) From fb74ae36d4b9ba21ccf98bd45b04c361029e7406 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 17:11:49 +0800 Subject: [PATCH 112/153] Refine serialize --- demo/mnist/.gitignore | 1 + demo/mnist/api_train_v2.py | 3 +++ python/paddle/v2/parameters.py | 40 +++++++++++++++++++++++++++++++++- python/paddle/v2/trainer.py | 4 ++-- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/demo/mnist/.gitignore b/demo/mnist/.gitignore index 9c552159be6f7..ed074b09e7fba 100644 --- a/demo/mnist/.gitignore +++ b/demo/mnist/.gitignore @@ -6,3 +6,4 @@ train.log *pyc .ipynb_checkpoints params.pkl +params.tar diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index a72ebfa980593..7a1f6613188f4 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -103,6 +103,9 @@ def event_handler(event): cPickle.dump( parameters, f, protocol=cPickle.HIGHEST_PROTOCOL) + with open('params.tar', 'w') as f: + parameters.serialize_to_tar(f) + elif isinstance(event, paddle.event.EndPass): result = trainer.test(reader=paddle.reader.batched( paddle.dataset.mnist.test(), batch_size=128)) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index d8c3a73b0ea9e..6a7b883500892 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -1,7 +1,9 @@ import numpy as np import py_paddle.swig_paddle as api from paddle.proto.ParameterConfig_pb2 import ParameterConfig - +import struct +import tarfile +import cStringIO from topology import Topology __all__ = ['Parameters', 'create'] @@ -235,6 +237,42 @@ def __getstate__(self): return {'conf': param_conf, 'params': params} + def serialize(self, name, f): + """ + + :param name: + :param f: + :type f: file + :return: + """ + param = self.get(name) + size = reduce(lambda a, b: a * b, param.shape) + f.write(struct.pack("IIQ", 0, 4, size)) + param = param.astype(np.float32) + f.write(param.tobytes()) + + def deserialize(self, name, f): + """ + + :param name: + :param f: + :type f: file + :return: + """ + f.read(16) # header + arr = np.fromfile(f, dtype=np.float32) + self.set(name, arr.reshape(self.get_shape(name))) + + def serialize_to_tar(self, f): + tar = tarfile.TarFile(fileobj=f, mode='w') + for nm in self.names(): + buf = cStringIO.StringIO() + self.serialize(nm, buf) + tarinfo = tarfile.TarInfo(name=nm) + buf.seek(0) + tarinfo.size = len(buf.getvalue()) + tar.addfile(tarinfo, buf) + def __setstate__(self, obj): Parameters.__init__(self) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index e878ea6e3b39b..7da97d79a85b0 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -101,7 +101,7 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): for each_param in self.__gradient_machine__.getNonStaticParameters( ): updater.update(each_param) - cost_sum = out_args.sumCosts() + cost_sum = out_args.sum() cost = cost_sum / len(data_batch) updater.finishBatch(cost) batch_evaluator.finish() @@ -137,7 +137,7 @@ def test(self, reader, reader_dict=None): num_samples += len(data_batch) self.__gradient_machine__.forward( feeder(data_batch), out_args, api.PASS_TEST) - total_cost += out_args.sumCosts() + total_cost += out_args.sum() self.__gradient_machine__.eval(evaluator) evaluator.finish() From efe53811c569182df71b14c46aa5a7238038cba1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 18:32:39 +0800 Subject: [PATCH 113/153] complete serialize * Test gzip --- demo/mnist/.gitignore | 1 + demo/mnist/api_train_v2.py | 14 ++++----- python/paddle/v2/parameters.py | 54 ++++++++++++++++------------------ 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/demo/mnist/.gitignore b/demo/mnist/.gitignore index ed074b09e7fba..7e61d5e3a0cab 100644 --- a/demo/mnist/.gitignore +++ b/demo/mnist/.gitignore @@ -7,3 +7,4 @@ train.log .ipynb_checkpoints params.pkl params.tar +params.tar.gz diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 7a1f6613188f4..a11260d91b35e 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -1,5 +1,5 @@ import paddle.v2 as paddle -import cPickle +import gzip def softmax_regression(img): @@ -73,8 +73,8 @@ def main(): cost = paddle.layer.classification_cost(input=predict, label=label) try: - with open('params.pkl', 'r') as f: - parameters = cPickle.load(f) + with gzip.open('params.tar.gz', 'r') as f: + parameters = paddle.parameters.Parameters.from_tar(f) except IOError: parameters = paddle.parameters.create(cost) @@ -99,12 +99,8 @@ def event_handler(event): event.pass_id, event.batch_id, event.cost, event.metrics, result.metrics) - with open('params.pkl', 'w') as f: - cPickle.dump( - parameters, f, protocol=cPickle.HIGHEST_PROTOCOL) - - with open('params.tar', 'w') as f: - parameters.serialize_to_tar(f) + with gzip.open('params.tar.gz', 'w') as f: + parameters.to_tar(f) elif isinstance(event, paddle.event.EndPass): result = trainer.test(reader=paddle.reader.batched( diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index 6a7b883500892..58be5234072b8 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -224,19 +224,6 @@ def append_gradient_machine(self, gradient_machine): self.__gradient_machines__.append(gradient_machine) - def __getstate__(self): - params = {} - for name in self.names(): - params[name] = self.get(name) - - param_conf = {} - for name in self.__param_conf__: - conf = self.__param_conf__[name] - assert isinstance(conf, ParameterConfig) - param_conf[name] = conf.SerializeToString() - - return {'conf': param_conf, 'params': params} - def serialize(self, name, f): """ @@ -260,10 +247,10 @@ def deserialize(self, name, f): :return: """ f.read(16) # header - arr = np.fromfile(f, dtype=np.float32) + arr = np.frombuffer(f.read(), dtype=np.float32) self.set(name, arr.reshape(self.get_shape(name))) - def serialize_to_tar(self, f): + def to_tar(self, f): tar = tarfile.TarFile(fileobj=f, mode='w') for nm in self.names(): buf = cStringIO.StringIO() @@ -273,19 +260,30 @@ def serialize_to_tar(self, f): tarinfo.size = len(buf.getvalue()) tar.addfile(tarinfo, buf) - def __setstate__(self, obj): - Parameters.__init__(self) - - def __impl__(conf, params): - for name in conf: - p = ParameterConfig() - p.ParseFromString(conf[name]) - self.__append_config__(p) - for name in params: - shape = self.get_shape(name) - self.set(name, params[name].reshape(shape)) - - __impl__(**obj) + conf = self.__param_conf__[nm] + confStr = conf.SerializeToString() + tarinfo = tarfile.TarInfo(name="%s.protobuf" % nm) + tarinfo.size = len(confStr) + buf = cStringIO.StringIO(confStr) + buf.seek(0) + tar.addfile(tarinfo, fileobj=buf) + + @staticmethod + def from_tar(f): + params = Parameters() + tar = tarfile.TarFile(fileobj=f, mode='r') + for finfo in tar: + assert isinstance(finfo, tarfile.TarInfo) + if finfo.name.endswith('.protobuf'): + f = tar.extractfile(finfo) + conf = ParameterConfig() + conf.ParseFromString(f.read()) + params.__append_config__(conf) + + for param_name in params.names(): + f = tar.extractfile(param_name) + params.deserialize(param_name, f) + return params def __get_parameter_in_gradient_machine__(gradient_machine, name): From 13d21d04a958c691cf2d66df56d7a3ac6fd889b7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 18:38:10 +0800 Subject: [PATCH 114/153] Fix merged error --- python/paddle/v2/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 0ec7e8a454342..0626429291907 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -44,5 +44,5 @@ def init(**kwargs): api.initPaddle(*args) -infer = inferencer.infer -batch = minibatch.batch \ No newline at end of file +infer = inference.infer +batch = minibatch.batch From c5fb4fd4d0f0c3f4ac4322e3b038445a0b16ca7c Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Sat, 4 Mar 2017 18:50:00 +0800 Subject: [PATCH 115/153] optimize import of eqToseq_net_v2 for book --- demo/seqToseq/api_train_v2.py | 1 + demo/seqToseq/seqToseq_net_v2.py | 76 ++++++++++++++++---------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index 74ae1cf9ec81b..8b9db4352ddb1 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -72,6 +72,7 @@ def main(): # define network topology cost = seqToseq_net_v2(source_dict_dim, target_dict_dim) parameters = paddle.parameters.create(cost) + optimizer = paddle.optimizer.Adam(learning_rate=1e-4) def event_handler(event): diff --git a/demo/seqToseq/seqToseq_net_v2.py b/demo/seqToseq/seqToseq_net_v2.py index 1ac95686b4352..058a6789d7094 100644 --- a/demo/seqToseq/seqToseq_net_v2.py +++ b/demo/seqToseq/seqToseq_net_v2.py @@ -1,8 +1,4 @@ -import paddle.v2.activation as activation -import paddle.v2.attr as attr -import paddle.v2.data_type as data_type -import paddle.v2.layer as layer -import paddle.v2.networks as networks +import paddle.v2 as paddle def seqToseq_net_v2(source_dict_dim, target_dict_dim): @@ -12,64 +8,70 @@ def seqToseq_net_v2(source_dict_dim, target_dict_dim): encoder_size = 512 # dimension of hidden unit in GRU Encoder network #### Encoder - src_word_id = layer.data( + src_word_id = paddle.layer.data( name='source_language_word', - type=data_type.integer_value_sequence(source_dict_dim)) - src_embedding = layer.embedding( + type=paddle.data_type.integer_value_sequence(source_dict_dim)) + src_embedding = paddle.layer.embedding( input=src_word_id, size=word_vector_dim, - param_attr=attr.ParamAttr(name='_source_language_embedding')) - src_forward = networks.simple_gru(input=src_embedding, size=encoder_size) - src_backward = networks.simple_gru( + param_attr=paddle.attr.ParamAttr(name='_source_language_embedding')) + src_forward = paddle.networks.simple_gru( + input=src_embedding, size=encoder_size) + src_backward = paddle.networks.simple_gru( input=src_embedding, size=encoder_size, reverse=True) - encoded_vector = layer.concat(input=[src_forward, src_backward]) + encoded_vector = paddle.layer.concat(input=[src_forward, src_backward]) #### Decoder - with layer.mixed(size=decoder_size) as encoded_proj: - encoded_proj += layer.full_matrix_projection(input=encoded_vector) + with paddle.layer.mixed(size=decoder_size) as encoded_proj: + encoded_proj += paddle.layer.full_matrix_projection( + input=encoded_vector) - backward_first = layer.first_seq(input=src_backward) + backward_first = paddle.layer.first_seq(input=src_backward) - with layer.mixed(size=decoder_size, act=activation.Tanh()) as decoder_boot: - decoder_boot += layer.full_matrix_projection(input=backward_first) + with paddle.layer.mixed( + size=decoder_size, act=paddle.activation.Tanh()) as decoder_boot: + decoder_boot += paddle.layer.full_matrix_projection( + input=backward_first) def gru_decoder_with_attention(enc_vec, enc_proj, current_word): - decoder_mem = layer.memory( + decoder_mem = paddle.layer.memory( name='gru_decoder', size=decoder_size, boot_layer=decoder_boot) - context = networks.simple_attention( + context = paddle.networks.simple_attention( encoded_sequence=enc_vec, encoded_proj=enc_proj, decoder_state=decoder_mem) - with layer.mixed(size=decoder_size * 3) as decoder_inputs: - decoder_inputs += layer.full_matrix_projection(input=context) - decoder_inputs += layer.full_matrix_projection(input=current_word) + with paddle.layer.mixed(size=decoder_size * 3) as decoder_inputs: + decoder_inputs += paddle.layer.full_matrix_projection(input=context) + decoder_inputs += paddle.layer.full_matrix_projection( + input=current_word) - gru_step = layer.gru_step( + gru_step = paddle.layer.gru_step( name='gru_decoder', input=decoder_inputs, output_mem=decoder_mem, size=decoder_size) - with layer.mixed( - size=target_dict_dim, bias_attr=True, - act=activation.Softmax()) as out: - out += layer.full_matrix_projection(input=gru_step) + with paddle.layer.mixed( + size=target_dict_dim, + bias_attr=True, + act=paddle.activation.Softmax()) as out: + out += paddle.layer.full_matrix_projection(input=gru_step) return out decoder_group_name = "decoder_group" - group_input1 = layer.StaticInputV2(input=encoded_vector, is_seq=True) - group_input2 = layer.StaticInputV2(input=encoded_proj, is_seq=True) + group_input1 = paddle.layer.StaticInputV2(input=encoded_vector, is_seq=True) + group_input2 = paddle.layer.StaticInputV2(input=encoded_proj, is_seq=True) group_inputs = [group_input1, group_input2] - trg_embedding = layer.embedding( - input=layer.data( + trg_embedding = paddle.layer.embedding( + input=paddle.layer.data( name='target_language_word', - type=data_type.integer_value_sequence(target_dict_dim)), + type=paddle.data_type.integer_value_sequence(target_dict_dim)), size=word_vector_dim, - param_attr=attr.ParamAttr(name='_target_language_embedding')) + param_attr=paddle.attr.ParamAttr(name='_target_language_embedding')) group_inputs.append(trg_embedding) # For decoder equipped with attention mechanism, in training, @@ -77,14 +79,14 @@ def gru_decoder_with_attention(enc_vec, enc_proj, current_word): # while encoded source sequence is accessed to as an unbounded memory. # Here, the StaticInput defines a read-only memory # for the recurrent_group. - decoder = layer.recurrent_group( + decoder = paddle.layer.recurrent_group( name=decoder_group_name, step=gru_decoder_with_attention, input=group_inputs) - lbl = layer.data( + lbl = paddle.layer.data( name='target_language_next_word', - type=data_type.integer_value_sequence(target_dict_dim)) - cost = layer.classification_cost(input=decoder, label=lbl) + type=paddle.data_type.integer_value_sequence(target_dict_dim)) + cost = paddle.layer.classification_cost(input=decoder, label=lbl) return cost From 3432b4cd2e02e540e73f74c25908c40166ce179a Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 18:39:35 +0800 Subject: [PATCH 116/153] Fix pre-commit style checker --- python/paddle/v2/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 0626429291907..25526bf409cf8 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -44,5 +44,6 @@ def init(**kwargs): api.initPaddle(*args) + infer = inference.infer batch = minibatch.batch From 3e398eaa8b147c4529cf1d678dec2e17ddab0c4e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 21:10:42 +0800 Subject: [PATCH 117/153] Follow comments --- python/paddle/v2/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 1608aa3f7147d..1e4efedde363f 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -28,7 +28,7 @@ act=paddle.activation.Softmax()) # use prediction instance where needed. - parameters = paddle.v2.parameters.create(cost) + parameters = paddle.parameters.create(cost) """ import collections From fd41a87a53d921ba2d5165022656fd99b5537dcb Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sat, 4 Mar 2017 21:50:00 +0800 Subject: [PATCH 118/153] complete data_type documentation --- doc/api/index_en.rst | 10 ++- doc/api/v2/data.rst | 6 ++ python/paddle/trainer/PyDataProvider2.py | 93 +++++++++++++++++++++++- python/paddle/v2/data_type.py | 16 ++-- 4 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 doc/api/v2/data.rst diff --git a/doc/api/index_en.rst b/doc/api/index_en.rst index b7f470e1f8a9a..deeeed26fa6ee 100644 --- a/doc/api/index_en.rst +++ b/doc/api/index_en.rst @@ -7,4 +7,12 @@ Model Config API .. toctree:: :maxdepth: 1 - v2/model_configs.rst \ No newline at end of file + v2/model_configs.rst + +Data API +-------- + +.. toctree:: + :maxdepth: 1 + + v2/data.rst diff --git a/doc/api/v2/data.rst b/doc/api/v2/data.rst new file mode 100644 index 0000000000000..65e57f2344bd5 --- /dev/null +++ b/doc/api/v2/data.rst @@ -0,0 +1,6 @@ +######### +DataTypes +######### + +.. automodule:: paddle.v2.data_type + :members: diff --git a/python/paddle/trainer/PyDataProvider2.py b/python/paddle/trainer/PyDataProvider2.py index 4e3c4db853205..0e752c117c1ec 100644 --- a/python/paddle/trainer/PyDataProvider2.py +++ b/python/paddle/trainer/PyDataProvider2.py @@ -45,6 +45,23 @@ class CacheType(object): class InputType(object): + """ + InputType is the base class for paddle input types. + + .. note:: + + this is a base class, and should never be used by user. + + :param dim: dimension of input. If the input is an integer, it means the + value range. Otherwise, it means the size of layer. + :type dim: int + :param seq_type: sequence type of input. 0 means it is not a sequence. 1 + means it is a variable length sequence. 2 means it is a + nested sequence. + :type seq_type: int + :param type: data type of input. + :type type: int + """ __slots__ = ['dim', 'seq_type', 'type'] def __init__(self, dim, seq_type, tp): @@ -54,20 +71,61 @@ def __init__(self, dim, seq_type, tp): def dense_slot(dim, seq_type=SequenceType.NO_SEQUENCE): + """ + Dense Vector. It means the input feature is dense float vector. For example, + if the input is an image with 28*28 pixels, the input of Paddle neural + network should be a dense vector with dimension 784. + + :param dim: dimension of this vector. + :type dim: int + :param seq_type: sequence type of input. + :type seq_type: int + :return: An input type object. + :rtype: InputType + """ return InputType(dim, seq_type, DataType.Dense) def sparse_non_value_slot(dim, seq_type=SequenceType.NO_SEQUENCE): + """ + Sparse binary vector. It means the input feature is a sparse vector and the + every element in this vector is either zero or one. + + :param dim: dimension of this vector. + :type dim: int + :param seq_type: sequence type of this input. + :type seq_type: int + :return: An input type object. + :rtype: InputType + """ return InputType(dim, seq_type, DataType.SparseNonValue) def sparse_value_slot(dim, seq_type=SequenceType.NO_SEQUENCE): + """ + Sparse vector. It means the input feature is a sparse vector. Most of the + elements in this vector are zero, others could be any float value. + + :param dim: dimension of this vector. + :type dim: int + :param seq_type: sequence type of this input. + :type seq_type: int + :return: An input type object. + :rtype: InputType + """ return InputType(dim, seq_type, DataType.SparseValue) def index_slot(value_range, seq_type=SequenceType.NO_SEQUENCE): - """Data type of integer. + """ + Data type of integer. + + :param seq_type: sequence type of this input. + :type seq_type: int :param value_range: range of this integer. + :type value_range: int + :return: An input type object + :rtype: InputType """ return InputType(value_range, seq_type, DataType.Index) @@ -76,10 +134,17 @@ def index_slot(value_range, seq_type=SequenceType.NO_SEQUENCE): sparse_binary_vector = sparse_non_value_slot sparse_vector = sparse_value_slot integer_value = index_slot -integer_value.__doc__ = index_slot.__doc__ def dense_vector_sequence(dim): + """ + Data type of a sequence of dense vector. + + :param dim: dimension of dense vector. + :type dim: int + :return: An input type object + :rtype: InputType + """ return dense_vector(dim, seq_type=SequenceType.SEQUENCE) @@ -88,6 +153,15 @@ def dense_vector_sub_sequence(dim): def sparse_binary_vector_sequence(dim): + """ + Data type of a sequence of sparse vector, which every element is either zero + or one. + + :param dim: dimension of sparse vector. + :type dim: int + :return: An input type object + :rtype: InputType + """ return sparse_binary_vector(dim, seq_type=SequenceType.SEQUENCE) @@ -96,6 +170,15 @@ def sparse_binary_vector_sub_sequence(dim): def sparse_vector_sequence(dim): + """ + Data type of a sequence of sparse vector, which most elements are zero, + others could be any float value. + + :param dim: dimension of sparse vector. + :type dim: int + :return: An input type object + :rtype: InputType + """ return sparse_vector(dim, seq_type=SequenceType.SEQUENCE) @@ -104,8 +187,11 @@ def sparse_vector_sub_sequence(dim): def integer_value_sequence(value_range): - """Data type of a sequence of integer. + """ + Data type of a sequence of integer. + :param value_range: range of each element. + :type value_range: int """ return integer_value(value_range, seq_type=SequenceType.SEQUENCE) @@ -115,7 +201,6 @@ def integer_value_sub_sequence(dim): integer_sequence = integer_value_sequence -integer_sequence.__doc__ = integer_value_sequence.__doc__ class SingleSlotWrapper(object): diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index 522ddfdaacce4..d582f76ddf01e 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -12,11 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.trainer.PyDataProvider2 import \ - InputType, DataType, dense_vector, sparse_binary_vector,\ - sparse_vector, integer_value, integer_value_sequence +import paddle.trainer.PyDataProvider2 as pydp2 -__all__ = [ - 'InputType', 'DataType', 'dense_vector', 'sparse_binary_vector', - 'sparse_vector', 'integer_value', 'integer_value_sequence' +import_list = [ + nm for nm in dir(pydp2) + if '_' in nm and nm[0] != '_' and ('value' in nm or 'vector' in nm) ] +import_list.extend(['InputType']) + +for nm in import_list: + globals()[nm] = getattr(pydp2, nm) + +__all__ = import_list From 8fa09b82f9c182b8bec4b538b7c7da9ace03b4eb Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Sat, 4 Mar 2017 21:50:56 +0800 Subject: [PATCH 119/153] add some comment for api_train_v2 of seqtoseq --- demo/seqToseq/api_train_v2.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index 8b9db4352ddb1..a5f59ec379738 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -73,31 +73,34 @@ def main(): cost = seqToseq_net_v2(source_dict_dim, target_dict_dim) parameters = paddle.parameters.create(cost) + # define optimize method and trainer optimizer = paddle.optimizer.Adam(learning_rate=1e-4) - - def event_handler(event): - if isinstance(event, paddle.event.EndIteration): - if event.batch_id % 10 == 0: - print "Pass %d, Batch %d, Cost %f, %s" % ( - event.pass_id, event.batch_id, event.cost, event.metrics) - trainer = paddle.trainer.SGD(cost=cost, parameters=parameters, update_equation=optimizer) + # define data reader reader_dict = { 'source_language_word': 0, 'target_language_word': 1, 'target_language_next_word': 2 } - trn_reader = paddle.reader.batched( + wmt14_reader = paddle.reader.batched( paddle.reader.shuffle( train_reader("data/pre-wmt14/train/train"), buf_size=8192), batch_size=5) + # define event_handler callback + def event_handler(event): + if isinstance(event, paddle.event.EndIteration): + if event.batch_id % 10 == 0: + print "Pass %d, Batch %d, Cost %f, %s" % ( + event.pass_id, event.batch_id, event.cost, event.metrics) + + # start to train trainer.train( - reader=trn_reader, + reader=wmt14_reader, event_handler=event_handler, num_passes=10000, reader_dict=reader_dict) From 797da0695883372a911984b08d7f30ae6de2061f Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 27 Feb 2017 18:04:07 -0800 Subject: [PATCH 120/153] word2vec v2 api --- demo/word2vec/train_v2.py | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 demo/word2vec/train_v2.py diff --git a/demo/word2vec/train_v2.py b/demo/word2vec/train_v2.py new file mode 100644 index 0000000000000..60235c93eab83 --- /dev/null +++ b/demo/word2vec/train_v2.py @@ -0,0 +1,80 @@ +import math + +import paddle.v2 as paddle + +dictsize = 1953 +embsize = 32 +hiddensize = 256 +N = 5 + + +def wordemb(inlayer): + wordemb = paddle.layer.table_projection( + input=inlayer, + size=embsize, + param_attr=paddle.attr.Param( + name="_proj", + initial_std=0.001, + learning_rate=1, + l2_rate=0, )) + return wordemb + + +def main(): + paddle.init(use_gpu=False, trainer_count=1) + word_dict = paddle.dataset.imikolov.build_dict() + dict_size = len(word_dict) + firstword = paddle.layer.data( + name="firstw", type=paddle.data_type.integer_value(dict_size)) + secondword = paddle.layer.data( + name="secondw", type=paddle.data_type.integer_value(dict_size)) + thirdword = paddle.layer.data( + name="thirdw", type=paddle.data_type.integer_value(dict_size)) + fourthword = paddle.layer.data( + name="fourthw", type=paddle.data_type.integer_value(dict_size)) + nextword = paddle.layer.data( + name="fifthw", type=paddle.data_type.integer_value(dict_size)) + + Efirst = wordemb(firstword) + Esecond = wordemb(secondword) + Ethird = wordemb(thirdword) + Efourth = wordemb(fourthword) + + contextemb = paddle.layer.concat(input=[Efirst, Esecond, Ethird, Efourth]) + hidden1 = paddle.layer.fc(input=contextemb, + size=hiddensize, + act=paddle.activation.Sigmoid(), + layer_attr=paddle.attr.Extra(drop_rate=0.5), + bias_attr=paddle.attr.Param(learning_rate=2), + param_attr=paddle.attr.Param( + initial_std=1. / math.sqrt(embsize * 8), + learning_rate=1)) + predictword = paddle.layer.fc(input=hidden1, + size=dict_size, + bias_attr=paddle.attr.Param(learning_rate=2), + act=paddle.activation.Softmax()) + + def event_handler(event): + if isinstance(event, paddle.event.EndIteration): + if event.batch_id % 100 == 0: + result = trainer.test( + paddle.dataset.imikolov.test(word_dict, N), 128) + print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % ( + event.pass_id, event.batch_id, event.cost, event.metrics, + result.metrics) + + cost = paddle.layer.classification_cost(input=predictword, label=nextword) + parameters = paddle.parameters.create(cost) + adam_optimizer = paddle.optimizer.Adam( + learning_rate=3e-3, + regularization=paddle.optimizer.L2Regularization(8e-4)) + trainer = paddle.trainer.SGD(cost, parameters, adam_optimizer) + trainer.train( + paddle.dataset.imikolov.train(word_dict, N), + num_passes=30, + batch_size=128, + event_handler=event_handler, ) + + +if __name__ == '__main__': + main() From 97a1c0c7e116a4f2e1939ee3aee85eeb401312ab Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Sat, 4 Mar 2017 17:43:38 +0000 Subject: [PATCH 121/153] update word2vec to work with current train api --- demo/word2vec/train_v2.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/word2vec/train_v2.py b/demo/word2vec/train_v2.py index 60235c93eab83..7d952b446f9db 100644 --- a/demo/word2vec/train_v2.py +++ b/demo/word2vec/train_v2.py @@ -58,7 +58,8 @@ def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 100 == 0: result = trainer.test( - paddle.dataset.imikolov.test(word_dict, N), 128) + paddle.batch( + paddle.dataset.imikolov.test(word_dict, N), 32)) print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % ( event.pass_id, event.batch_id, event.cost, event.metrics, result.metrics) @@ -70,10 +71,9 @@ def event_handler(event): regularization=paddle.optimizer.L2Regularization(8e-4)) trainer = paddle.trainer.SGD(cost, parameters, adam_optimizer) trainer.train( - paddle.dataset.imikolov.train(word_dict, N), + paddle.batch(paddle.dataset.imikolov.train(word_dict, N), 32), num_passes=30, - batch_size=128, - event_handler=event_handler, ) + event_handler=event_handler) if __name__ == '__main__': From dbffda2ff5e08c8675e5d9a5bd171d2bf62e067b Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Sat, 4 Mar 2017 17:44:24 +0000 Subject: [PATCH 122/153] change sumCost to sum --- python/paddle/v2/trainer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 8bcdd122b30bd..dd64f0565b0e2 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -101,7 +101,7 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): for each_param in self.__gradient_machine__.getNonStaticParameters( ): updater.update(each_param) - cost_sum = out_args.sumCosts() + cost_sum = out_args.sum() cost = cost_sum / len(data_batch) updater.finishBatch(cost) batch_evaluator.finish() @@ -137,7 +137,7 @@ def test(self, reader, reader_dict=None): num_samples += len(data_batch) self.__gradient_machine__.forward( feeder(data_batch), out_args, api.PASS_TEST) - total_cost += out_args.sumCosts() + total_cost += out_args.sum() self.__gradient_machine__.eval(evaluator) evaluator.finish() From 88cb8eeac4b62d32ef74708e7658effb5f96b53e Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Sun, 5 Mar 2017 12:07:39 +0800 Subject: [PATCH 123/153] Complete documentation for v2. --- doc/api/index_cn.rst | 26 +++++++- doc/api/index_en.rst | 8 +++ doc/api/v2/data.rst | 79 ++++++++++++++++++++++++- doc/api/v2/model_configs.rst | 7 +++ doc/api/v2/run_logic.rst | 22 +++++++ doc/design/reader/README.md | 74 +++++++++++------------ python/paddle/v2/data_feeder.py | 49 +++++++-------- python/paddle/v2/dataset/__init__.py | 3 + python/paddle/v2/dataset/cifar.py | 2 + python/paddle/v2/dataset/conll05.py | 6 +- python/paddle/v2/dataset/imdb.py | 2 + python/paddle/v2/dataset/imikolov.py | 2 + python/paddle/v2/dataset/mnist.py | 21 +++++++ python/paddle/v2/dataset/movielens.py | 5 ++ python/paddle/v2/dataset/sentiment.py | 11 ++-- python/paddle/v2/dataset/uci_housing.py | 5 ++ python/paddle/v2/event.py | 4 ++ python/paddle/v2/optimizer.py | 11 +++- python/paddle/v2/parameters.py | 6 ++ python/paddle/v2/reader/__init__.py | 65 +++++++++++++++++--- python/paddle/v2/reader/creator.py | 6 +- python/paddle/v2/reader/decorator.py | 50 +++++++++++----- python/paddle/v2/trainer.py | 26 +++++--- 23 files changed, 381 insertions(+), 109 deletions(-) create mode 100644 doc/api/v2/run_logic.rst diff --git a/doc/api/index_cn.rst b/doc/api/index_cn.rst index 874dd9cb2278c..fca981221e490 100644 --- a/doc/api/index_cn.rst +++ b/doc/api/index_cn.rst @@ -1,2 +1,26 @@ API -=== \ No newline at end of file +=== + +模型配置 API +------------ + +.. toctree:: + :maxdepth: 1 + + v2/model_configs.rst + +数据 API +-------- + +.. toctree:: + :maxdepth: 1 + + v2/data.rst + +训练 API +-------- + +.. toctree:: + :maxdepth: 1 + + v2/run_logic.rst \ No newline at end of file diff --git a/doc/api/index_en.rst b/doc/api/index_en.rst index deeeed26fa6ee..f0ad0fb2aee73 100644 --- a/doc/api/index_en.rst +++ b/doc/api/index_en.rst @@ -16,3 +16,11 @@ Data API :maxdepth: 1 v2/data.rst + +Train API +--------- + +.. toctree:: + :maxdepth: 1 + + v2/run_logic.rst \ No newline at end of file diff --git a/doc/api/v2/data.rst b/doc/api/v2/data.rst index 65e57f2344bd5..49f70b3671bdf 100644 --- a/doc/api/v2/data.rst +++ b/doc/api/v2/data.rst @@ -2,5 +2,80 @@ DataTypes ######### -.. automodule:: paddle.v2.data_type - :members: +.. automodule:: paddle.v2.data_type + :members: + +########## +DataFeeder +########## + +.. automodule:: paddle.v2.data_feeder + :members: + +###### +Reader +###### + +.. automodule:: paddle.v2.reader + :members: + +.. automodule:: paddle.v2.reader.creator + :members: + +####### +Dataset +####### + +.. automodule:: paddle.v2.dataset + :members: + + +mnist ++++++ + +.. automodule:: paddle.v2.dataset.mnist + :members: + + +cifar ++++++ + +.. automodule:: paddle.v2.dataset.cifar + :members: + +conll05 ++++++++ + +.. automodule:: paddle.v2.dataset.conll05 + :members: + +imdb +++++ + +.. automodule:: paddle.v2.dataset.imdb + :members: + +imikolov +++++++++ + +.. automodule:: paddle.v2.dataset.imikolov + :members: + +movielens ++++++++++ + +.. automodule:: paddle.v2.dataset.movielens + :members: + +sentiment ++++++++++ + +.. automodule:: paddle.v2.dataset.sentiment + :members: + +uci_housing ++++++++++++ + +.. automodule:: paddle.v2.dataset.uci_housing + :members: + diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst index b848bd7045a70..52e2dcd53055c 100644 --- a/doc/api/v2/model_configs.rst +++ b/doc/api/v2/model_configs.rst @@ -33,3 +33,10 @@ Networks .. automodule:: paddle.v2.networks :members: + +========== +Optimizers +========== + +.. automodule:: paddle.v2.optimizers + :members: diff --git a/doc/api/v2/run_logic.rst b/doc/api/v2/run_logic.rst new file mode 100644 index 0000000000000..522093f8aeedb --- /dev/null +++ b/doc/api/v2/run_logic.rst @@ -0,0 +1,22 @@ +========== +Parameters +========== + +.. automodule:: paddle.v2.parameters + :members: + + +======= +Trainer +======= + +.. automodule:: paddle.v2.trainer + :members: + + +===== +Event +===== + +.. automodule:: paddle.v2.event + :members: diff --git a/doc/design/reader/README.md b/doc/design/reader/README.md index 03119fdd74502..f21f7af520df5 100644 --- a/doc/design/reader/README.md +++ b/doc/design/reader/README.md @@ -23,19 +23,19 @@ An example implementation for single item data reader creator: ```python def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height) + return reader ``` An example implementation for multiple item data reader creator: ```python -def reader_creator_random_imageand_label(widht, height, label): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height), label - return reader +def reader_creator_random_image_and_label(width, height, label): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height), label + return reader ``` ## Batch Reader Interface @@ -74,11 +74,11 @@ mnist_train_batch_reader = paddle.batch(mnist_train, 128) Also easy to create custom batch reader: ```python def custom_batch_reader(): - while True: - batch = [] - for i in xrange(128): - batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended. - yield batch + while True: + batch = [] + for i in xrange(128): + batch.append((numpy.random.uniform(-1, 1, 28*28),)) # note that it's a tuple being appended. + yield batch mnist_random_image_batch_reader = custom_batch_reader ``` @@ -123,16 +123,16 @@ We can do: ```python def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height) + return reader def reader_creator_bool(t): - def reader: - while True: - yield t - return reader + def reader: + while True: + yield t + return reader true_reader = reader_creator_bool(True) false_reader = reader_creator_bool(False) @@ -172,18 +172,18 @@ We decided to use dictionary (`{"image":0, "label":1}`) instead of list (`["imag ```python def image_reader_creator(image_path, label_path, n): - def reader(): - f = open(image_path) - l = open(label_path) - images = numpy.fromfile( - f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32') - images = images / 255.0 * 2.0 - 1.0 - labels = numpy.fromfile(l, 'ubyte', count=n).astype("int") - for i in xrange(n): - yield images[i, :], labels[i] # a single entry of data is created each time - f.close() - l.close() - return reader + def reader(): + f = open(image_path) + l = open(label_path) + images = numpy.fromfile( + f, 'ubyte', count=n * 28 * 28).reshape((n, 28 * 28)).astype('float32') + images = images / 255.0 * 2.0 - 1.0 + labels = numpy.fromfile(l, 'ubyte', count=n).astype("int") + for i in xrange(n): + yield images[i, :], labels[i] # a single entry of data is created each time + f.close() + l.close() + return reader # images_reader_creator creates a reader reader = image_reader_creator("/path/to/image_file", "/path/to/label_file", 1024) @@ -196,7 +196,7 @@ An example implementation of paddle.train could be: ```python def train(batch_reader, mapping, batch_size, total_pass): - for pass_idx in range(total_pass): - for mini_batch in batch_reader(): # this loop will never end in online learning. - do_forward_backward(mini_batch, mapping) + for pass_idx in range(total_pass): + for mini_batch in batch_reader(): # this loop will never end in online learning. + do_forward_backward(mini_batch, mapping) ``` diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 3b106e100cff7..b7465238be813 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from py_paddle import swig_paddle from py_paddle import DataProviderConverter + import data_type __all__ = ['DataFeeder'] @@ -29,7 +29,10 @@ class DataFeeder(DataProviderConverter): to feed it to C++ interface. The example usage: - + + + .. code-block:: python + data_types = [('image', paddle.data_type.dense_vector(784)), ('label', paddle.data_type.integer_value(10))] reader_dict = {'image':0, 'label':1} @@ -43,20 +46,24 @@ class DataFeeder(DataProviderConverter): # [ [1.0,2.0,3.0,4.0], 5, [6,7,8] ] # second sample # ] arg = feeder(minibatch_data) + + .. note:: + + This module is for internal use only. Users should use the `reader` + interface. + + + + :param data_types: A list to specify data name and type. Each item is + a tuple of (data_name, data_type). + + :type data_types: list + :param reader_dict: A dictionary to specify the position of each data + in the input data. + :type reader_dict: dict """ def __init__(self, data_types, reader_dict): - """ - :param data_types: A list to specify data name and type. Each item is - a tuple of (data_name, data_type). For example: - [('image', paddle.data_type.dense_vector(784)), - ('label', paddle.data_type.integer_value(10))] - - :type data_types: A list of tuple - :param reader_dict: A dictionary to specify the position of each data - in the input data. - :type reader_dict: dict() - """ self.input_names = [] input_types = [] self.reader_dict = reader_dict @@ -70,22 +77,12 @@ def convert(self, dat, argument=None): """ :param dat: A list of mini-batch data. Each sample is a list or tuple one feature or multiple features. - for example: - [ - ([0.2, 0.2], ), # first sample - ([0.8, 0.3], ), # second sample - ] - or, - [ - [[0.2, 0.2], ], # first sample - [[0.8, 0.3], ], # second sample - ] - - :type dat: List + + :type dat: list :param argument: An Arguments object contains this mini-batch data with one or multiple features. The Arguments definition is in the API. - :type argument: swig_paddle.Arguments + :type argument: py_paddle.swig_paddle.Arguments """ def reorder_data(data): diff --git a/python/paddle/v2/dataset/__init__.py b/python/paddle/v2/dataset/__init__.py index 82f11a7c41149..9ef0277609d29 100644 --- a/python/paddle/v2/dataset/__init__.py +++ b/python/paddle/v2/dataset/__init__.py @@ -11,6 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +""" +Dataset package. +""" import mnist import imikolov diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 5c6f5d85567fa..d9f7a830ee60a 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -13,6 +13,8 @@ # limitations under the License. """ CIFAR dataset: https://www.cs.toronto.edu/~kriz/cifar.html + +TODO(yuyang18): Complete the comments. """ import cPickle diff --git a/python/paddle/v2/dataset/conll05.py b/python/paddle/v2/dataset/conll05.py index e96a701c1a944..9eab49ee39325 100644 --- a/python/paddle/v2/dataset/conll05.py +++ b/python/paddle/v2/dataset/conll05.py @@ -16,15 +16,17 @@ import gzip import itertools from common import download - -__all__ = ['test, get_dict', 'get_embedding'] """ Conll 2005 dataset. Paddle semantic role labeling Book and demo use this dataset as an example. Because Conll 2005 is not free in public, the default downloaded URL is test set of Conll 2005 (which is public). Users can change URL and MD5 to their Conll dataset. + +TODO(yuyang18): Complete comments. """ +__all__ = ['test, get_dict', 'get_embedding'] + DATA_URL = 'http://www.cs.upc.edu/~srlconll/conll05st-tests.tar.gz' DATA_MD5 = '387719152ae52d60422c016e92a742fc' WORDDICT_URL = 'http://paddlepaddle.bj.bcebos.com/demo/srl_dict_and_embedding/wordDict.txt' diff --git a/python/paddle/v2/dataset/imdb.py b/python/paddle/v2/dataset/imdb.py index f27756a38a9cd..76019d9f54020 100644 --- a/python/paddle/v2/dataset/imdb.py +++ b/python/paddle/v2/dataset/imdb.py @@ -13,6 +13,8 @@ # limitations under the License. """ IMDB dataset: http://ai.stanford.edu/%7Eamaas/data/sentiment/aclImdb_v1.tar.gz + +TODO(yuyang18): Complete comments. """ import paddle.v2.dataset.common diff --git a/python/paddle/v2/dataset/imikolov.py b/python/paddle/v2/dataset/imikolov.py index deb556942d9b0..97c160f111d09 100644 --- a/python/paddle/v2/dataset/imikolov.py +++ b/python/paddle/v2/dataset/imikolov.py @@ -13,6 +13,8 @@ # limitations under the License. """ imikolov's simple dataset: http://www.fit.vutbr.cz/~imikolov/rnnlm/ + +Complete comments. """ import paddle.v2.dataset.common import tarfile diff --git a/python/paddle/v2/dataset/mnist.py b/python/paddle/v2/dataset/mnist.py index 6a621a2aaad14..16f2fcb99de4c 100644 --- a/python/paddle/v2/dataset/mnist.py +++ b/python/paddle/v2/dataset/mnist.py @@ -13,6 +13,9 @@ # limitations under the License. """ MNIST dataset. + +This module will download dataset from http://yann.lecun.com/exdb/mnist/ and +parse train set and test set into paddle reader creators. """ import paddle.v2.dataset.common import subprocess @@ -72,6 +75,15 @@ def reader(): def train(): + """ + MNIST train set creator. + + It returns a reader creator, each sample in the reader is image pixels in + [0, 1] and label in [0, 9]. + + :return: Train reader creator + :rtype: callable + """ return reader_creator( paddle.v2.dataset.common.download(TRAIN_IMAGE_URL, 'mnist', TRAIN_IMAGE_MD5), @@ -80,6 +92,15 @@ def train(): def test(): + """ + MNIST test set cretor. + + It returns a reader creator, each sample in the reader is image pixels in + [0, 1] and label in [0, 9]. + + :return: Test reader creator. + :rtype: callable + """ return reader_creator( paddle.v2.dataset.common.download(TEST_IMAGE_URL, 'mnist', TEST_IMAGE_MD5), diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py index c22bcfa38b5f5..dc65e8f8b6f04 100644 --- a/python/paddle/v2/dataset/movielens.py +++ b/python/paddle/v2/dataset/movielens.py @@ -11,6 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +""" +Movielens 1-M dataset. + +TODO(yuyang18): Complete comments. +""" import zipfile from common import download diff --git a/python/paddle/v2/dataset/sentiment.py b/python/paddle/v2/dataset/sentiment.py index cbd08fa73684b..71689fd61b6b1 100644 --- a/python/paddle/v2/dataset/sentiment.py +++ b/python/paddle/v2/dataset/sentiment.py @@ -15,18 +15,19 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -The script fetch and preprocess movie_reviews data set +The script fetch and preprocess movie_reviews data set that provided by NLTK -that provided by NLTK +TODO(yuyang18): Complete dataset. """ -import common import collections -import nltk -import numpy as np from itertools import chain + +import nltk from nltk.corpus import movie_reviews +import common + __all__ = ['train', 'test', 'get_word_dict'] NUM_TRAINING_INSTANCES = 1600 NUM_TOTAL_INSTANCES = 2000 diff --git a/python/paddle/v2/dataset/uci_housing.py b/python/paddle/v2/dataset/uci_housing.py index b5a0537af66a3..27f454b137e3a 100644 --- a/python/paddle/v2/dataset/uci_housing.py +++ b/python/paddle/v2/dataset/uci_housing.py @@ -11,6 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +""" +UCI Housing dataset. + +TODO(yuyang18): Complete comments. +""" import numpy as np import os diff --git a/python/paddle/v2/event.py b/python/paddle/v2/event.py index a429e36b63c9e..1ad52b8baa411 100644 --- a/python/paddle/v2/event.py +++ b/python/paddle/v2/event.py @@ -34,6 +34,10 @@ def metrics(self): class TestResult(WithMetric): + """ + Result that trainer.test return. + """ + def __init__(self, evaluator, cost): super(TestResult, self).__init__(evaluator) self.cost = cost diff --git a/python/paddle/v2/optimizer.py b/python/paddle/v2/optimizer.py index 10e255dc945ef..1a01d95c205c0 100644 --- a/python/paddle/v2/optimizer.py +++ b/python/paddle/v2/optimizer.py @@ -1,7 +1,12 @@ import py_paddle.swig_paddle as swig_api -import paddle.trainer_config_helpers.optimizers as v1_optimizers + import paddle.trainer_config_helpers.config_parser_utils as config_parser_utils -import paddle.v2 +import paddle.trainer_config_helpers.optimizers as v1_optimizers +""" +Optimizers(update equation) for SGD method. + +TODO(yuyang18): Complete comments. +""" __all__ = [ 'Momentum', 'Adam', 'Adamax', 'AdaGrad', 'DecayedAdaGrad', 'AdaDelta', @@ -44,7 +49,7 @@ def create_remote_updater(self, pass_num): class Momentum(Optimizer): def __init__(self, momentum=None, sparse=False, **kwargs): learning_method = v1_optimizers.MomentumOptimizer( - momentum=None, sparse=False) + momentum=momentum, sparse=sparse) super(Momentum, self).__init__( learning_method=learning_method, **kwargs) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index 2a6026bcab1c8..7ee388f067c18 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -10,6 +10,7 @@ def create(layers): """ Create parameter pool by topology. + :param layers: :return: """ @@ -67,6 +68,7 @@ def __append_config__(self, param_conf): def keys(self): """ keys are the names of each parameter. + :return: list of parameter name :rtype: list """ @@ -75,6 +77,7 @@ def keys(self): def names(self): """ names of each parameter. + :return: list of parameter name :rtype: list """ @@ -83,6 +86,7 @@ def names(self): def has_key(self, key): """ has_key return true if there are such parameter name == key + :param key: Parameter name :type key: basestring :return: True if contains such key @@ -136,6 +140,7 @@ def __getitem__(self, key): def get_shape(self, key): """ get shape of the parameter. + :param key: parameter name :type key: basestring :return: parameter's shape @@ -190,6 +195,7 @@ def get(self, parameter_name): def set(self, parameter_name, value): """ Set parameter by parameter name & matrix. + :param parameter_name: parameter name :type parameter_name: basestring :param value: parameter matrix diff --git a/python/paddle/v2/reader/__init__.py b/python/paddle/v2/reader/__init__.py index 7373dc461b1d3..3b059735a924d 100644 --- a/python/paddle/v2/reader/__init__.py +++ b/python/paddle/v2/reader/__init__.py @@ -11,15 +11,64 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +""" +At training and testing time, PaddlePaddle programs need to read data. To ease +the users' work to write data reading code, we define that -# It would be too lengthy to require our users to prefix decorators with `decorator`. -# For example, we want the following line -# -# r = paddle.reader.decorator.bufferd(paddle.reader.creator.text("hello.txt")) -# -# to be a shorter version: -# -# r = paddle.reader.buffered(paddle.reader.creator.text("hello.txt")) +- A *reader* is a function that reads data (from file, network, random number + generator, etc) and yields data items. +- A *reader creator* is a function that returns a reader function. +- A *reader decorator* is a function, which accepts one or more readers, and + returns a reader. +- A *batch reader* is a function that reads data (from *reader*, file, network, + random number generator, etc) and yields a batch of data items. + +##################### +Data Reader Interface +##################### + +Indeed, *data reader* doesn't have to be a function that reads and yields data +items. It can be any function with no parameter that creates a iterable +(anything can be used in :code:`for x in iterable`)\: + +.. code-block:: python + + iterable = data_reader() + +Element produced from the iterable should be a **single** entry of data, +**not** a mini batch. That entry of data could be a single item, or a tuple of +items. +Item should be of `supported type `_ (e.g., numpy 1d +array of float32, int, list of int) + +An example implementation for single item data reader creator: + +.. code-block:: python + + def reader_creator_random_image(width, height): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height) + return reader + +An example implementation for multiple item data reader creator: + +.. code-block:: python + + def reader_creator_random_image_and_label(width, height, label): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height), label + return reader + + +TODO(yuyang18): Should we add whole design doc here? +""" + +import decorator from decorator import * import creator + +__all__ = decorator.__all__ + ['creator'] diff --git a/python/paddle/v2/reader/creator.py b/python/paddle/v2/reader/creator.py index 5a91bb0b8ef6d..07142056f872d 100644 --- a/python/paddle/v2/reader/creator.py +++ b/python/paddle/v2/reader/creator.py @@ -11,6 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +""" +Creator package contains some simple reader creator, which could be used in user +program. +""" __all__ = ['np_array', 'text_file'] @@ -38,7 +42,7 @@ def reader(): def text_file(path): """ Creates a data reader that outputs text line by line from given text file. - Trailing new line ('\n') of each line will be removed. + Trailing new line ('\\\\n') of each line will be removed. :path: path of the text file. :returns: data reader of text file diff --git a/python/paddle/v2/reader/decorator.py b/python/paddle/v2/reader/decorator.py index b7657e27764f0..4012499724723 100644 --- a/python/paddle/v2/reader/decorator.py +++ b/python/paddle/v2/reader/decorator.py @@ -12,25 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -__all__ = [ - 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', - 'ComposeNotAligned', 'batched', 'firstn' -] - import itertools import random from Queue import Queue from threading import Thread +__all__ = [ + 'map_readers', 'buffered', 'compose', 'chain', 'shuffle', + 'ComposeNotAligned', 'batched', 'firstn' +] + def map_readers(func, *readers): """ Creates a data reader that outputs return value of function using output of each data readers as arguments. - :param func: function to use. - :param *readers: readers whose outputs will be used as arguments of func. - :returns: the created data reader. + :param func: function to use. The type of func should be (Sample) => Sample + :type: callable + :param readers: readers whose outputs will be used as arguments of func. + :return: the created data reader. + :rtype: callable """ def reader(): @@ -45,16 +47,19 @@ def reader(): def shuffle(reader, buf_size): """ - Creates a data reader whose data output is suffled. + Creates a data reader whose data output is shuffled. Output from the iterator that created by original reader will be buffered into shuffle buffer, and then shuffled. The size of shuffle buffer is determined by argument buf_size. :param reader: the original reader whose output will be shuffled. + :type reader: callable :param buf_size: shuffle buffer size. + :type buf_size: int - :returns:the new reader whose output is shuffled. + :return: the new reader whose output is shuffled. + :rtype: callable """ def data_reader(): @@ -88,7 +93,8 @@ def chain(*readers): [0, 0, 0, 1, 1, 1, 2, 2, 2] :param readers: input readers. - :returns: the new data reader. + :return: the new data reader. + :rtype: callable """ def reader(): @@ -115,12 +121,13 @@ def compose(*readers, **kwargs): The composed reader will output: (1, 2, 3, 4, 5) - :*readers: readers that will be composed together. - :check_alignment: if True, will check if input readers are aligned + :param readers: readers that will be composed together. + :param check_alignment: if True, will check if input readers are aligned correctly. If False, will not check alignment and trailing outputs will be discarded. Defaults to True. + :type check_alignment: bool - :returns: the new data reader. + :return: the new data reader. :raises ComposeNotAligned: outputs of readers are not aligned. Will not raise when check_alignment is set to False. @@ -161,7 +168,9 @@ def buffered(reader, size): as the buffer is not empty. :param reader: the data reader to read from. + :type reader: callable :param size: max buffer size. + :type size: int :returns: the buffered data reader. """ @@ -196,9 +205,13 @@ def data_reader(): def batched(reader, batch_size): """ Create a batched reader. + :param reader: the data reader to read from. - :param batch_size: batch_size + :type reader: callable + :param batch_size: size of each mini-batch + :type batch_size: int :return: the batched reader. + :rtype: callable """ def batched_reader(): @@ -218,6 +231,13 @@ def batched_reader(): def firstn(reader, n): """ Limit the max number of samples that reader could return. + + :param reader: the data reader to read from. + :type reader: callable + :param n: the max number of samples that return. + :type n: int + :return: the decorated reader. + :rtype: callable """ # TODO(yuyang18): Check if just drop the reader, could clean the opened diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 8bcdd122b30bd..7b70672136708 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -9,6 +9,10 @@ from . import parameters as v2_parameters __all__ = ['SGD'] +""" +Trainer package +TODO(yuyang18): Complete comments. +""" def default_event_handler(event): @@ -22,14 +26,20 @@ def default_event_handler(event): pass -class SGD(): - def __init__(self, cost, parameters, update_equation): - """ - Simple SGD Trainer. +class SGD(object): + """ + Simple SGD Trainer. + TODO(yuyang18): Complete comments + + :param update_equation: The optimizer object. + :type update_equation: paddle.v2.optimizer.Optimizer + :param cost: Target cost that neural network should be optimized. + :type cost: paddle.v2.config_base.Layer + :param parameters: The parameters dictionary. + :type parameters: paddle.v2.parameters.Parameters + """ - :param update_equation: The optimizer object. - :type update_equation: v2_optimizer.Optimizer - """ + def __init__(self, cost, parameters, update_equation): if not isinstance(parameters, v2_parameters.Parameters): raise TypeError('parameters should be parameters') @@ -56,8 +66,6 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): Training method. Will train num_passes of input data. :param reader: - :param topology: Network Topology, use one or more Layers to represent it. - :param parameters: The parameter pools. :param num_passes: The total train passes. :param event_handler: Event handler. A method will be invoked when event occurred. From 98522dcb3390ecbccc4c544e0c9c57b8d3e4b2c9 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Sun, 5 Mar 2017 21:26:44 +0800 Subject: [PATCH 124/153] optimizer wmt14 dataset --- demo/seqToseq/api_train_v2.py | 161 +++++++++++++++----------- demo/seqToseq/seqToseq_net_v2.py | 92 --------------- python/paddle/v2/dataset/wmt14.py | 185 +++++++++++++----------------- 3 files changed, 174 insertions(+), 264 deletions(-) delete mode 100644 demo/seqToseq/seqToseq_net_v2.py diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index a5f59ec379738..f100ef80cb156 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -1,76 +1,106 @@ -import os - import paddle.v2 as paddle -from seqToseq_net_v2 import seqToseq_net_v2 - -# Data Definiation. -# TODO:This code should be merged to dataset package. -data_dir = "./data/pre-wmt14" -src_lang_dict = os.path.join(data_dir, 'src.dict') -trg_lang_dict = os.path.join(data_dir, 'trg.dict') - -source_dict_dim = len(open(src_lang_dict, "r").readlines()) -target_dict_dim = len(open(trg_lang_dict, "r").readlines()) - - -def read_to_dict(dict_path): - with open(dict_path, "r") as fin: - out_dict = { - line.strip(): line_count - for line_count, line in enumerate(fin) - } - return out_dict - - -src_dict = read_to_dict(src_lang_dict) -trg_dict = read_to_dict(trg_lang_dict) - -train_list = os.path.join(data_dir, 'train.list') -test_list = os.path.join(data_dir, 'test.list') - -UNK_IDX = 2 -START = "" -END = "" - -def _get_ids(s, dictionary): - words = s.strip().split() - return [dictionary[START]] + \ - [dictionary.get(w, UNK_IDX) for w in words] + \ - [dictionary[END]] - - -def train_reader(file_name): - def reader(): - with open(file_name, 'r') as f: - for line_count, line in enumerate(f): - line_split = line.strip().split('\t') - if len(line_split) != 2: - continue - src_seq = line_split[0] # one source sequence - src_ids = _get_ids(src_seq, src_dict) - - trg_seq = line_split[1] # one target sequence - trg_words = trg_seq.split() - trg_ids = [trg_dict.get(w, UNK_IDX) for w in trg_words] - - # remove sequence whose length > 80 in training mode - if len(src_ids) > 80 or len(trg_ids) > 80: - continue - trg_ids_next = trg_ids + [trg_dict[END]] - trg_ids = [trg_dict[START]] + trg_ids - - yield src_ids, trg_ids, trg_ids_next - - return reader +def seqToseq_net(source_dict_dim, target_dict_dim): + ### Network Architecture + word_vector_dim = 512 # dimension of word vector + decoder_size = 512 # dimension of hidden unit in GRU Decoder network + encoder_size = 512 # dimension of hidden unit in GRU Encoder network + + #### Encoder + src_word_id = paddle.layer.data( + name='source_language_word', + type=paddle.data_type.integer_value_sequence(source_dict_dim)) + src_embedding = paddle.layer.embedding( + input=src_word_id, + size=word_vector_dim, + param_attr=paddle.attr.ParamAttr(name='_source_language_embedding')) + src_forward = paddle.networks.simple_gru( + input=src_embedding, size=encoder_size) + src_backward = paddle.networks.simple_gru( + input=src_embedding, size=encoder_size, reverse=True) + encoded_vector = paddle.layer.concat(input=[src_forward, src_backward]) + + #### Decoder + with paddle.layer.mixed(size=decoder_size) as encoded_proj: + encoded_proj += paddle.layer.full_matrix_projection( + input=encoded_vector) + + backward_first = paddle.layer.first_seq(input=src_backward) + + with paddle.layer.mixed( + size=decoder_size, act=paddle.activation.Tanh()) as decoder_boot: + decoder_boot += paddle.layer.full_matrix_projection( + input=backward_first) + + def gru_decoder_with_attention(enc_vec, enc_proj, current_word): + + decoder_mem = paddle.layer.memory( + name='gru_decoder', size=decoder_size, boot_layer=decoder_boot) + + context = paddle.networks.simple_attention( + encoded_sequence=enc_vec, + encoded_proj=enc_proj, + decoder_state=decoder_mem) + + with paddle.layer.mixed(size=decoder_size * 3) as decoder_inputs: + decoder_inputs += paddle.layer.full_matrix_projection(input=context) + decoder_inputs += paddle.layer.full_matrix_projection( + input=current_word) + + gru_step = paddle.layer.gru_step( + name='gru_decoder', + input=decoder_inputs, + output_mem=decoder_mem, + size=decoder_size) + + with paddle.layer.mixed( + size=target_dict_dim, + bias_attr=True, + act=paddle.activation.Softmax()) as out: + out += paddle.layer.full_matrix_projection(input=gru_step) + return out + + decoder_group_name = "decoder_group" + group_input1 = paddle.layer.StaticInputV2(input=encoded_vector, is_seq=True) + group_input2 = paddle.layer.StaticInputV2(input=encoded_proj, is_seq=True) + group_inputs = [group_input1, group_input2] + + trg_embedding = paddle.layer.embedding( + input=paddle.layer.data( + name='target_language_word', + type=paddle.data_type.integer_value_sequence(target_dict_dim)), + size=word_vector_dim, + param_attr=paddle.attr.ParamAttr(name='_target_language_embedding')) + group_inputs.append(trg_embedding) + + # For decoder equipped with attention mechanism, in training, + # target embeding (the groudtruth) is the data input, + # while encoded source sequence is accessed to as an unbounded memory. + # Here, the StaticInput defines a read-only memory + # for the recurrent_group. + decoder = paddle.layer.recurrent_group( + name=decoder_group_name, + step=gru_decoder_with_attention, + input=group_inputs) + + lbl = paddle.layer.data( + name='target_language_next_word', + type=paddle.data_type.integer_value_sequence(target_dict_dim)) + cost = paddle.layer.classification_cost(input=decoder, label=lbl) + + return cost def main(): paddle.init(use_gpu=False, trainer_count=1) + # source and target dict dim. + dict_size = 30000 + source_dict_dim = target_dict_dim = dict_size + # define network topology - cost = seqToseq_net_v2(source_dict_dim, target_dict_dim) + cost = seqToseq_net(source_dict_dim, target_dict_dim) parameters = paddle.parameters.create(cost) # define optimize method and trainer @@ -85,10 +115,9 @@ def main(): 'target_language_word': 1, 'target_language_next_word': 2 } - wmt14_reader = paddle.reader.batched( paddle.reader.shuffle( - train_reader("data/pre-wmt14/train/train"), buf_size=8192), + paddle.dataset.wmt14.train(dict_size=dict_size), buf_size=8192), batch_size=5) # define event_handler callback diff --git a/demo/seqToseq/seqToseq_net_v2.py b/demo/seqToseq/seqToseq_net_v2.py deleted file mode 100644 index 058a6789d7094..0000000000000 --- a/demo/seqToseq/seqToseq_net_v2.py +++ /dev/null @@ -1,92 +0,0 @@ -import paddle.v2 as paddle - - -def seqToseq_net_v2(source_dict_dim, target_dict_dim): - ### Network Architecture - word_vector_dim = 512 # dimension of word vector - decoder_size = 512 # dimension of hidden unit in GRU Decoder network - encoder_size = 512 # dimension of hidden unit in GRU Encoder network - - #### Encoder - src_word_id = paddle.layer.data( - name='source_language_word', - type=paddle.data_type.integer_value_sequence(source_dict_dim)) - src_embedding = paddle.layer.embedding( - input=src_word_id, - size=word_vector_dim, - param_attr=paddle.attr.ParamAttr(name='_source_language_embedding')) - src_forward = paddle.networks.simple_gru( - input=src_embedding, size=encoder_size) - src_backward = paddle.networks.simple_gru( - input=src_embedding, size=encoder_size, reverse=True) - encoded_vector = paddle.layer.concat(input=[src_forward, src_backward]) - - #### Decoder - with paddle.layer.mixed(size=decoder_size) as encoded_proj: - encoded_proj += paddle.layer.full_matrix_projection( - input=encoded_vector) - - backward_first = paddle.layer.first_seq(input=src_backward) - - with paddle.layer.mixed( - size=decoder_size, act=paddle.activation.Tanh()) as decoder_boot: - decoder_boot += paddle.layer.full_matrix_projection( - input=backward_first) - - def gru_decoder_with_attention(enc_vec, enc_proj, current_word): - - decoder_mem = paddle.layer.memory( - name='gru_decoder', size=decoder_size, boot_layer=decoder_boot) - - context = paddle.networks.simple_attention( - encoded_sequence=enc_vec, - encoded_proj=enc_proj, - decoder_state=decoder_mem) - - with paddle.layer.mixed(size=decoder_size * 3) as decoder_inputs: - decoder_inputs += paddle.layer.full_matrix_projection(input=context) - decoder_inputs += paddle.layer.full_matrix_projection( - input=current_word) - - gru_step = paddle.layer.gru_step( - name='gru_decoder', - input=decoder_inputs, - output_mem=decoder_mem, - size=decoder_size) - - with paddle.layer.mixed( - size=target_dict_dim, - bias_attr=True, - act=paddle.activation.Softmax()) as out: - out += paddle.layer.full_matrix_projection(input=gru_step) - return out - - decoder_group_name = "decoder_group" - group_input1 = paddle.layer.StaticInputV2(input=encoded_vector, is_seq=True) - group_input2 = paddle.layer.StaticInputV2(input=encoded_proj, is_seq=True) - group_inputs = [group_input1, group_input2] - - trg_embedding = paddle.layer.embedding( - input=paddle.layer.data( - name='target_language_word', - type=paddle.data_type.integer_value_sequence(target_dict_dim)), - size=word_vector_dim, - param_attr=paddle.attr.ParamAttr(name='_target_language_embedding')) - group_inputs.append(trg_embedding) - - # For decoder equipped with attention mechanism, in training, - # target embeding (the groudtruth) is the data input, - # while encoded source sequence is accessed to as an unbounded memory. - # Here, the StaticInput defines a read-only memory - # for the recurrent_group. - decoder = paddle.layer.recurrent_group( - name=decoder_group_name, - step=gru_decoder_with_attention, - input=group_inputs) - - lbl = paddle.layer.data( - name='target_language_next_word', - type=paddle.data_type.integer_value_sequence(target_dict_dim)) - cost = paddle.layer.classification_cost(input=decoder, label=lbl) - - return cost diff --git a/python/paddle/v2/dataset/wmt14.py b/python/paddle/v2/dataset/wmt14.py index 9904848b5d3ef..5a9dd4ca8099b 100644 --- a/python/paddle/v2/dataset/wmt14.py +++ b/python/paddle/v2/dataset/wmt14.py @@ -14,129 +14,102 @@ """ wmt14 dataset """ -import paddle.v2.dataset.common -import tarfile +import os import os.path -import itertools +import tarfile + +import paddle.v2.dataset.common +from wmt14_util import SeqToSeqDatasetCreater __all__ = ['train', 'test', 'build_dict'] URL_DEV_TEST = 'http://www-lium.univ-lemans.fr/~schwenk/cslm_joint_paper/data/dev+test.tgz' MD5_DEV_TEST = '7d7897317ddd8ba0ae5c5fa7248d3ff5' -URL_TRAIN = 'http://localhost:8000/train.tgz' -MD5_TRAIN = '72de99da2830ea5a3a2c4eb36092bbc7' - - -def word_count(f, word_freq=None): - add = paddle.v2.dataset.common.dict_add - if word_freq == None: - word_freq = {} - - for l in f: - for w in l.strip().split(): - add(word_freq, w) - add(word_freq, '') - add(word_freq, '') - - return word_freq - - -def get_word_dix(word_freq): - TYPO_FREQ = 50 - word_freq = filter(lambda x: x[1] > TYPO_FREQ, word_freq.items()) - word_freq_sorted = sorted(word_freq, key=lambda x: (-x[1], x[0])) - words, _ = list(zip(*word_freq_sorted)) - word_idx = dict(zip(words, xrange(len(words)))) - word_idx[''] = len(words) - return word_idx - - -def get_word_freq(train, dev): - word_freq = word_count(train, word_count(dev)) - if '' in word_freq: - # remove for now, since we will set it as last index - del word_freq[''] - return word_freq - - -def build_dict(): - base_dir = './wmt14-data' - train_en_filename = base_dir + '/train/train.en' - train_fr_filename = base_dir + '/train/train.fr' - dev_en_filename = base_dir + '/dev/ntst1213.en' - dev_fr_filename = base_dir + '/dev/ntst1213.fr' - - if not os.path.exists(train_en_filename) or not os.path.exists( - train_fr_filename): +URL_TRAIN = 'http://localhost:8989/wmt14.tgz' +MD5_TRAIN = '7373473f86016f1f48037c9c340a2d5b' + +START = "" +END = "" +UNK = "" +UNK_IDX = 2 + +DEFAULT_DATA_DIR = "./data" +ORIGIN_DATA_DIR = "wmt14" +INNER_DATA_DIR = "pre-wmt14" +SRC_DICT = INNER_DATA_DIR + "/src.dict" +TRG_DICT = INNER_DATA_DIR + "/trg.dict" +TRAIN_FILE = INNER_DATA_DIR + "/train/train" + + +def __process_data__(data_path, dict_size=None): + downloaded_data = os.path.join(data_path, ORIGIN_DATA_DIR) + if not os.path.exists(downloaded_data): + # 1. download and extract tgz. with tarfile.open( paddle.v2.dataset.common.download(URL_TRAIN, 'wmt14', MD5_TRAIN)) as tf: - tf.extractall(base_dir) - - if not os.path.exists(dev_en_filename) or not os.path.exists( - dev_fr_filename): - with tarfile.open( - paddle.v2.dataset.common.download(URL_DEV_TEST, 'wmt14', - MD5_DEV_TEST)) as tf: - tf.extractall(base_dir) - - f_en = open(train_en_filename) - f_fr = open(train_fr_filename) - f_en_dev = open(dev_en_filename) - f_fr_dev = open(dev_fr_filename) - - word_freq_en = get_word_freq(f_en, f_en_dev) - word_freq_fr = get_word_freq(f_fr, f_fr_dev) - - f_en.close() - f_fr.close() - f_en_dev.close() - f_fr_dev.close() - - return get_word_dix(word_freq_en), get_word_dix(word_freq_fr) - - -def reader_creator(directory, path_en, path_fr, URL, MD5, dict_en, dict_fr): - def reader(): - if not os.path.exists(path_en) or not os.path.exists(path_fr): - with tarfile.open( - paddle.v2.dataset.common.download(URL, 'wmt14', MD5)) as tf: - tf.extractall(directory) - - f_en = open(path_en) - f_fr = open(path_fr) - UNK_en = dict_en[''] - UNK_fr = dict_fr[''] - - for en, fr in itertools.izip(f_en, f_fr): - src_ids = [dict_en.get(w, UNK_en) for w in en.strip().split()] - tar_ids = [ - dict_fr.get(w, UNK_fr) - for w in [''] + fr.strip().split() + [''] + tf.extractall(data_path) + + # 2. process data file to intermediate format. + processed_data = os.path.join(data_path, INNER_DATA_DIR) + if not os.path.exists(processed_data): + dict_size = dict_size or -1 + data_creator = SeqToSeqDatasetCreater(downloaded_data, processed_data) + data_creator.create_dataset(dict_size, mergeDict=False) + + +def __read_to_dict__(dict_path, count): + with open(dict_path, "r") as fin: + out_dict = dict() + for line_count, line in enumerate(fin): + if line_count <= count: + out_dict[line.strip()] = line_count + else: + break + return out_dict + + +def __reader__(file_name, src_dict, trg_dict): + with open(file_name, 'r') as f: + for line_count, line in enumerate(f): + line_split = line.strip().split('\t') + if len(line_split) != 2: + continue + src_seq = line_split[0] # one source sequence + src_words = src_seq.split() + src_ids = [ + src_dict.get(w, UNK_IDX) for w in [START] + src_words + [END] ] + trg_seq = line_split[1] # one target sequence + trg_words = trg_seq.split() + trg_ids = [trg_dict.get(w, UNK_IDX) for w in trg_words] + # remove sequence whose length > 80 in training mode - if len(src_ids) == 0 or len(tar_ids) <= 1 or len( - src_ids) > 80 or len(tar_ids) > 80: + if len(src_ids) > 80 or len(trg_ids) > 80: continue + trg_ids_next = trg_ids + [trg_dict[END]] + trg_ids = [trg_dict[START]] + trg_ids + + yield src_ids, trg_ids, trg_ids_next - yield src_ids, tar_ids[:-1], tar_ids[1:] - f_en.close() - f_fr.close() +def train(data_dir=None, dict_size=None): + data_dir = data_dir or DEFAULT_DATA_DIR + __process_data__(data_dir, dict_size) + src_lang_dict = os.path.join(data_dir, SRC_DICT) + trg_lang_dict = os.path.join(data_dir, TRG_DICT) + train_file_name = os.path.join(data_dir, TRAIN_FILE) - return reader + default_dict_size = len(open(src_lang_dict, "r").readlines()) + if dict_size > default_dict_size: + raise ValueError("dict_dim should not be larger then the " + "length of word dict") -def train(dict_en, dict_fr): - directory = './wmt14-data' - return reader_creator(directory, directory + '/train/train.en', - directory + '/train/train.fr', URL_TRAIN, MD5_TRAIN, - dict_en, dict_fr) + real_dict_dim = dict_size or default_dict_size + src_dict = __read_to_dict__(src_lang_dict, real_dict_dim) + trg_dict = __read_to_dict__(trg_lang_dict, real_dict_dim) -def test(dict_en, dict_fr): - directory = './wmt14-data' - return reader_creator(directory, directory + '/dev/ntst1213.en', - directory + '/dev/ntst1213.fr', URL_DEV_TEST, - MD5_DEV_TEST, dict_en, dict_fr) + return lambda: __reader__(train_file_name, src_dict, trg_dict) From f6f444ff3da1ab16d4b770d9c98615095f842715 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Sun, 5 Mar 2017 21:55:46 +0800 Subject: [PATCH 125/153] optimize code --- demo/seqToseq/api_train_v2.py | 2 +- demo/seqToseq/preprocess.py | 160 +--------------------------------- 2 files changed, 2 insertions(+), 160 deletions(-) diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index f100ef80cb156..177fd26d681d1 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -115,7 +115,7 @@ def main(): 'target_language_word': 1, 'target_language_next_word': 2 } - wmt14_reader = paddle.reader.batched( + wmt14_reader = paddle.batch( paddle.reader.shuffle( paddle.dataset.wmt14.train(dict_size=dict_size), buf_size=8192), batch_size=5) diff --git a/demo/seqToseq/preprocess.py b/demo/seqToseq/preprocess.py index 03f371331a075..afa7bd5e0f419 100755 --- a/demo/seqToseq/preprocess.py +++ b/demo/seqToseq/preprocess.py @@ -23,167 +23,9 @@ -m --mergeDict merge source and target dictionary """ import os -import sys - -import string from optparse import OptionParser -from paddle.utils.preprocess_util import save_list, DatasetCreater - - -class SeqToSeqDatasetCreater(DatasetCreater): - """ - A class to process data for sequence to sequence application. - """ - - def __init__(self, data_path, output_path): - """ - data_path: the path to store the train data, test data and gen data - output_path: the path to store the processed dataset - """ - DatasetCreater.__init__(self, data_path) - self.gen_dir_name = 'gen' - self.gen_list_name = 'gen.list' - self.output_path = output_path - - def concat_file(self, file_path, file1, file2, output_path, output): - """ - Concat file1 and file2 to be one output file - The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 - file_path: the path to store file1 and file2 - output_path: the path to store output file - """ - file1 = os.path.join(file_path, file1) - file2 = os.path.join(file_path, file2) - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) - - def cat_file(self, dir_path, suffix, output_path, output): - """ - Cat all the files in dir_path with suffix to be one output file - dir_path: the base directory to store input file - suffix: suffix of file name - output_path: the path to store output file - """ - cmd = 'cat ' - file_list = os.listdir(dir_path) - file_list.sort() - for file in file_list: - if file.endswith(suffix): - cmd += os.path.join(dir_path, file) + ' ' - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system(cmd + '> ' + output) - - def build_dict(self, file_path, dict_path, dict_size=-1): - """ - Create the dictionary for the file, Note that - 1. Valid characters include all printable characters - 2. There is distinction between uppercase and lowercase letters - 3. There is 3 special token: - : the start of a sequence - : the end of a sequence - : a word not included in dictionary - file_path: the path to store file - dict_path: the path to store dictionary - dict_size: word count of dictionary - if is -1, dictionary will contains all the words in file - """ - if not os.path.exists(dict_path): - dictory = dict() - with open(file_path, "r") as fdata: - for line in fdata: - line = line.split('\t') - for line_split in line: - words = line_split.strip().split() - for word in words: - if word not in dictory: - dictory[word] = 1 - else: - dictory[word] += 1 - output = open(dict_path, "w+") - output.write('\n\n\n') - count = 3 - for key, value in sorted( - dictory.items(), key=lambda d: d[1], reverse=True): - output.write(key + "\n") - count += 1 - if count == dict_size: - break - self.dict_size = count - - def create_dataset(self, - dict_size=-1, - mergeDict=False, - suffixes=['.src', '.trg']): - """ - Create seqToseq dataset - """ - # dataset_list and dir_list has one-to-one relationship - train_dataset = os.path.join(self.data_path, self.train_dir_name) - test_dataset = os.path.join(self.data_path, self.test_dir_name) - gen_dataset = os.path.join(self.data_path, self.gen_dir_name) - dataset_list = [train_dataset, test_dataset, gen_dataset] - - train_dir = os.path.join(self.output_path, self.train_dir_name) - test_dir = os.path.join(self.output_path, self.test_dir_name) - gen_dir = os.path.join(self.output_path, self.gen_dir_name) - dir_list = [train_dir, test_dir, gen_dir] - - # create directory - for dir in dir_list: - if not os.path.exists(dir): - os.mkdir(dir) - - # checkout dataset should be parallel corpora - suffix_len = len(suffixes[0]) - for dataset in dataset_list: - file_list = os.listdir(dataset) - if len(file_list) % 2 == 1: - raise RuntimeError("dataset should be parallel corpora") - file_list.sort() - for i in range(0, len(file_list), 2): - if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: - raise RuntimeError( - "source and target file name should be equal") - - # cat all the files with the same suffix in dataset - for suffix in suffixes: - for dataset in dataset_list: - outname = os.path.basename(dataset) + suffix - self.cat_file(dataset, suffix, dataset, outname) - - # concat parallel corpora and create file.list - print 'concat parallel corpora for dataset' - id = 0 - list = ['train.list', 'test.list', 'gen.list'] - for dataset in dataset_list: - outname = os.path.basename(dataset) - self.concat_file(dataset, outname + suffixes[0], - outname + suffixes[1], dir_list[id], outname) - save_list([os.path.join(dir_list[id], outname)], - os.path.join(self.output_path, list[id])) - id += 1 - # build dictionary for train data - dict = ['src.dict', 'trg.dict'] - dict_path = [ - os.path.join(self.output_path, dict[0]), - os.path.join(self.output_path, dict[1]) - ] - if mergeDict: - outname = os.path.join(train_dir, train_dataset.split('/')[-1]) - print 'build src dictionary for train data' - self.build_dict(outname, dict_path[0], dict_size) - print 'build trg dictionary for train data' - os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) - else: - outname = os.path.join(train_dataset, self.train_dir_name) - for id in range(0, 2): - suffix = suffixes[id] - print 'build ' + suffix[1:] + ' dictionary for train data' - self.build_dict(outname + suffix, dict_path[id], dict_size) - print 'dictionary size is', self.dict_size +from paddle.v2.dataset.wmt14_util import SeqToSeqDatasetCreater def main(): From 75f2e54c385a979252834bde293b6efd1c984f7c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 10:48:14 +0800 Subject: [PATCH 126/153] Refine API generation file. --- doc/api/v2/data.rst | 5 +++++ doc/api/v2/model_configs.rst | 6 +++++- doc/api/v2/run_logic.rst | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/api/v2/data.rst b/doc/api/v2/data.rst index d2723a81e214b..1c0a202a8c043 100644 --- a/doc/api/v2/data.rst +++ b/doc/api/v2/data.rst @@ -1,3 +1,8 @@ +================ +Data Related API +================ + + ######### DataTypes ######### diff --git a/doc/api/v2/model_configs.rst b/doc/api/v2/model_configs.rst index 52e2dcd53055c..e9cd3d5bf7b0e 100644 --- a/doc/api/v2/model_configs.rst +++ b/doc/api/v2/model_configs.rst @@ -1,3 +1,7 @@ +######################### +Configuration Related API +######################### + ====== Layers ====== @@ -38,5 +42,5 @@ Networks Optimizers ========== -.. automodule:: paddle.v2.optimizers +.. automodule:: paddle.v2.optimizer :members: diff --git a/doc/api/v2/run_logic.rst b/doc/api/v2/run_logic.rst index 522093f8aeedb..904d45966dfc1 100644 --- a/doc/api/v2/run_logic.rst +++ b/doc/api/v2/run_logic.rst @@ -1,3 +1,7 @@ +########### +Trainer API +########### + ========== Parameters ========== From 06915d0a0507ba25e46917e4e622fcbbe3cd2668 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 6 Mar 2017 10:53:16 +0800 Subject: [PATCH 127/153] add wmt14_util.py and a small dataset on bos for test --- python/paddle/v2/dataset/wmt14.py | 3 +- python/paddle/v2/dataset/wmt14_util.py | 172 +++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/dataset/wmt14_util.py diff --git a/python/paddle/v2/dataset/wmt14.py b/python/paddle/v2/dataset/wmt14.py index 5a9dd4ca8099b..254f07c8dd391 100644 --- a/python/paddle/v2/dataset/wmt14.py +++ b/python/paddle/v2/dataset/wmt14.py @@ -25,7 +25,8 @@ URL_DEV_TEST = 'http://www-lium.univ-lemans.fr/~schwenk/cslm_joint_paper/data/dev+test.tgz' MD5_DEV_TEST = '7d7897317ddd8ba0ae5c5fa7248d3ff5' -URL_TRAIN = 'http://localhost:8989/wmt14.tgz' +# this is a small set of data for test. The original data is too large and will be add later. +URL_TRAIN = 'http://paddlepaddle.bj.bcebos.com/demo/wmt_shrinked_data/wmt14.tgz' MD5_TRAIN = '7373473f86016f1f48037c9c340a2d5b' START = "" diff --git a/python/paddle/v2/dataset/wmt14_util.py b/python/paddle/v2/dataset/wmt14_util.py new file mode 100644 index 0000000000000..0d72389164337 --- /dev/null +++ b/python/paddle/v2/dataset/wmt14_util.py @@ -0,0 +1,172 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os + +from paddle.utils.preprocess_util import save_list, DatasetCreater + + +class SeqToSeqDatasetCreater(DatasetCreater): + """ + A class to process data for sequence to sequence application. + """ + + def __init__(self, data_path, output_path): + """ + data_path: the path to store the train data, test data and gen data + output_path: the path to store the processed dataset + """ + DatasetCreater.__init__(self, data_path) + self.gen_dir_name = 'gen' + self.gen_list_name = 'gen.list' + self.output_path = output_path + + def concat_file(self, file_path, file1, file2, output_path, output): + """ + Concat file1 and file2 to be one output file + The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 + file_path: the path to store file1 and file2 + output_path: the path to store output file + """ + file1 = os.path.join(file_path, file1) + file2 = os.path.join(file_path, file2) + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) + + def cat_file(self, dir_path, suffix, output_path, output): + """ + Cat all the files in dir_path with suffix to be one output file + dir_path: the base directory to store input file + suffix: suffix of file name + output_path: the path to store output file + """ + cmd = 'cat ' + file_list = os.listdir(dir_path) + file_list.sort() + for file in file_list: + if file.endswith(suffix): + cmd += os.path.join(dir_path, file) + ' ' + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system(cmd + '> ' + output) + + def build_dict(self, file_path, dict_path, dict_size=-1): + """ + Create the dictionary for the file, Note that + 1. Valid characters include all printable characters + 2. There is distinction between uppercase and lowercase letters + 3. There is 3 special token: + : the start of a sequence + : the end of a sequence + : a word not included in dictionary + file_path: the path to store file + dict_path: the path to store dictionary + dict_size: word count of dictionary + if is -1, dictionary will contains all the words in file + """ + if not os.path.exists(dict_path): + dictory = dict() + with open(file_path, "r") as fdata: + for line in fdata: + line = line.split('\t') + for line_split in line: + words = line_split.strip().split() + for word in words: + if word not in dictory: + dictory[word] = 1 + else: + dictory[word] += 1 + output = open(dict_path, "w+") + output.write('\n\n\n') + count = 3 + for key, value in sorted( + dictory.items(), key=lambda d: d[1], reverse=True): + output.write(key + "\n") + count += 1 + if count == dict_size: + break + self.dict_size = count + + def create_dataset(self, + dict_size=-1, + mergeDict=False, + suffixes=['.src', '.trg']): + """ + Create seqToseq dataset + """ + # dataset_list and dir_list has one-to-one relationship + train_dataset = os.path.join(self.data_path, self.train_dir_name) + test_dataset = os.path.join(self.data_path, self.test_dir_name) + gen_dataset = os.path.join(self.data_path, self.gen_dir_name) + dataset_list = [train_dataset, test_dataset, gen_dataset] + + train_dir = os.path.join(self.output_path, self.train_dir_name) + test_dir = os.path.join(self.output_path, self.test_dir_name) + gen_dir = os.path.join(self.output_path, self.gen_dir_name) + dir_list = [train_dir, test_dir, gen_dir] + + # create directory + for dir in dir_list: + if not os.path.exists(dir): + os.makedirs(dir) + + # checkout dataset should be parallel corpora + suffix_len = len(suffixes[0]) + for dataset in dataset_list: + file_list = os.listdir(dataset) + if len(file_list) % 2 == 1: + raise RuntimeError("dataset should be parallel corpora") + file_list.sort() + for i in range(0, len(file_list), 2): + if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: + raise RuntimeError( + "source and target file name should be equal") + + # cat all the files with the same suffix in dataset + for suffix in suffixes: + for dataset in dataset_list: + outname = os.path.basename(dataset) + suffix + self.cat_file(dataset, suffix, dataset, outname) + + # concat parallel corpora and create file.list + print 'concat parallel corpora for dataset' + id = 0 + list = ['train.list', 'test.list', 'gen.list'] + for dataset in dataset_list: + outname = os.path.basename(dataset) + self.concat_file(dataset, outname + suffixes[0], + outname + suffixes[1], dir_list[id], outname) + save_list([os.path.join(dir_list[id], outname)], + os.path.join(self.output_path, list[id])) + id += 1 + + # build dictionary for train data + dict = ['src.dict', 'trg.dict'] + dict_path = [ + os.path.join(self.output_path, dict[0]), + os.path.join(self.output_path, dict[1]) + ] + if mergeDict: + outname = os.path.join(train_dir, train_dataset.split('/')[-1]) + print 'build src dictionary for train data' + self.build_dict(outname, dict_path[0], dict_size) + print 'build trg dictionary for train data' + os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) + else: + outname = os.path.join(train_dataset, self.train_dir_name) + for id in range(0, 2): + suffix = suffixes[id] + print 'build ' + suffix[1:] + ' dictionary for train data' + self.build_dict(outname + suffix, dict_path[id], dict_size) + print 'dictionary size is', self.dict_size From 977fcef7b5c4985db61cd30a7a4c864de0bd1667 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 11:22:33 +0800 Subject: [PATCH 128/153] Fix unittest --- python/paddle/v2/tests/test_topology.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/paddle/v2/tests/test_topology.py b/python/paddle/v2/tests/test_topology.py index 1bf55a5bc68df..5c6dbcdb4f49b 100644 --- a/python/paddle/v2/tests/test_topology.py +++ b/python/paddle/v2/tests/test_topology.py @@ -16,6 +16,7 @@ import paddle.v2.topology as topology import paddle.v2.data_type as data_type import paddle.trainer_config_helpers as conf_helps +import paddle.trainer.PyDataProvider2 as pydp2 class TestTopology(unittest.TestCase): @@ -35,13 +36,13 @@ def test_data_type(self): pixel_data_type = filter(lambda type: type[0] == "pixel", data_types) self.assertEqual(len(pixel_data_type), 1) pixel_data_type = pixel_data_type[0] - self.assertEqual(pixel_data_type[1].type, data_type.DataType.Dense) + self.assertEqual(pixel_data_type[1].type, pydp2.DataType.Dense) self.assertEqual(pixel_data_type[1].dim, 784) label_data_type = filter(lambda type: type[0] == "label", data_types) self.assertEqual(len(label_data_type), 1) label_data_type = label_data_type[0] - self.assertEqual(label_data_type[1].type, data_type.DataType.Index) + self.assertEqual(label_data_type[1].type, pydp2.DataType.Index) self.assertEqual(label_data_type[1].dim, 10) def test_get_layer(self): From d5365bb715c4438d05bc3c80a750c3448e09b347 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 11:19:17 +0800 Subject: [PATCH 129/153] Add input data interface for inference --- demo/mnist/api_train_v2.py | 19 ++++---- doc/api/v2/run_logic.rst | 8 ++++ python/paddle/v2/inference.py | 88 ++++++++++++++++++++++++++++++++--- 3 files changed, 99 insertions(+), 16 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 4fb1808ca11a6..81b330a60522e 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -90,7 +90,7 @@ def event_handler(event): print "Pass %d, Batch %d, Cost %f, %s" % ( event.pass_id, event.batch_id, event.cost, event.metrics) if isinstance(event, paddle.event.EndPass): - result = trainer.test(reader=paddle.reader.batched( + result = trainer.test(reader=paddle.batch( paddle.dataset.mnist.test(), batch_size=128)) print "Test with Pass %d, Cost %f, %s\n" % ( event.pass_id, result.cost, result.metrics) @@ -110,17 +110,16 @@ def event_handler(event): print 'Best pass is %s, testing Avgcost is %s' % (best[0], best[1]) print 'The classification accuracy is %.2f%%' % (100 - float(best[2]) * 100) + test_creator = paddle.dataset.mnist.test() + test_data = [] + for item in test_creator(): + test_data.append(item[0]) + if len(test_data) == 100: + break + # output is a softmax layer. It returns probabilities. # Shape should be (100, 10) - probs = paddle.infer( - output=predict, - parameters=parameters, - reader=paddle.batch( - paddle.reader.firstn( - paddle.reader.map_readers(lambda item: (item[0], ), - paddle.dataset.mnist.test()), - n=100), - batch_size=32)) + probs = paddle.infer(output=predict, parameters=parameters, input=test_data) print probs.shape diff --git a/doc/api/v2/run_logic.rst b/doc/api/v2/run_logic.rst index 904d45966dfc1..0f807873ff9a1 100644 --- a/doc/api/v2/run_logic.rst +++ b/doc/api/v2/run_logic.rst @@ -2,6 +2,7 @@ Trainer API ########### + ========== Parameters ========== @@ -24,3 +25,10 @@ Event .. automodule:: paddle.v2.event :members: + + +========= +Inference +========= + +.. autofunction:: paddle.v2.infer \ No newline at end of file diff --git a/python/paddle/v2/inference.py b/python/paddle/v2/inference.py index 476fd3fa4523a..7c079a0d32df6 100644 --- a/python/paddle/v2/inference.py +++ b/python/paddle/v2/inference.py @@ -1,9 +1,9 @@ +import numpy import py_paddle.swig_paddle as api - +import collections import topology +import minibatch from data_feeder import DataFeeder -import itertools -import numpy __all__ = ['infer'] @@ -21,9 +21,39 @@ def __init__(self, output, parameters): self.__gradient_machine__ = gm self.__data_types__ = topo.data_type() - def iter_infer(self, reader, reader_dict=None): + def iter_infer(self, + input=None, + batch_size=None, + reader=None, + reader_dict=None): if reader_dict is None: reader_dict = self.default_reader_dict() + + if reader is None: + assert input is not None and isinstance(input, collections.Iterable) + if not isinstance(input, collections.Iterable): + raise TypeError("When reader is None, input should be whole " + "inference data and should be iterable") + + if batch_size is None: + if not hasattr(input, '__len__'): + raise ValueError("Should set batch size when input data " + "don't contain length.") + batch_size = len(input) + + def __reader_impl__(): + for each_sample in input: + if len(reader_dict) == 1: + yield [each_sample] + else: + yield each_sample + + reader = minibatch.batch(__reader_impl__, batch_size=batch_size) + else: + if input is not None: + raise ValueError("User should set either input or reader, " + "should not set them both.") + feeder = DataFeeder(self.__data_types__, reader_dict) self.__gradient_machine__.start() for data_batch in reader(): @@ -54,6 +84,52 @@ def default_reader_dict(self): return reader_dict -def infer(output, parameters, reader, reader_dict=None, field='value'): +def infer(output, + parameters, + input=None, + batch_size=None, + reader=None, + reader_dict=None, + field='value'): + """ + Infer a neural network by given neural network output and parameters. The + user should pass either a batch of input data or reader method. + + Example usages: + + .. code-block:: python + + result = paddle.infer(prediction, parameters, input=SomeData, + batch_size=32) + print result + + :param output: output of the neural network that would be inferred + :type output: paddle.v2.config_base.Layer + :param parameters: parameters of the neural network. + :type parameters: paddle.v2.parameters.Parameters + :param input: input data batch. Should be a python iterable object, and each + element is the data batch. + :type input: collections.Iterable + :param batch_size: the batch size when perform inference. Default is the + length of input. + :type batch_size: int + :param reader: input data reader creator in batch. If this field is set, the + `input` and `batch_size` will be ignored. + :type reader: callable + :param reader_dict: Reader dictionary. Default could generate from input + value. + :param field: The prediction field. It should in [`value`, `ids`]. `value` + means return the prediction probabilities, `ids` means return + the prediction labels. Default is `value` + :type field: str + :return: a numpy array + :rtype: numpy.ndarray + """ + inferer = Inference(output=output, parameters=parameters) - return inferer.infer(field=field, reader=reader, reader_dict=reader_dict) + return inferer.infer( + field=field, + input=input, + batch_size=batch_size, + reader=reader, + reader_dict=reader_dict) From c36a3f46070e8ef5102b6fb34362c50193d5f529 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 14:51:15 +0800 Subject: [PATCH 130/153] Add unittest for serialize/deserialize. --- python/paddle/v2/parameters.py | 6 +++ python/paddle/v2/tests/run_tests.sh | 2 +- python/paddle/v2/tests/test_parameters.py | 60 +++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/tests/test_parameters.py diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index 1fed0b8a6a6eb..05dc5c68dd97b 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -124,6 +124,12 @@ def __getitem__(self, key): if len(self.__gradient_machines__) == 0: # create new parameter in python numpy. + if len(self.__tmp_params__) != 0: + ret_list = [ + mat for name, mat in self.__tmp_params__ if name == key + ] + if len(ret_list) == 1: + return ret_list[0] return np.ndarray(shape=shape, dtype=np.float32) else: for each_gradient_machine in self.__gradient_machines__: diff --git a/python/paddle/v2/tests/run_tests.sh b/python/paddle/v2/tests/run_tests.sh index b96f54fe9cc78..dda1b1bd222a9 100755 --- a/python/paddle/v2/tests/run_tests.sh +++ b/python/paddle/v2/tests/run_tests.sh @@ -22,7 +22,7 @@ cd $SCRIPTPATH $1 -m pip install ../../../../paddle/dist/*.whl -test_list="test_data_feeder.py" +test_list="test_data_feeder.py test_parameters.py" export PYTHONPATH=$PWD/../../../../python/ diff --git a/python/paddle/v2/tests/test_parameters.py b/python/paddle/v2/tests/test_parameters.py new file mode 100644 index 0000000000000..ebb182caab643 --- /dev/null +++ b/python/paddle/v2/tests/test_parameters.py @@ -0,0 +1,60 @@ +import unittest +import sys + +try: + import py_paddle + + del py_paddle +except ImportError: + print >> sys.stderr, "It seems swig of Paddle is not installed, this " \ + "unittest will not be run." + sys.exit(0) + +import paddle.v2.parameters as parameters +from paddle.proto.ParameterConfig_pb2 import ParameterConfig +import random +import cStringIO +import numpy + + +def __rand_param_config__(name): + conf = ParameterConfig() + conf.name = name + size = 1 + for i in xrange(2): + dim = random.randint(1, 1000) + conf.dims.append(dim) + size *= dim + conf.size = size + assert conf.IsInitialized() + return conf + + +class TestParameters(unittest.TestCase): + def test_serialization(self): + params = parameters.Parameters() + params.__append_config__(__rand_param_config__("param_0")) + params.__append_config__(__rand_param_config__("param_1")) + + for name in params.names(): + param = params.get(name) + param[:] = numpy.random.uniform( + -1.0, 1.0, size=params.get_shape(name)) + params.set(name, param) + + tmp_file = cStringIO.StringIO() + params.to_tar(tmp_file) + tmp_file.seek(0) + params_dup = parameters.Parameters.from_tar(tmp_file) + + self.assertEqual(params_dup.names(), params.names()) + + for name in params.names(): + self.assertEqual(params.get_shape(name), params_dup.get_shape(name)) + p0 = params.get(name) + p1 = params_dup.get(name) + self.assertTrue(numpy.isclose(p0, p1).all()) + + +if __name__ == '__main__': + unittest.main() From 26445368a2fb2d95598d80b5fad0d880c04bd0da Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 15:45:19 +0800 Subject: [PATCH 131/153] Rename reader_dict to feeding * Also fix some other bugs. * Fix #1495 --- demo/image_classification/api_v2_train.py | 13 ++++++----- demo/introduction/api_train_v2.py | 22 ++++++++--------- demo/mnist/api_train_v2.py | 4 ++-- demo/semantic_role_labeling/api_train_v2.py | 6 ++--- demo/sentiment/train_v2.py | 23 +++++++----------- demo/seqToseq/api_train_v2.py | 6 ++--- python/paddle/v2/data_feeder.py | 24 ++++++++++++++----- python/paddle/v2/inference.py | 16 ++++--------- python/paddle/v2/trainer.py | 26 ++++++--------------- 9 files changed, 64 insertions(+), 76 deletions(-) diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py index e0fc0e04bbd21..7134fa61e861b 100644 --- a/demo/image_classification/api_v2_train.py +++ b/demo/image_classification/api_v2_train.py @@ -13,8 +13,9 @@ # limitations under the License import sys + import paddle.v2 as paddle -from api_v2_vgg import vgg_bn_drop + from api_v2_resnet import resnet_cifar10 @@ -23,7 +24,7 @@ def main(): classdim = 10 # PaddlePaddle init - paddle.init(use_gpu=True, trainer_count=1) + paddle.init(use_gpu=False, trainer_count=1) image = paddle.layer.data( name="image", type=paddle.data_type.dense_vector(datadim)) @@ -68,8 +69,8 @@ def event_handler(event): result = trainer.test( reader=paddle.batch( paddle.dataset.cifar.test10(), batch_size=128), - reader_dict={'image': 0, - 'label': 1}) + feeding={'image': 0, + 'label': 1}) print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics) # Create trainer @@ -83,8 +84,8 @@ def event_handler(event): batch_size=128), num_passes=5, event_handler=event_handler, - reader_dict={'image': 0, - 'label': 1}) + feeding={'image': 0, + 'label': 1}) if __name__ == '__main__': diff --git a/demo/introduction/api_train_v2.py b/demo/introduction/api_train_v2.py index 75dd65f9fc8cd..84125c3b4b621 100644 --- a/demo/introduction/api_train_v2.py +++ b/demo/introduction/api_train_v2.py @@ -30,26 +30,26 @@ def main(): def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 100 == 0: - print "Pass %d, Batch %d, Cost %f, %s" % ( - event.pass_id, event.batch_id, event.cost, event.metrics) + print "Pass %d, Batch %d, Cost %f" % ( + event.pass_id, event.batch_id, event.cost) if isinstance(event, paddle.event.EndPass): - result = trainer.test( - reader=paddle.reader.batched( - uci_housing.test(), batch_size=2), - reader_dict={'x': 0, + if (event.pass_id + 1) % 10 == 0: + result = trainer.test( + reader=paddle.batch( + uci_housing.test(), batch_size=2), + feeding={'x': 0, 'y': 1}) - if event.pass_id % 10 == 0: - print "Test %d, %s" % (event.pass_id, result.metrics) + print "Test %d, %.2f" % (event.pass_id, result.cost) # training trainer.train( - reader=paddle.reader.batched( + reader=paddle.batch( paddle.reader.shuffle( uci_housing.train(), buf_size=500), batch_size=2), - reader_dict={'x': 0, - 'y': 1}, + feeding={'x': 0, + 'y': 1}, event_handler=event_handler, num_passes=30) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 072b2a08da6db..68761be80f24f 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -92,7 +92,7 @@ def main(): def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 1000 == 0: - result = trainer.test(reader=paddle.reader.batched( + result = trainer.test(reader=paddle.batch( paddle.dataset.mnist.test(), batch_size=256)) print "Pass %d, Batch %d, Cost %f, %s, Testing metrics %s" % ( @@ -103,7 +103,7 @@ def event_handler(event): parameters.to_tar(f) elif isinstance(event, paddle.event.EndPass): - result = trainer.test(reader=paddle.reader.batched( + result = trainer.test(reader=paddle.batch( paddle.dataset.mnist.test(), batch_size=128)) print "Test with Pass %d, Cost %f, %s\n" % ( event.pass_id, result.cost, result.metrics) diff --git a/demo/semantic_role_labeling/api_train_v2.py b/demo/semantic_role_labeling/api_train_v2.py index 15db922b97abc..036cad4b0a323 100644 --- a/demo/semantic_role_labeling/api_train_v2.py +++ b/demo/semantic_role_labeling/api_train_v2.py @@ -163,11 +163,11 @@ def event_handler(event): update_equation=optimizer) parameters.set('emb', load_parameter(conll05.get_embedding(), 44068, 32)) - trn_reader = paddle.reader.batched( + trn_reader = paddle.batch( paddle.reader.shuffle( conll05.test(), buf_size=8192), batch_size=10) - reader_dict = { + feeding = { 'word_data': 0, 'ctx_n2_data': 1, 'ctx_n1_data': 2, @@ -183,7 +183,7 @@ def event_handler(event): reader=trn_reader, event_handler=event_handler, num_passes=10000, - reader_dict=reader_dict) + feeding=feeding) if __name__ == '__main__': diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py index 3a266e74ea930..fd7243cbe6997 100644 --- a/demo/sentiment/train_v2.py +++ b/demo/sentiment/train_v2.py @@ -18,11 +18,7 @@ import paddle.v2 as paddle -def convolution_net(input_dim, - class_dim=2, - emb_dim=128, - hid_dim=128, - is_predict=False): +def convolution_net(input_dim, class_dim=2, emb_dim=128, 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) @@ -42,8 +38,7 @@ def stacked_lstm_net(input_dim, class_dim=2, emb_dim=128, hid_dim=512, - stacked_num=3, - is_predict=False): + stacked_num=3): """ A Wrapper for sentiment classification task. This network uses bi-directional recurrent network, @@ -110,7 +105,7 @@ def stacked_lstm_net(input_dim, if __name__ == '__main__': # init - paddle.init(use_gpu=True, trainer_count=4) + paddle.init(use_gpu=False, trainer_count=4) # network config print 'load dictionary...' @@ -143,11 +138,11 @@ def event_handler(event): sys.stdout.flush() if isinstance(event, paddle.event.EndPass): result = trainer.test( - reader=paddle.reader.batched( + reader=paddle.batch( lambda: paddle.dataset.imdb.test(word_dict), batch_size=128), - reader_dict={'word': 0, - 'label': 1}) + feeding={'word': 0, + 'label': 1}) print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics) # create trainer @@ -156,11 +151,11 @@ def event_handler(event): update_equation=adam_optimizer) trainer.train( - reader=paddle.reader.batched( + reader=paddle.batch( paddle.reader.shuffle( lambda: paddle.dataset.imdb.train(word_dict), buf_size=1000), batch_size=100), event_handler=event_handler, - reader_dict={'word': 0, - 'label': 1}, + feeding={'word': 0, + 'label': 1}, num_passes=10) diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index a5f59ec379738..5b7506b152ccd 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -80,13 +80,13 @@ def main(): update_equation=optimizer) # define data reader - reader_dict = { + feeding = { 'source_language_word': 0, 'target_language_word': 1, 'target_language_next_word': 2 } - wmt14_reader = paddle.reader.batched( + wmt14_reader = paddle.batch( paddle.reader.shuffle( train_reader("data/pre-wmt14/train/train"), buf_size=8192), batch_size=5) @@ -103,7 +103,7 @@ def event_handler(event): reader=wmt14_reader, event_handler=event_handler, num_passes=10000, - reader_dict=reader_dict) + feeding=feeding) if __name__ == '__main__': diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index b7465238be813..ba77fecf21eec 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -14,11 +14,18 @@ from py_paddle import DataProviderConverter -import data_type +import paddle.trainer.PyDataProvider2 as pydp2 __all__ = ['DataFeeder'] +def default_feeding_map(data_types): + reader_dict = dict() + for i, tp in enumerate(data_types): + reader_dict[tp[0]] = i + return reader_dict + + class DataFeeder(DataProviderConverter): """ DataFeeder converts the data returned by paddle.reader into a data structure @@ -60,16 +67,21 @@ class DataFeeder(DataProviderConverter): :type data_types: list :param reader_dict: A dictionary to specify the position of each data in the input data. - :type reader_dict: dict + :type feeding: dict """ - def __init__(self, data_types, reader_dict): + def __init__(self, data_types, feeding=None): self.input_names = [] input_types = [] - self.reader_dict = reader_dict + if feeding is None: + feeding = default_feeding_map(data_types) + + self.feeding = feeding for each in data_types: self.input_names.append(each[0]) - assert isinstance(each[1], data_type.InputType) + if not isinstance(each[1], pydp2.InputType): + raise TypeError("second item in each data_type should be an " + "InputType") input_types.append(each[1]) DataProviderConverter.__init__(self, input_types) @@ -90,7 +102,7 @@ def reorder_data(data): for each in data: reorder = [] for name in self.input_names: - reorder.append(each[self.reader_dict[name]]) + reorder.append(each[self.feeding[name]]) retv.append(reorder) return retv diff --git a/python/paddle/v2/inference.py b/python/paddle/v2/inference.py index 476fd3fa4523a..7d889bce7fe5d 100644 --- a/python/paddle/v2/inference.py +++ b/python/paddle/v2/inference.py @@ -21,10 +21,8 @@ def __init__(self, output, parameters): self.__gradient_machine__ = gm self.__data_types__ = topo.data_type() - def iter_infer(self, reader, reader_dict=None): - if reader_dict is None: - reader_dict = self.default_reader_dict() - feeder = DataFeeder(self.__data_types__, reader_dict) + def iter_infer(self, reader, feeding=None): + feeder = DataFeeder(self.__data_types__, feeding) self.__gradient_machine__.start() for data_batch in reader(): yield self.__gradient_machine__.forwardTest(feeder(data_batch)) @@ -47,13 +45,7 @@ def infer(self, field='value', **kwargs): else: return retv - def default_reader_dict(self): - reader_dict = dict() - for i, tp in enumerate(self.__data_types__): - reader_dict[tp[0]] = i - return reader_dict - -def infer(output, parameters, reader, reader_dict=None, field='value'): +def infer(output, parameters, reader, feeding=None, field='value'): inferer = Inference(output=output, parameters=parameters) - return inferer.infer(field=field, reader=reader, reader_dict=reader_dict) + return inferer.infer(field=field, reader=reader, feeding=feeding) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 187abaf9a34f7..7bd3e2c565ee0 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -61,7 +61,7 @@ def __init__(self, cost, parameters, update_equation): self.__gradient_machine__.randParameters() parameters.append_gradient_machine(gm) - def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): + def train(self, reader, num_passes=1, event_handler=None, feeding=None): """ Training method. Will train num_passes of input data. @@ -70,14 +70,13 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): :param event_handler: Event handler. A method will be invoked when event occurred. :type event_handler: (BaseEvent) => None + :param feeding: Feeding is a map of neural network input name and array + index that reader returns. + :type feeding: dict :return: """ if event_handler is None: event_handler = default_event_handler - - if reader_dict is None: - reader_dict = self.default_reader_dict() - __check_train_args__(**locals()) updater = self.__optimizer__.create_local_updater() @@ -89,9 +88,7 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): pass_evaluator = self.__gradient_machine__.makeEvaluator() assert isinstance(pass_evaluator, api.Evaluator) out_args = api.Arguments.createArguments(0) - - feeder = DataFeeder(self.__data_types__, reader_dict) - + feeder = DataFeeder(self.__data_types__, feeding) for pass_id in xrange(num_passes): event_handler(v2_event.BeginPass(pass_id)) pass_evaluator.start() @@ -125,17 +122,8 @@ def train(self, reader, num_passes=1, event_handler=None, reader_dict=None): event_handler(v2_event.EndPass(pass_id, evaluator=pass_evaluator)) self.__gradient_machine__.finish() - def default_reader_dict(self): - reader_dict = dict() - for i, tp in enumerate(self.__data_types__): - reader_dict[tp[0]] = i - return reader_dict - - def test(self, reader, reader_dict=None): - if reader_dict is None: - reader_dict = self.default_reader_dict() - - feeder = DataFeeder(self.__data_types__, reader_dict) + def test(self, reader, feeding=None): + feeder = DataFeeder(self.__data_types__, feeding) evaluator = self.__gradient_machine__.makeEvaluator() out_args = api.Arguments.createArguments(0) evaluator.start() From c7d259e1fe673bcb192b3180a3be1deaba8bd49f Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 6 Mar 2017 16:43:46 +0800 Subject: [PATCH 132/153] Merge develop --- demo/recommendation/api_train_v2.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/demo/recommendation/api_train_v2.py b/demo/recommendation/api_train_v2.py index a7cf137a798ed..9b254933a1de6 100644 --- a/demo/recommendation/api_train_v2.py +++ b/demo/recommendation/api_train_v2.py @@ -72,7 +72,7 @@ def main(): parameters=parameters, update_equation=paddle.optimizer.Adam( learning_rate=1e-4)) - reader_dict = { + feeding = { 'user_id': 0, 'gender_id': 1, 'age_id': 2, @@ -90,14 +90,12 @@ def event_handler(event): event.pass_id, event.batch_id, event.cost) trainer.train( - reader=paddle.reader.batched( - paddle.reader.firstn( - paddle.reader.shuffle( - paddle.dataset.movielens.train(), buf_size=8192), - n=1000), + reader=paddle.batch( + paddle.reader.shuffle( + paddle.dataset.movielens.train(), buf_size=8192), batch_size=256), event_handler=event_handler, - reader_dict=reader_dict, + feeding=feeding, num_passes=1) user_id = 234 @@ -111,17 +109,16 @@ def event_handler(event): def reader(): yield feature - infer_dict = copy.copy(reader_dict) + infer_dict = copy.copy(feeding) del infer_dict['score'] - print infer_dict prediction = paddle.infer( output=inference, parameters=parameters, - reader=paddle.reader.batched( + reader=paddle.batch( reader, batch_size=32), - reader_dict=infer_dict) - print prediction + feeding=infer_dict) + print(prediction + 5) / 2 if __name__ == '__main__': From 82437970594e331f63bed25c2f3ab42b413e68d9 Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 6 Mar 2017 18:54:47 +0800 Subject: [PATCH 133/153] add relu in layer_math.py --- .../trainer_config_helpers/layer_math.py | 1 + .../tests/configs/math_ops.py | 3 +- .../tests/configs/protostr/math_ops.protostr | 32 ++++++++++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/python/paddle/trainer_config_helpers/layer_math.py b/python/paddle/trainer_config_helpers/layer_math.py index 2d9e36f2b0d37..544b443825393 100644 --- a/python/paddle/trainer_config_helpers/layer_math.py +++ b/python/paddle/trainer_config_helpers/layer_math.py @@ -39,6 +39,7 @@ def op(input, name=None): register_unary_math_op('sigmoid', act.SigmoidActivation()) register_unary_math_op('tanh', act.TanhActivation()) register_unary_math_op('square', act.SquareActivation()) +register_unary_math_op('relu', act.ReluActivation()) def add(layeroutput, other): diff --git a/python/paddle/trainer_config_helpers/tests/configs/math_ops.py b/python/paddle/trainer_config_helpers/tests/configs/math_ops.py index 3331c10d6497f..24c901c8ee3ab 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/math_ops.py +++ b/python/paddle/trainer_config_helpers/tests/configs/math_ops.py @@ -7,8 +7,9 @@ x = layer_math.log(x) x = layer_math.abs(x) x = layer_math.sigmoid(x) +x = layer_math.tanh(x) x = layer_math.square(x) -x = layer_math.square(x) +x = layer_math.relu(x) y = 1 + x y = y + 1 y = x + y diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/math_ops.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/math_ops.protostr index da8da1b541f37..9b8a2ad9687d3 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/math_ops.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/math_ops.protostr @@ -65,13 +65,28 @@ layers { } } } +layers { + name: "__tanh_0__" + type: "mixed" + size: 100 + active_type: "tanh" + inputs { + input_layer_name: "__sigmoid_0__" + proj_conf { + type: "identity" + name: "___tanh_0__.w0" + input_size: 100 + output_size: 100 + } + } +} layers { name: "__square_0__" type: "mixed" size: 100 active_type: "square" inputs { - input_layer_name: "__sigmoid_0__" + input_layer_name: "__tanh_0__" proj_conf { type: "identity" name: "___square_0__.w0" @@ -81,15 +96,15 @@ layers { } } layers { - name: "__square_1__" + name: "__relu_0__" type: "mixed" size: 100 - active_type: "square" + active_type: "relu" inputs { input_layer_name: "__square_0__" proj_conf { type: "identity" - name: "___square_1__.w0" + name: "___relu_0__.w0" input_size: 100 output_size: 100 } @@ -101,7 +116,7 @@ layers { size: 100 active_type: "" inputs { - input_layer_name: "__square_1__" + input_layer_name: "__relu_0__" } slope: 1.0 intercept: 1 @@ -123,7 +138,7 @@ layers { size: 100 active_type: "" inputs { - input_layer_name: "__square_1__" + input_layer_name: "__relu_0__" proj_conf { type: "identity" name: "___mixed_0__.w0" @@ -147,7 +162,7 @@ layers { size: 100 active_type: "" inputs { - input_layer_name: "__square_1__" + input_layer_name: "__relu_0__" } slope: -1.0 intercept: 0.0 @@ -339,8 +354,9 @@ sub_models { layer_names: "__log_0__" layer_names: "__abs_0__" layer_names: "__sigmoid_0__" + layer_names: "__tanh_0__" layer_names: "__square_0__" - layer_names: "__square_1__" + layer_names: "__relu_0__" layer_names: "__slope_intercept_layer_0__" layer_names: "__slope_intercept_layer_1__" layer_names: "__mixed_0__" From 96a2e44aa3d0e1c566c08bee01e284f59277ef3c Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 6 Mar 2017 20:46:25 +0800 Subject: [PATCH 134/153] optimize seq2seq-dataset --- demo/sentiment/preprocess.py | 166 +++++++++++++++++++++++- python/paddle/v2/dataset/wmt14.py | 149 ++++++++++----------- python/paddle/v2/dataset/wmt14_util.py | 172 ------------------------- 3 files changed, 229 insertions(+), 258 deletions(-) delete mode 100644 python/paddle/v2/dataset/wmt14_util.py diff --git a/demo/sentiment/preprocess.py b/demo/sentiment/preprocess.py index 29b3682b747c6..59c3b5febe7d3 100755 --- a/demo/sentiment/preprocess.py +++ b/demo/sentiment/preprocess.py @@ -12,22 +12,176 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import sys -import random import operator -import numpy as np -from subprocess import Popen, PIPE -from os.path import join as join_path from optparse import OptionParser +from os.path import join as join_path +from subprocess import Popen, PIPE +import numpy as np from paddle.utils.preprocess_util import * +from paddle.utils.preprocess_util import save_list, DatasetCreater """ Usage: run following command to show help message. python preprocess.py -h """ +class SeqToSeqDatasetCreater(DatasetCreater): + """ + A class to process data for sequence to sequence application. + """ + + def __init__(self, data_path, output_path): + """ + data_path: the path to store the train data, test data and gen data + output_path: the path to store the processed dataset + """ + DatasetCreater.__init__(self, data_path) + self.gen_dir_name = 'gen' + self.gen_list_name = 'gen.list' + self.output_path = output_path + + def concat_file(self, file_path, file1, file2, output_path, output): + """ + Concat file1 and file2 to be one output file + The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 + file_path: the path to store file1 and file2 + output_path: the path to store output file + """ + file1 = os.path.join(file_path, file1) + file2 = os.path.join(file_path, file2) + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) + + def cat_file(self, dir_path, suffix, output_path, output): + """ + Cat all the files in dir_path with suffix to be one output file + dir_path: the base directory to store input file + suffix: suffix of file name + output_path: the path to store output file + """ + cmd = 'cat ' + file_list = os.listdir(dir_path) + file_list.sort() + for file in file_list: + if file.endswith(suffix): + cmd += os.path.join(dir_path, file) + ' ' + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system(cmd + '> ' + output) + + def build_dict(self, file_path, dict_path, dict_size=-1): + """ + Create the dictionary for the file, Note that + 1. Valid characters include all printable characters + 2. There is distinction between uppercase and lowercase letters + 3. There is 3 special token: + : the start of a sequence + : the end of a sequence + : a word not included in dictionary + file_path: the path to store file + dict_path: the path to store dictionary + dict_size: word count of dictionary + if is -1, dictionary will contains all the words in file + """ + if not os.path.exists(dict_path): + dictory = dict() + with open(file_path, "r") as fdata: + for line in fdata: + line = line.split('\t') + for line_split in line: + words = line_split.strip().split() + for word in words: + if word not in dictory: + dictory[word] = 1 + else: + dictory[word] += 1 + output = open(dict_path, "w+") + output.write('\n\n\n') + count = 3 + for key, value in sorted( + dictory.items(), key=lambda d: d[1], reverse=True): + output.write(key + "\n") + count += 1 + if count == dict_size: + break + self.dict_size = count + + def create_dataset(self, + dict_size=-1, + mergeDict=False, + suffixes=['.src', '.trg']): + """ + Create seqToseq dataset + """ + # dataset_list and dir_list has one-to-one relationship + train_dataset = os.path.join(self.data_path, self.train_dir_name) + test_dataset = os.path.join(self.data_path, self.test_dir_name) + gen_dataset = os.path.join(self.data_path, self.gen_dir_name) + dataset_list = [train_dataset, test_dataset, gen_dataset] + + train_dir = os.path.join(self.output_path, self.train_dir_name) + test_dir = os.path.join(self.output_path, self.test_dir_name) + gen_dir = os.path.join(self.output_path, self.gen_dir_name) + dir_list = [train_dir, test_dir, gen_dir] + + # create directory + for dir in dir_list: + if not os.path.exists(dir): + os.makedirs(dir) + + # checkout dataset should be parallel corpora + suffix_len = len(suffixes[0]) + for dataset in dataset_list: + file_list = os.listdir(dataset) + if len(file_list) % 2 == 1: + raise RuntimeError("dataset should be parallel corpora") + file_list.sort() + for i in range(0, len(file_list), 2): + if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: + raise RuntimeError( + "source and target file name should be equal") + + # cat all the files with the same suffix in dataset + for suffix in suffixes: + for dataset in dataset_list: + outname = os.path.basename(dataset) + suffix + self.cat_file(dataset, suffix, dataset, outname) + + # concat parallel corpora and create file.list + print 'concat parallel corpora for dataset' + id = 0 + list = ['train.list', 'test.list', 'gen.list'] + for dataset in dataset_list: + outname = os.path.basename(dataset) + self.concat_file(dataset, outname + suffixes[0], + outname + suffixes[1], dir_list[id], outname) + save_list([os.path.join(dir_list[id], outname)], + os.path.join(self.output_path, list[id])) + id += 1 + + # build dictionary for train data + dict = ['src.dict', 'trg.dict'] + dict_path = [ + os.path.join(self.output_path, dict[0]), + os.path.join(self.output_path, dict[1]) + ] + if mergeDict: + outname = os.path.join(train_dir, train_dataset.split('/')[-1]) + print 'build src dictionary for train data' + self.build_dict(outname, dict_path[0], dict_size) + print 'build trg dictionary for train data' + os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) + else: + outname = os.path.join(train_dataset, self.train_dir_name) + for id in range(0, 2): + suffix = suffixes[id] + print 'build ' + suffix[1:] + ' dictionary for train data' + self.build_dict(outname + suffix, dict_path[id], dict_size) + print 'dictionary size is', self.dict_size + + def save_dict(dict, filename, is_reverse=True): """ Save dictionary into file. diff --git a/python/paddle/v2/dataset/wmt14.py b/python/paddle/v2/dataset/wmt14.py index 254f07c8dd391..f8637c0a00950 100644 --- a/python/paddle/v2/dataset/wmt14.py +++ b/python/paddle/v2/dataset/wmt14.py @@ -14,103 +14,92 @@ """ wmt14 dataset """ -import os -import os.path import tarfile import paddle.v2.dataset.common -from wmt14_util import SeqToSeqDatasetCreater __all__ = ['train', 'test', 'build_dict'] URL_DEV_TEST = 'http://www-lium.univ-lemans.fr/~schwenk/cslm_joint_paper/data/dev+test.tgz' MD5_DEV_TEST = '7d7897317ddd8ba0ae5c5fa7248d3ff5' # this is a small set of data for test. The original data is too large and will be add later. -URL_TRAIN = 'http://paddlepaddle.bj.bcebos.com/demo/wmt_shrinked_data/wmt14.tgz' -MD5_TRAIN = '7373473f86016f1f48037c9c340a2d5b' +URL_TRAIN = 'http://localhost:8989/wmt14.tgz' +MD5_TRAIN = 'a755315dd01c2c35bde29a744ede23a6' START = "" END = "" UNK = "" UNK_IDX = 2 -DEFAULT_DATA_DIR = "./data" -ORIGIN_DATA_DIR = "wmt14" -INNER_DATA_DIR = "pre-wmt14" -SRC_DICT = INNER_DATA_DIR + "/src.dict" -TRG_DICT = INNER_DATA_DIR + "/trg.dict" -TRAIN_FILE = INNER_DATA_DIR + "/train/train" - - -def __process_data__(data_path, dict_size=None): - downloaded_data = os.path.join(data_path, ORIGIN_DATA_DIR) - if not os.path.exists(downloaded_data): - # 1. download and extract tgz. - with tarfile.open( - paddle.v2.dataset.common.download(URL_TRAIN, 'wmt14', - MD5_TRAIN)) as tf: - tf.extractall(data_path) - - # 2. process data file to intermediate format. - processed_data = os.path.join(data_path, INNER_DATA_DIR) - if not os.path.exists(processed_data): - dict_size = dict_size or -1 - data_creator = SeqToSeqDatasetCreater(downloaded_data, processed_data) - data_creator.create_dataset(dict_size, mergeDict=False) - - -def __read_to_dict__(dict_path, count): - with open(dict_path, "r") as fin: + +def __read_to_dict__(tar_file, dict_size): + def __to_dict__(fd, size): out_dict = dict() - for line_count, line in enumerate(fin): - if line_count <= count: + for line_count, line in enumerate(fd): + if line_count < size: out_dict[line.strip()] = line_count else: break - return out_dict - - -def __reader__(file_name, src_dict, trg_dict): - with open(file_name, 'r') as f: - for line_count, line in enumerate(f): - line_split = line.strip().split('\t') - if len(line_split) != 2: - continue - src_seq = line_split[0] # one source sequence - src_words = src_seq.split() - src_ids = [ - src_dict.get(w, UNK_IDX) for w in [START] + src_words + [END] + return out_dict + + with tarfile.open(tar_file, mode='r') as f: + names = [ + each_item.name for each_item in f + if each_item.name.endswith("src.dict") + ] + assert len(names) == 1 + src_dict = __to_dict__(f.extractfile(names[0]), dict_size) + names = [ + each_item.name for each_item in f + if each_item.name.endswith("trg.dict") + ] + assert len(names) == 1 + trg_dict = __to_dict__(f.extractfile(names[0]), dict_size) + return src_dict, trg_dict + + +def reader_creator(tar_file, file_name, dict_size): + def reader(): + src_dict, trg_dict = __read_to_dict__(tar_file, dict_size) + with tarfile.open(tar_file, mode='r') as f: + names = [ + each_item.name for each_item in f + if each_item.name.endswith(file_name) ] - - trg_seq = line_split[1] # one target sequence - trg_words = trg_seq.split() - trg_ids = [trg_dict.get(w, UNK_IDX) for w in trg_words] - - # remove sequence whose length > 80 in training mode - if len(src_ids) > 80 or len(trg_ids) > 80: - continue - trg_ids_next = trg_ids + [trg_dict[END]] - trg_ids = [trg_dict[START]] + trg_ids - - yield src_ids, trg_ids, trg_ids_next - - -def train(data_dir=None, dict_size=None): - data_dir = data_dir or DEFAULT_DATA_DIR - __process_data__(data_dir, dict_size) - src_lang_dict = os.path.join(data_dir, SRC_DICT) - trg_lang_dict = os.path.join(data_dir, TRG_DICT) - train_file_name = os.path.join(data_dir, TRAIN_FILE) - - default_dict_size = len(open(src_lang_dict, "r").readlines()) - - if dict_size > default_dict_size: - raise ValueError("dict_dim should not be larger then the " - "length of word dict") - - real_dict_dim = dict_size or default_dict_size - - src_dict = __read_to_dict__(src_lang_dict, real_dict_dim) - trg_dict = __read_to_dict__(trg_lang_dict, real_dict_dim) - - return lambda: __reader__(train_file_name, src_dict, trg_dict) + for name in names: + for line in f.extractfile(name): + line_split = line.strip().split('\t') + if len(line_split) != 2: + continue + src_seq = line_split[0] # one source sequence + src_words = src_seq.split() + src_ids = [ + src_dict.get(w, UNK_IDX) + for w in [START] + src_words + [END] + ] + + trg_seq = line_split[1] # one target sequence + trg_words = trg_seq.split() + trg_ids = [trg_dict.get(w, UNK_IDX) for w in trg_words] + + # remove sequence whose length > 80 in training mode + if len(src_ids) > 80 or len(trg_ids) > 80: + continue + trg_ids_next = trg_ids + [trg_dict[END]] + trg_ids = [trg_dict[START]] + trg_ids + + yield src_ids, trg_ids, trg_ids_next + + return reader + + +def train(dict_size): + return reader_creator( + paddle.v2.dataset.common.download(URL_TRAIN, 'wmt14', MD5_TRAIN), + 'train/train', dict_size) + + +def test(dict_size): + return reader_creator( + paddle.v2.dataset.common.download(URL_TRAIN, 'wmt14', MD5_TRAIN), + 'test/test', dict_size) diff --git a/python/paddle/v2/dataset/wmt14_util.py b/python/paddle/v2/dataset/wmt14_util.py deleted file mode 100644 index 0d72389164337..0000000000000 --- a/python/paddle/v2/dataset/wmt14_util.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os - -from paddle.utils.preprocess_util import save_list, DatasetCreater - - -class SeqToSeqDatasetCreater(DatasetCreater): - """ - A class to process data for sequence to sequence application. - """ - - def __init__(self, data_path, output_path): - """ - data_path: the path to store the train data, test data and gen data - output_path: the path to store the processed dataset - """ - DatasetCreater.__init__(self, data_path) - self.gen_dir_name = 'gen' - self.gen_list_name = 'gen.list' - self.output_path = output_path - - def concat_file(self, file_path, file1, file2, output_path, output): - """ - Concat file1 and file2 to be one output file - The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 - file_path: the path to store file1 and file2 - output_path: the path to store output file - """ - file1 = os.path.join(file_path, file1) - file2 = os.path.join(file_path, file2) - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) - - def cat_file(self, dir_path, suffix, output_path, output): - """ - Cat all the files in dir_path with suffix to be one output file - dir_path: the base directory to store input file - suffix: suffix of file name - output_path: the path to store output file - """ - cmd = 'cat ' - file_list = os.listdir(dir_path) - file_list.sort() - for file in file_list: - if file.endswith(suffix): - cmd += os.path.join(dir_path, file) + ' ' - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system(cmd + '> ' + output) - - def build_dict(self, file_path, dict_path, dict_size=-1): - """ - Create the dictionary for the file, Note that - 1. Valid characters include all printable characters - 2. There is distinction between uppercase and lowercase letters - 3. There is 3 special token: - : the start of a sequence - : the end of a sequence - : a word not included in dictionary - file_path: the path to store file - dict_path: the path to store dictionary - dict_size: word count of dictionary - if is -1, dictionary will contains all the words in file - """ - if not os.path.exists(dict_path): - dictory = dict() - with open(file_path, "r") as fdata: - for line in fdata: - line = line.split('\t') - for line_split in line: - words = line_split.strip().split() - for word in words: - if word not in dictory: - dictory[word] = 1 - else: - dictory[word] += 1 - output = open(dict_path, "w+") - output.write('\n\n\n') - count = 3 - for key, value in sorted( - dictory.items(), key=lambda d: d[1], reverse=True): - output.write(key + "\n") - count += 1 - if count == dict_size: - break - self.dict_size = count - - def create_dataset(self, - dict_size=-1, - mergeDict=False, - suffixes=['.src', '.trg']): - """ - Create seqToseq dataset - """ - # dataset_list and dir_list has one-to-one relationship - train_dataset = os.path.join(self.data_path, self.train_dir_name) - test_dataset = os.path.join(self.data_path, self.test_dir_name) - gen_dataset = os.path.join(self.data_path, self.gen_dir_name) - dataset_list = [train_dataset, test_dataset, gen_dataset] - - train_dir = os.path.join(self.output_path, self.train_dir_name) - test_dir = os.path.join(self.output_path, self.test_dir_name) - gen_dir = os.path.join(self.output_path, self.gen_dir_name) - dir_list = [train_dir, test_dir, gen_dir] - - # create directory - for dir in dir_list: - if not os.path.exists(dir): - os.makedirs(dir) - - # checkout dataset should be parallel corpora - suffix_len = len(suffixes[0]) - for dataset in dataset_list: - file_list = os.listdir(dataset) - if len(file_list) % 2 == 1: - raise RuntimeError("dataset should be parallel corpora") - file_list.sort() - for i in range(0, len(file_list), 2): - if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: - raise RuntimeError( - "source and target file name should be equal") - - # cat all the files with the same suffix in dataset - for suffix in suffixes: - for dataset in dataset_list: - outname = os.path.basename(dataset) + suffix - self.cat_file(dataset, suffix, dataset, outname) - - # concat parallel corpora and create file.list - print 'concat parallel corpora for dataset' - id = 0 - list = ['train.list', 'test.list', 'gen.list'] - for dataset in dataset_list: - outname = os.path.basename(dataset) - self.concat_file(dataset, outname + suffixes[0], - outname + suffixes[1], dir_list[id], outname) - save_list([os.path.join(dir_list[id], outname)], - os.path.join(self.output_path, list[id])) - id += 1 - - # build dictionary for train data - dict = ['src.dict', 'trg.dict'] - dict_path = [ - os.path.join(self.output_path, dict[0]), - os.path.join(self.output_path, dict[1]) - ] - if mergeDict: - outname = os.path.join(train_dir, train_dataset.split('/')[-1]) - print 'build src dictionary for train data' - self.build_dict(outname, dict_path[0], dict_size) - print 'build trg dictionary for train data' - os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) - else: - outname = os.path.join(train_dataset, self.train_dir_name) - for id in range(0, 2): - suffix = suffixes[id] - print 'build ' + suffix[1:] + ' dictionary for train data' - self.build_dict(outname + suffix, dict_path[id], dict_size) - print 'dictionary size is', self.dict_size From 2ad9fd646f1cf612fb721d869f4b4c93e7aa5c2a Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 6 Mar 2017 20:52:18 +0800 Subject: [PATCH 135/153] revert preprocess.py --- demo/sentiment/preprocess.py | 166 ++--------------------------------- demo/seqToseq/preprocess.py | 160 ++++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 161 deletions(-) diff --git a/demo/sentiment/preprocess.py b/demo/sentiment/preprocess.py index 59c3b5febe7d3..29b3682b747c6 100755 --- a/demo/sentiment/preprocess.py +++ b/demo/sentiment/preprocess.py @@ -12,176 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os +import sys +import random import operator -from optparse import OptionParser -from os.path import join as join_path +import numpy as np from subprocess import Popen, PIPE +from os.path import join as join_path +from optparse import OptionParser -import numpy as np from paddle.utils.preprocess_util import * -from paddle.utils.preprocess_util import save_list, DatasetCreater """ Usage: run following command to show help message. python preprocess.py -h """ -class SeqToSeqDatasetCreater(DatasetCreater): - """ - A class to process data for sequence to sequence application. - """ - - def __init__(self, data_path, output_path): - """ - data_path: the path to store the train data, test data and gen data - output_path: the path to store the processed dataset - """ - DatasetCreater.__init__(self, data_path) - self.gen_dir_name = 'gen' - self.gen_list_name = 'gen.list' - self.output_path = output_path - - def concat_file(self, file_path, file1, file2, output_path, output): - """ - Concat file1 and file2 to be one output file - The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 - file_path: the path to store file1 and file2 - output_path: the path to store output file - """ - file1 = os.path.join(file_path, file1) - file2 = os.path.join(file_path, file2) - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) - - def cat_file(self, dir_path, suffix, output_path, output): - """ - Cat all the files in dir_path with suffix to be one output file - dir_path: the base directory to store input file - suffix: suffix of file name - output_path: the path to store output file - """ - cmd = 'cat ' - file_list = os.listdir(dir_path) - file_list.sort() - for file in file_list: - if file.endswith(suffix): - cmd += os.path.join(dir_path, file) + ' ' - output = os.path.join(output_path, output) - if not os.path.exists(output): - os.system(cmd + '> ' + output) - - def build_dict(self, file_path, dict_path, dict_size=-1): - """ - Create the dictionary for the file, Note that - 1. Valid characters include all printable characters - 2. There is distinction between uppercase and lowercase letters - 3. There is 3 special token: - : the start of a sequence - : the end of a sequence - : a word not included in dictionary - file_path: the path to store file - dict_path: the path to store dictionary - dict_size: word count of dictionary - if is -1, dictionary will contains all the words in file - """ - if not os.path.exists(dict_path): - dictory = dict() - with open(file_path, "r") as fdata: - for line in fdata: - line = line.split('\t') - for line_split in line: - words = line_split.strip().split() - for word in words: - if word not in dictory: - dictory[word] = 1 - else: - dictory[word] += 1 - output = open(dict_path, "w+") - output.write('\n\n\n') - count = 3 - for key, value in sorted( - dictory.items(), key=lambda d: d[1], reverse=True): - output.write(key + "\n") - count += 1 - if count == dict_size: - break - self.dict_size = count - - def create_dataset(self, - dict_size=-1, - mergeDict=False, - suffixes=['.src', '.trg']): - """ - Create seqToseq dataset - """ - # dataset_list and dir_list has one-to-one relationship - train_dataset = os.path.join(self.data_path, self.train_dir_name) - test_dataset = os.path.join(self.data_path, self.test_dir_name) - gen_dataset = os.path.join(self.data_path, self.gen_dir_name) - dataset_list = [train_dataset, test_dataset, gen_dataset] - - train_dir = os.path.join(self.output_path, self.train_dir_name) - test_dir = os.path.join(self.output_path, self.test_dir_name) - gen_dir = os.path.join(self.output_path, self.gen_dir_name) - dir_list = [train_dir, test_dir, gen_dir] - - # create directory - for dir in dir_list: - if not os.path.exists(dir): - os.makedirs(dir) - - # checkout dataset should be parallel corpora - suffix_len = len(suffixes[0]) - for dataset in dataset_list: - file_list = os.listdir(dataset) - if len(file_list) % 2 == 1: - raise RuntimeError("dataset should be parallel corpora") - file_list.sort() - for i in range(0, len(file_list), 2): - if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: - raise RuntimeError( - "source and target file name should be equal") - - # cat all the files with the same suffix in dataset - for suffix in suffixes: - for dataset in dataset_list: - outname = os.path.basename(dataset) + suffix - self.cat_file(dataset, suffix, dataset, outname) - - # concat parallel corpora and create file.list - print 'concat parallel corpora for dataset' - id = 0 - list = ['train.list', 'test.list', 'gen.list'] - for dataset in dataset_list: - outname = os.path.basename(dataset) - self.concat_file(dataset, outname + suffixes[0], - outname + suffixes[1], dir_list[id], outname) - save_list([os.path.join(dir_list[id], outname)], - os.path.join(self.output_path, list[id])) - id += 1 - - # build dictionary for train data - dict = ['src.dict', 'trg.dict'] - dict_path = [ - os.path.join(self.output_path, dict[0]), - os.path.join(self.output_path, dict[1]) - ] - if mergeDict: - outname = os.path.join(train_dir, train_dataset.split('/')[-1]) - print 'build src dictionary for train data' - self.build_dict(outname, dict_path[0], dict_size) - print 'build trg dictionary for train data' - os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) - else: - outname = os.path.join(train_dataset, self.train_dir_name) - for id in range(0, 2): - suffix = suffixes[id] - print 'build ' + suffix[1:] + ' dictionary for train data' - self.build_dict(outname + suffix, dict_path[id], dict_size) - print 'dictionary size is', self.dict_size - - def save_dict(dict, filename, is_reverse=True): """ Save dictionary into file. diff --git a/demo/seqToseq/preprocess.py b/demo/seqToseq/preprocess.py index afa7bd5e0f419..03f371331a075 100755 --- a/demo/seqToseq/preprocess.py +++ b/demo/seqToseq/preprocess.py @@ -23,9 +23,167 @@ -m --mergeDict merge source and target dictionary """ import os +import sys + +import string from optparse import OptionParser +from paddle.utils.preprocess_util import save_list, DatasetCreater + + +class SeqToSeqDatasetCreater(DatasetCreater): + """ + A class to process data for sequence to sequence application. + """ + + def __init__(self, data_path, output_path): + """ + data_path: the path to store the train data, test data and gen data + output_path: the path to store the processed dataset + """ + DatasetCreater.__init__(self, data_path) + self.gen_dir_name = 'gen' + self.gen_list_name = 'gen.list' + self.output_path = output_path + + def concat_file(self, file_path, file1, file2, output_path, output): + """ + Concat file1 and file2 to be one output file + The i-th line of output = i-th line of file1 + '\t' + i-th line of file2 + file_path: the path to store file1 and file2 + output_path: the path to store output file + """ + file1 = os.path.join(file_path, file1) + file2 = os.path.join(file_path, file2) + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system('paste ' + file1 + ' ' + file2 + ' > ' + output) + + def cat_file(self, dir_path, suffix, output_path, output): + """ + Cat all the files in dir_path with suffix to be one output file + dir_path: the base directory to store input file + suffix: suffix of file name + output_path: the path to store output file + """ + cmd = 'cat ' + file_list = os.listdir(dir_path) + file_list.sort() + for file in file_list: + if file.endswith(suffix): + cmd += os.path.join(dir_path, file) + ' ' + output = os.path.join(output_path, output) + if not os.path.exists(output): + os.system(cmd + '> ' + output) + + def build_dict(self, file_path, dict_path, dict_size=-1): + """ + Create the dictionary for the file, Note that + 1. Valid characters include all printable characters + 2. There is distinction between uppercase and lowercase letters + 3. There is 3 special token: + : the start of a sequence + : the end of a sequence + : a word not included in dictionary + file_path: the path to store file + dict_path: the path to store dictionary + dict_size: word count of dictionary + if is -1, dictionary will contains all the words in file + """ + if not os.path.exists(dict_path): + dictory = dict() + with open(file_path, "r") as fdata: + for line in fdata: + line = line.split('\t') + for line_split in line: + words = line_split.strip().split() + for word in words: + if word not in dictory: + dictory[word] = 1 + else: + dictory[word] += 1 + output = open(dict_path, "w+") + output.write('\n\n\n') + count = 3 + for key, value in sorted( + dictory.items(), key=lambda d: d[1], reverse=True): + output.write(key + "\n") + count += 1 + if count == dict_size: + break + self.dict_size = count + + def create_dataset(self, + dict_size=-1, + mergeDict=False, + suffixes=['.src', '.trg']): + """ + Create seqToseq dataset + """ + # dataset_list and dir_list has one-to-one relationship + train_dataset = os.path.join(self.data_path, self.train_dir_name) + test_dataset = os.path.join(self.data_path, self.test_dir_name) + gen_dataset = os.path.join(self.data_path, self.gen_dir_name) + dataset_list = [train_dataset, test_dataset, gen_dataset] + + train_dir = os.path.join(self.output_path, self.train_dir_name) + test_dir = os.path.join(self.output_path, self.test_dir_name) + gen_dir = os.path.join(self.output_path, self.gen_dir_name) + dir_list = [train_dir, test_dir, gen_dir] + + # create directory + for dir in dir_list: + if not os.path.exists(dir): + os.mkdir(dir) + + # checkout dataset should be parallel corpora + suffix_len = len(suffixes[0]) + for dataset in dataset_list: + file_list = os.listdir(dataset) + if len(file_list) % 2 == 1: + raise RuntimeError("dataset should be parallel corpora") + file_list.sort() + for i in range(0, len(file_list), 2): + if file_list[i][:-suffix_len] != file_list[i + 1][:-suffix_len]: + raise RuntimeError( + "source and target file name should be equal") + + # cat all the files with the same suffix in dataset + for suffix in suffixes: + for dataset in dataset_list: + outname = os.path.basename(dataset) + suffix + self.cat_file(dataset, suffix, dataset, outname) + + # concat parallel corpora and create file.list + print 'concat parallel corpora for dataset' + id = 0 + list = ['train.list', 'test.list', 'gen.list'] + for dataset in dataset_list: + outname = os.path.basename(dataset) + self.concat_file(dataset, outname + suffixes[0], + outname + suffixes[1], dir_list[id], outname) + save_list([os.path.join(dir_list[id], outname)], + os.path.join(self.output_path, list[id])) + id += 1 -from paddle.v2.dataset.wmt14_util import SeqToSeqDatasetCreater + # build dictionary for train data + dict = ['src.dict', 'trg.dict'] + dict_path = [ + os.path.join(self.output_path, dict[0]), + os.path.join(self.output_path, dict[1]) + ] + if mergeDict: + outname = os.path.join(train_dir, train_dataset.split('/')[-1]) + print 'build src dictionary for train data' + self.build_dict(outname, dict_path[0], dict_size) + print 'build trg dictionary for train data' + os.system('cp ' + dict_path[0] + ' ' + dict_path[1]) + else: + outname = os.path.join(train_dataset, self.train_dir_name) + for id in range(0, 2): + suffix = suffixes[id] + print 'build ' + suffix[1:] + ' dictionary for train data' + self.build_dict(outname + suffix, dict_path[id], dict_size) + print 'dictionary size is', self.dict_size def main(): From 1940f58f5393497c4fe7b58e66b695d272ab1e77 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 6 Mar 2017 20:59:29 +0800 Subject: [PATCH 136/153] add bos url --- python/paddle/v2/dataset/wmt14.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/v2/dataset/wmt14.py b/python/paddle/v2/dataset/wmt14.py index f8637c0a00950..f5a16d51477f9 100644 --- a/python/paddle/v2/dataset/wmt14.py +++ b/python/paddle/v2/dataset/wmt14.py @@ -23,7 +23,7 @@ URL_DEV_TEST = 'http://www-lium.univ-lemans.fr/~schwenk/cslm_joint_paper/data/dev+test.tgz' MD5_DEV_TEST = '7d7897317ddd8ba0ae5c5fa7248d3ff5' # this is a small set of data for test. The original data is too large and will be add later. -URL_TRAIN = 'http://localhost:8989/wmt14.tgz' +URL_TRAIN = 'http://paddlepaddle.bj.bcebos.com/demo/wmt_shrinked_data/wmt14.tgz' MD5_TRAIN = 'a755315dd01c2c35bde29a744ede23a6' START = "" From b1c22b67907dce137aafcfd42be33c992d74b1ca Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Tue, 7 Mar 2017 00:59:27 +0800 Subject: [PATCH 137/153] Fix MultiGradientMachine error --- .../gradientmachines/MultiGradientMachine.cpp | 36 ++++++++++++++----- .../gradientmachines/MultiGradientMachine.h | 7 +++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index 123273f916f5d..e7db487e7e896 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -346,7 +346,9 @@ Evaluator* MultiGradientMachine::makeEvaluator() const { void MultiGradientMachine::eval(Evaluator* evaluator) const { for (auto& thread : threads_) { SetDevice device(thread->getDeviceId()); - thread->getGradientMachine()->eval(evaluator); + if (thread->hasInputData()) { + thread->getGradientMachine()->eval(evaluator); + } } } @@ -356,14 +358,20 @@ void MultiGradientMachine::getOutArgs(std::vector* outArgs, REGISTER_TIMER("waitOutArgs"); thread->waitOutArgsReady(); } - outArgs_.resize(threads_[0]->getOutArgs().size()); + // outArgs_.size() only need to be calculated once. + static int size = threads_[threads_.size() - 1]->getOutArgs().size(); + outArgs_.resize(size); REGISTER_TIMER("copyOutArgs"); for (size_t i = 0; i < outArgs_.size(); ++i) { std::vector args; args.reserve(threads_.size()); for (auto& thread : threads_) { - args.push_back(thread->getOutArgs()[i]); + // If the thread input is empty, then the output is empty. + auto tmp = thread->getOutArgs(); + if (tmp.size() > 0) { + args.push_back(tmp[i]); + } } outArgs_[i].concat(args, useGpu_, outArgStream_, passType); } @@ -534,7 +542,7 @@ void TrainerThread::prefetch() { void TrainerThread::forward() { if (!inArgsCopied_) { REGISTER_TIMER("copyInArgs"); - copyInArgs(); + batchSize_ = copyInArgs(); } else { inArgsCopied_ = false; } @@ -564,7 +572,12 @@ void TrainerThread::forward() { { REGISTER_TIMER("thread_forward"); - gradientMachine_->forward(inArgs_, &outArgs_, multiMachine_->getPassType()); + if (batchSize_ > 0) { + gradientMachine_->forward( + inArgs_, &outArgs_, multiMachine_->getPassType()); + } else { + outArgs_.clear(); + } } outArgsReadySem_.post(); } @@ -574,7 +587,13 @@ void TrainerThread::backward() { if (multiMachine_->isPassGrad()) { copyOutputGrad(); } - gradientMachine_->backward(backwardCallback_); + if (batchSize_ > 0) { + gradientMachine_->backward(backwardCallback_); + } else { + for (size_t i = parameters_.size(); i > 0; i--) { + backwardCallback(parameters_[i - 1].get()); + } + } if (multiMachine_->hasNonstaticCpuParamters()) { mergeCpuGradients(); } @@ -732,7 +751,7 @@ void TrainerThread::notifyValueReady(int paramId) { notifyValueDispatch(paramId); } -void TrainerThread::copyInArgs() { +int TrainerThread::copyInArgs() { const std::vector& fullInArgs = multiMachine_->getInArgs(); int numThreads = multiMachine_->getAllThreads().size(); int32_t numSequences = fullInArgs[0].getNumSequences(); @@ -748,7 +767,7 @@ void TrainerThread::copyInArgs() { } if (copySize == 0) { - return; + return 0; } for (size_t i = 0; i < fullInArgs.size(); i++) { @@ -758,6 +777,7 @@ void TrainerThread::copyInArgs() { copySize, FLAGS_parallel_nn ? false : multiMachine_->useGpu()); } + return copySize; } void TrainerThread::mergeCpuGradients() { diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index 838a52b5153af..31bb28b6fedc9 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -387,6 +387,9 @@ class TrainerThread { /// copy the output gradient from the main GradientMachine. void copyOutputGrad(); + /// Whether the thread has input data. + bool hasInputData() { return batchSize_ != 0; } + protected: void mergeCpuGradients(); @@ -407,7 +410,7 @@ class TrainerThread { void copyGradToBufferThread(); void gradCollectThread(); - void copyInArgs(); + int copyInArgs(); void forward(); void backward(); void backwardCallback(Parameter* para); @@ -467,6 +470,8 @@ class TrainerThread { /// indicate whether inArgs is copied before forward() bool inArgsCopied_; + + int batchSize_; }; } // namespace paddle From 9322f8cbf51de19983bce257bff08078739a1224 Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Tue, 7 Mar 2017 10:16:40 +0800 Subject: [PATCH 138/153] Format --- paddle/gserver/gradientmachines/MultiGradientMachine.cpp | 5 +++-- paddle/gserver/gradientmachines/MultiGradientMachine.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index e7db487e7e896..faadca69abd76 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -358,6 +358,7 @@ void MultiGradientMachine::getOutArgs(std::vector* outArgs, REGISTER_TIMER("waitOutArgs"); thread->waitOutArgsReady(); } + // outArgs_.size() only need to be calculated once. static int size = threads_[threads_.size() - 1]->getOutArgs().size(); outArgs_.resize(size); @@ -574,9 +575,9 @@ void TrainerThread::forward() { REGISTER_TIMER("thread_forward"); if (batchSize_ > 0) { gradientMachine_->forward( - inArgs_, &outArgs_, multiMachine_->getPassType()); + inArgs_, &outArgs_, multiMachine_->getPassType()); } else { - outArgs_.clear(); + outArgs_.clear(); } } outArgsReadySem_.post(); diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.h b/paddle/gserver/gradientmachines/MultiGradientMachine.h index 31bb28b6fedc9..70203bbb97fe7 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.h +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.h @@ -470,7 +470,6 @@ class TrainerThread { /// indicate whether inArgs is copied before forward() bool inArgsCopied_; - int batchSize_; }; From 929a390f6c14821be9b4dafd5d150225a23b8cf6 Mon Sep 17 00:00:00 2001 From: gangliao Date: Tue, 7 Mar 2017 11:24:32 +0800 Subject: [PATCH 139/153] Set VGG in image classification demo --- demo/image_classification/api_v2_train.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/image_classification/api_v2_train.py b/demo/image_classification/api_v2_train.py index 7134fa61e861b..53cffa6fb4e8b 100644 --- a/demo/image_classification/api_v2_train.py +++ b/demo/image_classification/api_v2_train.py @@ -16,7 +16,7 @@ import paddle.v2 as paddle -from api_v2_resnet import resnet_cifar10 +from api_v2_vgg import vgg_bn_drop def main(): @@ -31,9 +31,9 @@ def main(): # Add neural network config # option 1. resnet - net = resnet_cifar10(image, depth=32) + # net = resnet_cifar10(image, depth=32) # option 2. vgg - # net = vgg_bn_drop(image) + net = vgg_bn_drop(image) out = paddle.layer.fc(input=net, size=classdim, From 0d2d419a598ceb9deb488e5e3d2f1384635ee9be Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 7 Mar 2017 16:25:09 +0800 Subject: [PATCH 140/153] Follow comments --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/inference.py | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 81b330a60522e..d0aca5eb1d94a 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -113,7 +113,7 @@ def event_handler(event): test_creator = paddle.dataset.mnist.test() test_data = [] for item in test_creator(): - test_data.append(item[0]) + test_data.append((item[0], )) if len(test_data) == 100: break diff --git a/python/paddle/v2/inference.py b/python/paddle/v2/inference.py index 7c079a0d32df6..7d7dc82de987c 100644 --- a/python/paddle/v2/inference.py +++ b/python/paddle/v2/inference.py @@ -43,10 +43,7 @@ def iter_infer(self, def __reader_impl__(): for each_sample in input: - if len(reader_dict) == 1: - yield [each_sample] - else: - yield each_sample + yield each_sample reader = minibatch.batch(__reader_impl__, batch_size=batch_size) else: From 714e9bb95a25e591d6cd6fef9ba047383079aa5b Mon Sep 17 00:00:00 2001 From: gangliao Date: Tue, 7 Mar 2017 17:33:03 +0800 Subject: [PATCH 141/153] Set Protobuf 3.1 in FIND_PACKAGE --- cmake/external/protobuf.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/external/protobuf.cmake b/cmake/external/protobuf.cmake index 26da7e8e384ba..1575d8e9f5613 100644 --- a/cmake/external/protobuf.cmake +++ b/cmake/external/protobuf.cmake @@ -14,7 +14,7 @@ INCLUDE(ExternalProject) -FIND_PACKAGE(Protobuf) +FIND_PACKAGE(Protobuf 3.1) IF(NOT PROTOBUF_FOUND) SET(PROTOBUF_SOURCES_DIR ${THIRD_PARTY_PATH}/protobuf) From df8a5af96f13d5e857b60f08856f4cb369c1fedf Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Wed, 8 Mar 2017 00:19:15 +0800 Subject: [PATCH 142/153] Fix outArgs_.resize() --- paddle/gserver/gradientmachines/MultiGradientMachine.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp index faadca69abd76..4654d0206413e 100644 --- a/paddle/gserver/gradientmachines/MultiGradientMachine.cpp +++ b/paddle/gserver/gradientmachines/MultiGradientMachine.cpp @@ -359,9 +359,7 @@ void MultiGradientMachine::getOutArgs(std::vector* outArgs, thread->waitOutArgsReady(); } - // outArgs_.size() only need to be calculated once. - static int size = threads_[threads_.size() - 1]->getOutArgs().size(); - outArgs_.resize(size); + outArgs_.resize(threads_[threads_.size() - 1]->getOutArgs().size()); REGISTER_TIMER("copyOutArgs"); for (size_t i = 0; i < outArgs_.size(); ++i) { From 71ab4df36625ea5ae6637afbee2b588a513db608 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 8 Mar 2017 13:26:28 +0800 Subject: [PATCH 143/153] Follow comments, remove reader/batch_size in interface. --- demo/mnist/api_train_v2.py | 3 ++- python/paddle/v2/inference.py | 31 +++++++------------------------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 75c2f08132dca..3aa2199bcb712 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -132,7 +132,8 @@ def event_handler(event): # output is a softmax layer. It returns probabilities. # Shape should be (100, 10) - probs = paddle.infer(output=predict, parameters=parameters, input=test_data) + probs = paddle.infer( + output_layer=predict, parameters=parameters, input=test_data) print probs.shape diff --git a/python/paddle/v2/inference.py b/python/paddle/v2/inference.py index 2ad4d9d1ab037..53510d80c9d92 100644 --- a/python/paddle/v2/inference.py +++ b/python/paddle/v2/inference.py @@ -9,8 +9,8 @@ class Inference(object): - def __init__(self, output, parameters): - topo = topology.Topology(output) + def __init__(self, output_layer, parameters): + topo = topology.Topology(output_layer) gm = api.GradientMachine.createFromConfigProto( topo.proto(), api.CREATE_MODE_TESTING, [api.PARAMETER_VALUE]) for param in gm.getParameters(): @@ -70,13 +70,7 @@ def infer(self, field='value', **kwargs): return retv -def infer(output, - parameters, - input=None, - batch_size=None, - reader=None, - feeding=None, - field='value'): +def infer(output_layer, parameters, input=None, feeding=None, field='value'): """ Infer a neural network by given neural network output and parameters. The user should pass either a batch of input data or reader method. @@ -89,19 +83,13 @@ def infer(output, batch_size=32) print result - :param output: output of the neural network that would be inferred - :type output: paddle.v2.config_base.Layer + :param output_layer: output of the neural network that would be inferred + :type output_layer: paddle.v2.config_base.Layer :param parameters: parameters of the neural network. :type parameters: paddle.v2.parameters.Parameters :param input: input data batch. Should be a python iterable object, and each element is the data batch. :type input: collections.Iterable - :param batch_size: the batch size when perform inference. Default is the - length of input. - :type batch_size: int - :param reader: input data reader creator in batch. If this field is set, the - `input` and `batch_size` will be ignored. - :type reader: callable :param feeding: Reader dictionary. Default could generate from input value. :param field: The prediction field. It should in [`value`, `ids`]. `value` @@ -112,10 +100,5 @@ def infer(output, :rtype: numpy.ndarray """ - inferer = Inference(output=output, parameters=parameters) - return inferer.infer( - field=field, - input=input, - batch_size=batch_size, - reader=reader, - feeding=feeding) + inferer = Inference(output_layer=output_layer, parameters=parameters) + return inferer.infer(field=field, input=input, feeding=feeding) From 05b45e1f86e04e16bb94ee2ea75ddfef6029f631 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 8 Mar 2017 13:33:36 +0800 Subject: [PATCH 144/153] Remove reader logic --- python/paddle/v2/inference.py | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/python/paddle/v2/inference.py b/python/paddle/v2/inference.py index 4065f7fe11258..ec3c67d89548f 100644 --- a/python/paddle/v2/inference.py +++ b/python/paddle/v2/inference.py @@ -21,30 +21,16 @@ def __init__(self, output_layer, parameters): self.__gradient_machine__ = gm self.__data_types__ = topo.data_type() - def iter_infer(self, input=None, batch_size=None, reader=None, - feeding=None): + def iter_infer(self, input, feeding=None): feeder = DataFeeder(self.__data_types__, feeding) - if reader is None: - assert input is not None and isinstance(input, collections.Iterable) - if not isinstance(input, collections.Iterable): - raise TypeError("When reader is None, input should be whole " - "inference data and should be iterable") - - if batch_size is None: - if not hasattr(input, '__len__'): - raise ValueError("Should set batch size when input data " - "don't contain length.") - batch_size = len(input) - - def __reader_impl__(): - for each_sample in input: - yield each_sample - - reader = minibatch.batch(__reader_impl__, batch_size=batch_size) - else: - if input is not None: - raise ValueError("User should set either input or reader, " - "should not set them both.") + batch_size = len(input) + + def __reader_impl__(): + for each_sample in input: + yield each_sample + + reader = minibatch.batch(__reader_impl__, batch_size=batch_size) + self.__gradient_machine__.start() for data_batch in reader(): yield self.__gradient_machine__.forwardTest(feeder(data_batch)) From f11cfbe947c5994625d79f88073b80cfda1ed95c Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 8 Mar 2017 15:08:46 +0800 Subject: [PATCH 145/153] Add submodule for book --- .gitmodules | 3 +++ .pre-commit-config.yaml | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000..55dae027fe240 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "book"] + path = book + url = https://github.com/PaddlePaddle/book.git \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a6e45028ebc3f..3402223b044b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,12 +2,12 @@ sha: c25201a00e6b0514370501050cf2a8538ac12270 hooks: - id: remove-crlf - files: (?!.*third_party)^.*$ + files: (?!.*third_party)^.*$ | (?!.*book)^.*$ - repo: https://github.com/reyoung/mirrors-yapf.git sha: v0.13.2 hooks: - id: yapf - files: (.*\.(py|bzl)|BUILD|.*\.BUILD|WORKSPACE)$ # Bazel BUILD files follow Python syntax. + files: (.*\.(py|bzl)|BUILD|.*\.BUILD|WORKSPACE)$ - repo: https://github.com/pre-commit/pre-commit-hooks sha: 7539d8bd1a00a3c1bfd34cdb606d3a6372e83469 hooks: @@ -15,7 +15,7 @@ - id: check-merge-conflict - id: check-symlinks - id: detect-private-key - files: (?!.*third_party)^.*$ + files: (?!.*third_party)^.*$ | (?!.*book)^.*$ - id: end-of-file-fixer - repo: https://github.com/PaddlePaddle/clang-format-pre-commit-hook.git sha: 28c0ea8a67a3e2dbbf4822ef44e85b63a0080a29 From ba13af0d7ef9abe1cc850b05054674c3d02e2550 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 8 Mar 2017 15:09:44 +0800 Subject: [PATCH 146/153] add blank --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 55dae027fe240..c614602cb8eb8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "book"] path = book - url = https://github.com/PaddlePaddle/book.git \ No newline at end of file + url = https://github.com/PaddlePaddle/book.git From dbe96a47752be035a69d2488791ab592c63c2e26 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Wed, 8 Mar 2017 16:02:09 +0800 Subject: [PATCH 147/153] update authors --- authors | 3 +++ 1 file changed, 3 insertions(+) diff --git a/authors b/authors index ab4d3118ff1f7..daac4ec5d8173 100644 --- a/authors +++ b/authors @@ -29,13 +29,16 @@ Luo, Tao Lyu, Qin Mao, Hongyue Qian, Xiaojun +Qiao, Longfei Qi, Jun Qin, Duohao Shen, Guolong Shi, Guangchuan Song, Xiang +Wang, Helin Wang, Jiang Wang, Yanfei +Wang, Yi Wang, Yong Weng, Renliang Xu, Tianbing From 00cce87666e45a065380c4df43e556d27947c87c Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 8 Mar 2017 16:03:49 +0800 Subject: [PATCH 148/153] Add module dir --- book | 1 + 1 file changed, 1 insertion(+) create mode 160000 book diff --git a/book b/book new file mode 160000 index 0000000000000..22ed2a01aee87 --- /dev/null +++ b/book @@ -0,0 +1 @@ +Subproject commit 22ed2a01aee872f055b5f5f212428f481cefc10d From c043d718401e701012d9bdc94482b58e68498518 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 8 Mar 2017 17:59:19 +0800 Subject: [PATCH 149/153] Add Book in Docker --- .../build_and_install/docker_install_en.rst | 25 ++++++++++++++++++- paddle/scripts/docker/Dockerfile | 6 ++--- paddle/scripts/docker/Dockerfile.gpu | 6 ++--- paddle/scripts/docker/build.sh | 3 ++- paddle/scripts/docker/entrypoint | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_en.rst b/doc/getstarted/build_and_install/docker_install_en.rst index 5a1056e859a0c..a92201c618ca7 100644 --- a/doc/getstarted/build_and_install/docker_install_en.rst +++ b/doc/getstarted/build_and_install/docker_install_en.rst @@ -42,7 +42,7 @@ Windows -- in a consistent way. .. code-block:: bash - docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev + docker run -d -p 2202:22 -p 8888:8888 -v $PWD:/paddle paddle:dev This runs a container of the development environment Docker image with the local source tree mounted to :code:`/paddle` of the @@ -82,6 +82,29 @@ Windows -- in a consistent way. cd /paddle/build ctest +4. Run PaddlePaddle Book under Docker Container + + The Jupyter Notebook is an open-source web application that allows + you to create and share documents that contain live code, equations, + visualizations and explanatory text in a single browser. + + PaddlePaddle Book is an interactive Jupyter Notebook for users and developers. + We already exposed port 8888 for this book. If you want to + dig deeper into deep learning, PaddlePaddle Book definitely is your best choice. + + Once you are inside the container, simply issue the command: + + .. code-block:: bash + + jupyter notebook + + Then, you would back and paste the address into the local browser: + + .. code-block:: text + + http://localhost:8888/ + + That's all. Enjoy your journey! CPU-only and GPU Images ----------------------- diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index 98eaa15a0fdf2..fa4aee4f8a922 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -34,6 +34,8 @@ RUN apt-get update && \ # git credential to skip password typing RUN git config --global credential.helper store +# fetch PaddlePaddle book +RUN git submodule update --init --recursive # Fix locales to en_US.UTF-8 RUN localedef -i en_US -f UTF-8 en_US.UTF-8 @@ -60,9 +62,7 @@ RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config EXPOSE 22 -# Jupyter Notebook directory. -RUN mkdir /notes/ -WORKDIR "/notes" +# Jupyter Notebook: Paddle book EXPOSE 8888 COPY ./paddle/scripts/docker/entrypoint /opt/bin/ diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 4d30ccdd2b5de..07b32dda754ae 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -34,6 +34,8 @@ RUN apt-get update && \ # git credential to skip password typing RUN git config --global credential.helper store +# fetch PaddlePaddle book +RUN git submodule update --init --recursive # Fix locales to en_US.UTF-8 RUN localedef -i en_US -f UTF-8 en_US.UTF-8 @@ -60,9 +62,7 @@ RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config EXPOSE 22 -# Jupyter Notebook directory. -RUN mkdir /notes/ -WORKDIR "/notes" +# Jupyter Notebook: Paddle book EXPOSE 8888 COPY ./paddle/scripts/docker/entrypoint /opt/bin/ diff --git a/paddle/scripts/docker/build.sh b/paddle/scripts/docker/build.sh index d9c44f4234032..b2e6416c3d559 100755 --- a/paddle/scripts/docker/build.sh +++ b/paddle/scripts/docker/build.sh @@ -17,7 +17,8 @@ if [[ ${BUILD_AND_INSTALL:-OFF} == 'ON' ]]; then fi mkdir -p /paddle/build # -p means no error if exists - cd /paddle/build + # clean local cmake and third_party cache + cd /paddle/build && rm -rf * && rm -rf ../third_party cmake .. \ -DWITH_DOC=${WITH_DOC:-OFF} \ -DWITH_GPU=${WITH_GPU:-OFF} \ diff --git a/paddle/scripts/docker/entrypoint b/paddle/scripts/docker/entrypoint index 87083467f50ac..cd119917f91ac 100755 --- a/paddle/scripts/docker/entrypoint +++ b/paddle/scripts/docker/entrypoint @@ -4,5 +4,5 @@ LOG=/var/log/all touch $LOG /usr/sbin/sshd -D >> $LOG & -jupyter notebook --ip=0.0.0.0 /notes/ >> $LOG & +jupyter notebook --ip=0.0.0.0 /paddle/book/ >> $LOG & tail -f $LOG From 1ff95e3de121fb72bd230b31c92c75b46f798c0e Mon Sep 17 00:00:00 2001 From: hedaoyuan Date: Wed, 8 Mar 2017 20:42:10 +0800 Subject: [PATCH 150/153] Use v2 attr and pooling fix sentiment train_v2.py --- demo/sentiment/train_v2.py | 48 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/demo/sentiment/train_v2.py b/demo/sentiment/train_v2.py index fd7243cbe6997..1c856556bd0cb 100644 --- a/demo/sentiment/train_v2.py +++ b/demo/sentiment/train_v2.py @@ -13,8 +13,6 @@ # limitations under the License. import sys -import paddle.trainer_config_helpers.attrs as attrs -from paddle.trainer_config_helpers.poolings import MaxPooling import paddle.v2 as paddle @@ -51,16 +49,14 @@ def stacked_lstm_net(input_dim, emb_dim: dimension of word embedding. hid_dim: dimension of hidden layer. stacked_num: number of stacked lstm-hidden layer. - is_predict: is predicting or not. - Some layers is not needed in network when predicting. """ assert stacked_num % 2 == 1 - layer_attr = attrs.ExtraLayerAttribute(drop_rate=0.5) - fc_para_attr = attrs.ParameterAttribute(learning_rate=1e-3) - lstm_para_attr = attrs.ParameterAttribute(initial_std=0., learning_rate=1.) + 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.) para_attr = [fc_para_attr, lstm_para_attr] - bias_attr = attrs.ParameterAttribute(initial_std=0., l2_rate=0.) + bias_attr = paddle.attr.Param(initial_std=0., l2_rate=0.) relu = paddle.activation.Relu() linear = paddle.activation.Linear() @@ -90,8 +86,10 @@ def stacked_lstm_net(input_dim, layer_attr=layer_attr) inputs = [fc, lstm] - fc_last = paddle.layer.pooling(input=inputs[0], pooling_type=MaxPooling()) - lstm_last = paddle.layer.pooling(input=inputs[1], pooling_type=MaxPooling()) + 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()) output = paddle.layer.fc(input=[fc_last, lstm_last], size=class_dim, act=paddle.activation.Softmax(), @@ -105,14 +103,23 @@ def stacked_lstm_net(input_dim, if __name__ == '__main__': # init - paddle.init(use_gpu=False, trainer_count=4) + paddle.init(use_gpu=False) - # network config + #data print 'load dictionary...' word_dict = paddle.dataset.imdb.word_dict() dict_dim = len(word_dict) class_dim = 2 + 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) + + feeding = {'word': 0, 'label': 1} + # network config # Please choose the way to build the network # by uncommenting the corresponding line. cost = convolution_net(dict_dim, class_dim=class_dim) @@ -137,12 +144,7 @@ def event_handler(event): sys.stdout.write('.') sys.stdout.flush() if isinstance(event, paddle.event.EndPass): - result = trainer.test( - reader=paddle.batch( - lambda: paddle.dataset.imdb.test(word_dict), - batch_size=128), - feeding={'word': 0, - 'label': 1}) + result = trainer.test(reader=test_reader, feeding=feeding) print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics) # create trainer @@ -151,11 +153,7 @@ def event_handler(event): update_equation=adam_optimizer) trainer.train( - reader=paddle.batch( - paddle.reader.shuffle( - lambda: paddle.dataset.imdb.train(word_dict), buf_size=1000), - batch_size=100), + reader=train_reader, event_handler=event_handler, - feeding={'word': 0, - 'label': 1}, - num_passes=10) + feeding=feeding, + num_passes=2) From 06690cfb015ebc11d4190d751f98971f350d8316 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Wed, 8 Mar 2017 22:39:10 +0800 Subject: [PATCH 151/153] add l2 regularization to reduce the probability of fpe exception --- demo/seqToseq/api_train_v2.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/demo/seqToseq/api_train_v2.py b/demo/seqToseq/api_train_v2.py index 6efd254e7a487..5d138a8c4f919 100644 --- a/demo/seqToseq/api_train_v2.py +++ b/demo/seqToseq/api_train_v2.py @@ -1,3 +1,4 @@ +import sys import paddle.v2 as paddle @@ -104,7 +105,9 @@ def main(): parameters = paddle.parameters.create(cost) # define optimize method and trainer - optimizer = paddle.optimizer.Adam(learning_rate=1e-4) + optimizer = paddle.optimizer.Adam( + learning_rate=5e-5, + regularization=paddle.optimizer.L2Regularization(rate=1e-3)) trainer = paddle.trainer.SGD(cost=cost, parameters=parameters, update_equation=optimizer) @@ -125,8 +128,11 @@ def main(): def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 10 == 0: - print "Pass %d, Batch %d, Cost %f, %s" % ( + 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() # start to train trainer.train( From ca9249645d410fb01adee3bb37ea213257ef24a0 Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 8 Mar 2017 16:27:59 -0800 Subject: [PATCH 152/153] translate install paddle using docker to chinese --- .../build_and_install/docker_install_cn.rst | 196 ++++++++---------- 1 file changed, 86 insertions(+), 110 deletions(-) diff --git a/doc/getstarted/build_and_install/docker_install_cn.rst b/doc/getstarted/build_and_install/docker_install_cn.rst index 6b132d2a4d31a..78f518cfe49d8 100644 --- a/doc/getstarted/build_and_install/docker_install_cn.rst +++ b/doc/getstarted/build_and_install/docker_install_cn.rst @@ -1,158 +1,134 @@ -安装PaddlePaddle的Docker镜像 -============================ +PaddlePaddle的Docker容器使用方式 +================================ -PaddlePaddle项目提供官方 `Docker `_ 镜像。Docker镜像是我们目前唯一官方支持的部署和运行方式。 +PaddlePaddle目前唯一官方支持的运行的方式是Docker容器。因为Docker能在所有主要操作系统(包括Linux,Mac OS X和Windows)上运行。 请注意,您需要更改 `Dockers设置 `_ 才能充分利用Mac OS X和Windows上的硬件资源。 -下述内容将分为如下几个类别描述。 -* PaddlePaddle提供的Docker镜像版本 -* 下载和运行Docker镜像 -* 注意事项 +通过Docker容器开发PaddlePaddle +------------------------------ -PaddlePaddle提供的Docker镜像版本 --------------------------------- +开发人员可以在Docker中开发PaddlePaddle。这样开发人员可以以一致的方式在不同的平台上工作 - Linux,Mac OS X和Windows。 -我们提供了12个 `Docker image `_ ,他们的image name都是 :code:`paddledev/paddle` ,tag分别为 +1. 将开发环境构建为Docker镜像 + + .. code-block:: bash -+-----------------+------------------+------------------------+-----------------------+ -| | normal | devel | demo | -+=================+==================+========================+=======================+ -| CPU | cpu-latest | cpu-devel-latest | cpu-demo-latest | -+-----------------+------------------+------------------------+-----------------------+ -| GPU | gpu-latest | gpu-devel-latest | gpu-demo-latest | -+-----------------+------------------+------------------------+-----------------------+ -| CPU WITHOUT AVX | cpu-noavx-latest | cpu-noavx-devel-latest | cpu-noavx-demo-latest | -+-----------------+------------------+------------------------+-----------------------+ -| GPU WITHOUT AVX | gpu-noavx-latest | gpu-noavx-devel-latest | gpu-noavx-demo-latest | -+-----------------+------------------+------------------------+-----------------------+ + git clone --recursive https://github.com/PaddlePaddle/Paddle + cd Paddle + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile . -其中,横向包括三个版本,normal,devel和demo。 -* Normal: 正常的Docker image,只包括paddle的二进制 -* Devel: 包括Paddle的二进制、编译环境和源代码 -* Demo: 包括Paddle运行demo所需要的依赖 + 请注意,默认情况下,:code:`docker build` 不会将源码导入到镜像中并编译它。如果我们想这样做,需要设置一个参数: -纵向包括四个版本,他们是。 + .. code-block:: bash -* CPU: CPU版本。需要支持AVX指令集的CPU -* GPU: GPU版本。需要支持AVX指令集的CPU -* CPU WITHOUT AVX: CPU版本,不支持AVX指令集的CPU也可以运行 -* GPU WITHOUT AVX: GPU版本,不需要AVX指令集的CPU也可以运行。 + docker build -t paddle:dev -f paddle/scripts/docker/Dockerfile --build-arg BUILD_AND_INSTALL=ON . -用户可以选择对应版本的docker image。使用如下脚本可以确定本机的CPU是否支持 :code:`AVX` 指令集\: -.. code-block:: bash +2. 运行开发环境 - if cat /proc/cpuinfo | grep -q avx ; then echo "Support AVX"; else echo "Not support AVX"; fi + 当我们编译好了 :code:`paddle:dev`, 我们可以在docker容器里做开发,源代码可以通过挂载本地文件来被载入Docker的开发环境里面: + + .. code-block:: bash -如果输出 :code:`Support AVX`,则可以选择上表中的AVX版本PaddlePaddle。否则需要选择非AVX的PaddlePaddle。选择普通CPU版本的devel版本的image,则可以使用 :code:`paddledev/paddle:cpu-devel-latest` 来引用这个image。 + docker run -d -p 2202:22 -v $PWD:/paddle paddle:dev -PaddlePaddle提供的镜像并不包含任何命令运行,想要运行PaddlePaddle,您需要进入镜像运行PaddlePaddle -程序或者自定义一个含有启动脚本的image。具体请参考注意事项中的 :code:`使用ssh访问PaddlePaddle镜像` + 以上代码会启动一个带有PaddlePaddle开发环境的docker容器,源代码会被挂载到 :code:`/paddle` 。 -下载和运行Docker镜像 --------------------- + 请注意, :code:`paddle:dev` 的默认入口是 :code:`sshd` 。以上的 :code:`docker run` 命令其实会启动一个在2202端口监听的SSHD服务器。这样,我们就能SSH进入我们的开发容器了: + + .. code-block:: bash -为了运行PaddlePaddle的docker镜像,您需要在机器中安装好Docker。安装Docker需要您的机器 -至少具有3.10以上的linux kernel。安装方法请参考 -`Docker的官方文档 `_ 。如果您使用 -mac osx或者是windows机器,请参考 -`mac osx的安装文档 `_ 和 -`windows 的安装文档 `_ 。 + ssh root@localhost -p 2202 -您可以使用 :code:`docker pull` 命令预先下载镜像,也可以直接执行 -:code:`docker run` 命令运行镜像。执行方法如下: +3. 在Docker开发环境中编译与安装PaddlPaddle代码 -.. code-block:: bash - - $ docker run -it paddledev/paddle:cpu-latest + 当在容器里面的时候,可以用脚本 :code:`paddle/scripts/docker/build.sh` 来编译、安装与测试PaddlePaddle: + + .. code-block:: bash + + /paddle/paddle/scripts/docker/build.sh -即可启动和进入PaddlePaddle的container。如果运行GPU版本的PaddlePaddle,则需要先将 -cuda相关的Driver和设备映射进container中,脚本类似于 + 以上指令会在 :code:`/paddle/build` 中编译PaddlePaddle。通过以下指令可以运行单元测试: + + .. code-block:: bash -.. code-block:: bash + cd /paddle/build + ctest - $ export CUDA_SO="$(\ls /usr/lib64/libcuda* | xargs -I{} echo '-v {}:{}') $(\ls /usr/lib64/libnvidia* | xargs -I{} echo '-v {}:{}')" - $ export DEVICES=$(\ls /dev/nvidia* | xargs -I{} echo '--device {}:{}') - $ docker run ${CUDA_SO} ${DEVICES} -it paddledev/paddle:gpu-latest -进入Docker container后,运行 :code:`paddle version` 即可打印出PaddlePaddle的版本和构建 -信息。安装完成的PaddlePaddle主体包括三个部分, :code:`paddle` 脚本, python的 -:code:`paddle` 包和 :code:`py_paddle` 包。其中\: +纯CPU和GPU的docker镜像 +---------------------- -* :code:`paddle` 脚本和 :code:`paddle` 的python包是PaddlePaddle的训练主要程序。使用 - :code:`paddle` 脚本可以启动PaddlePaddle的训练进程和pserver。而 :code:`paddle` 脚本 - 中的二进制使用了 :code:`paddle` 的python包来做配置文件解析等工作。 -* python包 :code:`py_paddle` 是一个swig封装的PaddlePaddle包,用来做预测和简单的定制化 - 训练。 +对于每一个PaddlePaddle版本,我们都会发布两个Docker镜像:纯CPU的和GPU的。我们通过设置 `dockerhub.com `_ 自动运行以下两个命令: -注意事项 --------- +.. code-block:: bash -性能问题 -++++++++ + docker build -t paddle:cpu -f paddle/scripts/docker/Dockerfile . + docker build -t paddle:gpu -f paddle/scripts/docker/Dockerfile.gpu . -由于Docker是基于容器的轻量化虚拟方案,所以在CPU的运算性能上并不会有严重的影响。 -而GPU的驱动和设备全部映射到了容器内,所以GPU在运算性能上也不会有严重的影响。 +以交互容器方式运行纯CPU的镜像: -但是如果使用了高性能的网卡,例如RDMA网卡(RoCE 40GbE 或者 IB 56GbE),或者高性能的 -以太网卡 (10GbE)。推荐使用将本地网卡,即 "--net=host" 来进行训练。而不使用docker -的网桥来进行网络通信。 +.. code-block:: bash -远程访问问题和二次开发 -++++++++++++++++++++++ + docker run -it --rm paddledev/paddle:cpu-latest /bin/bash -由于PaddlePaddle的Docker镜像并不包含任何预定义的运行命令。所以如果想要在后台启用ssh -远程访问,则需要进行一定的二次开发,将ssh装入系统内并开启远程访问。二次开发可以 -使用Dockerfile构建一个全新的docker image。需要参考 -`Dockerfile的文档 `_ 和 -`Dockerfile的最佳实践 `_ -两个文档。 +或者,可以以后台进程方式运行容器: -简单的含有ssh的Dockerfile如下: +.. code-block:: bash -.. code-block:: bash + docker run -d -p 2202:22 paddledev/paddle:cpu-latest - FROM paddledev/paddle:cpu-latest +然后用密码 :code:`root` SSH进入容器: - MAINTAINER PaddlePaddle dev team +.. code-block:: bash - RUN apt-get update - RUN apt-get install -y openssh-server - RUN mkdir /var/run/sshd - RUN echo 'root:root' | chpasswd + ssh -p 2202 root@localhost - RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config - RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config +SSH方式的一个优点是我们可以从多个终端进入容器。比如,一个终端运行vi,另一个终端运行Python。另一个好处是我们可以把PaddlePaddle容器运行在远程服务器上,并在笔记本上通过SSH与其连接。 - EXPOSE 22 - CMD ["/usr/sbin/sshd", "-D"] +以上方法在GPU镜像里也能用-只是请不要忘记按装CUDA驱动,以及告诉Docker: +.. code-block:: bash -使用该Dockerfile构建出镜像,然后运行这个container即可。相关命令为\: + export CUDA_SO="$(\ls /usr/lib64/libcuda* | xargs -I{} echo '-v {}:{}') $(\ls /usr/lib64/libnvidia* | xargs -I{} echo '-v {}:{}')" + export DEVICES=$(\ls /dev/nvidia* | xargs -I{} echo '--device {}:{}') + docker run ${CUDA_SO} ${DEVICES} -it paddledev/paddle:gpu-latest -.. code-block:: bash - # cd到含有Dockerfile的路径中 - $ docker build . -t paddle_ssh - # 运行这个container,将宿主机的8022端口映射到container的22端口上 - $ docker run -d -p 8022:22 --name paddle_ssh_machine paddle_ssh +非AVX镜像 +--------- -执行如下命令即可以关闭这个container,并且删除container中的数据\: +纯CPU镜像以及GPU镜像都会用到AVX指令集,但是2008年之前生产的旧电脑不支持AVX。以下指令能检查Linux电脑是否支持AVX: -.. code-block:: bash - - # 关闭container - $ docker stop paddle_ssh_machine - # 删除container - $ docker rm paddle_ssh_machine -如果想要在外部机器访问这个container,即可以使用ssh访问宿主机的8022端口。用户名为 -root,密码也是root。命令为\: +.. code-block:: bash -.. code-block:: bash + if cat /proc/cpuinfo | grep -i avx; then echo Yes; else echo No; fi - $ ssh -p 8022 root@YOUR_HOST_MACHINE +如果输出是No,我们就需要手动编译一个非AVX版本的镜像: -至此,您就可以远程的使用PaddlePaddle啦。 +.. code-block:: bash + + cd ~ + git clone https://github.com/PaddlePaddle/Paddle.git + cd Paddle + docker build --build-arg WITH_AVX=OFF -t paddle:cpu-noavx -f paddle/scripts/docker/Dockerfile . + docker build --build-arg WITH_AVX=OFF -t paddle:gpu-noavx -f paddle/scripts/docker/Dockerfile.gpu . + + +文档 +---- + +Paddle的Docker镜像带有一个通过 `woboq code browser +`_ 生成的HTML版本的C++源代码,便于用户浏览C++源码。 + +只要在Docker里启动PaddlePaddle的时候给它一个名字,就可以再运行另一个Nginx Docker镜像来服务HTML代码: + +.. code-block:: bash + + docker run -d --name paddle-cpu-doc paddle:cpu + docker run -d --volumes-from paddle-cpu-doc -p 8088:80 nginx + +接着我们就能够打开浏览器在 http://localhost:8088/paddle/ 浏览代码。 From b48ebd16c833ab5d6036c4ba9e6f897667ba5f33 Mon Sep 17 00:00:00 2001 From: liaogang Date: Thu, 9 Mar 2017 09:51:10 +0800 Subject: [PATCH 153/153] Fix git submodule in docker --- paddle/scripts/docker/Dockerfile | 4 ++-- paddle/scripts/docker/Dockerfile.gpu | 4 ++-- paddle/scripts/docker/entrypoint | 8 ++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/paddle/scripts/docker/Dockerfile b/paddle/scripts/docker/Dockerfile index fa4aee4f8a922..6435923c890e9 100644 --- a/paddle/scripts/docker/Dockerfile +++ b/paddle/scripts/docker/Dockerfile @@ -34,8 +34,6 @@ RUN apt-get update && \ # git credential to skip password typing RUN git config --global credential.helper store -# fetch PaddlePaddle book -RUN git submodule update --init --recursive # Fix locales to en_US.UTF-8 RUN localedef -i en_US -f UTF-8 en_US.UTF-8 @@ -52,7 +50,9 @@ RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ cd .. && rm -rf cmake-3.4.1 COPY . /paddle/ +RUN cd /paddle/ && git submodule update --init --recursive RUN /paddle/paddle/scripts/docker/build.sh + VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"] # Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service diff --git a/paddle/scripts/docker/Dockerfile.gpu b/paddle/scripts/docker/Dockerfile.gpu index 07b32dda754ae..06e53a0ef3e27 100644 --- a/paddle/scripts/docker/Dockerfile.gpu +++ b/paddle/scripts/docker/Dockerfile.gpu @@ -34,8 +34,6 @@ RUN apt-get update && \ # git credential to skip password typing RUN git config --global credential.helper store -# fetch PaddlePaddle book -RUN git submodule update --init --recursive # Fix locales to en_US.UTF-8 RUN localedef -i en_US -f UTF-8 en_US.UTF-8 @@ -52,7 +50,9 @@ RUN curl -sSL https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz | tar -xz && \ cd .. && rm -rf cmake-3.4.1 COPY . /paddle/ +RUN cd /paddle/ && git submodule update --init --recursive RUN /paddle/paddle/scripts/docker/build.sh + VOLUME ["/usr/share/nginx/html/data", "/usr/share/nginx/html/paddle"] # Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service diff --git a/paddle/scripts/docker/entrypoint b/paddle/scripts/docker/entrypoint index cd119917f91ac..bc194bd909aa3 100755 --- a/paddle/scripts/docker/entrypoint +++ b/paddle/scripts/docker/entrypoint @@ -1,8 +1,4 @@ #!/bin/bash -LOG=/var/log/all -touch $LOG - -/usr/sbin/sshd -D >> $LOG & -jupyter notebook --ip=0.0.0.0 /paddle/book/ >> $LOG & -tail -f $LOG +/usr/sbin/sshd -D & +jupyter notebook --ip=0.0.0.0 /paddle/book/