From 07539b2a1c9976b8d4ba5c13b498d16d5288b1f4 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 10:23:23 +0800 Subject: [PATCH 01/17] add-topology --- python/paddle/v2/__init__.py | 3 ++- python/paddle/v2/topology.py | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/topology.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index c0a2bdc425..cf01f37a33 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -18,11 +18,12 @@ import parameters import trainer import event import data_type +import topology import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type.py' + 'event', 'data_type', 'topology' ] diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py new file mode 100644 index 0000000000..ddba1b2345 --- /dev/null +++ b/python/paddle/v2/topology.py @@ -0,0 +1,44 @@ +# 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 . import layer + +__all__ = ['Topology'] + + +class Topology(object): + """ + Topology is used to store the information about all layers + and network configs. + """ + + def __init__(self, cost): + self.cost = cost + self.__model_config__ = layer.parse_network(cost) + + def __call__(self): + return self.__model_config__ + + def get_layer(self, name): + """ + get layer by layer name + :param name: + :return: + """ + pass + + def data_type(self): + """ + """ + pass From 7cfe34da7c99c541189cb73165bc022bbc4289c0 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 21 Feb 2017 23:53:42 +0800 Subject: [PATCH 02/17] modify api_train_v2 --- demo/mnist/api_train_v2.py | 20 ++++--- python/paddle/v2/layer.py | 8 ++- python/paddle/v2/parameters.py | 21 ++++---- python/paddle/v2/topology.py | 96 +++++++++++++++++++++++++++++++--- python/paddle/v2/trainer.py | 20 +++---- 5 files changed, 119 insertions(+), 46 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index 6fc01ce58b..f6edd1f34f 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,7 +26,9 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - parameters = paddle.parameters.create(cost) + topology = paddle.topology.Topology(cost) + + parameters = paddle.parameters.create(topology) for param_name in parameters.keys(): array = parameters.get(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) @@ -45,16 +47,12 @@ def main(): trainer = paddle.trainer.SGD(update_equation=adam_optimizer) - trainer.train(train_data_reader=train_reader, - topology=cost, - parameters=parameters, - event_handler=event_handler, - batch_size=32, # batch size should be refactor in Data reader - data_types={ # data_types will be removed, It should be in - # network topology - 'pixel': images.type, - 'label': label.type - }) + trainer.train( + train_data_reader=train_reader, + topology=topology, + parameters=parameters, + event_handler=event_handler, + batch_size=32) # batch size should be refactor in Data reader if __name__ == '__main__': diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4d052c983c..5f146c8c03 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -66,12 +66,14 @@ Also, the creation of a protobuf message is hidden in the invocation of paddle.v2.parameters.create, no longer exposed to users. """ +import collections + import paddle.trainer_config_helpers as conf_helps -from . import data_type as v2_data from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import collections + +import data_type as v2_data __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', @@ -184,6 +186,8 @@ class DataLayerV2(Layer): return getattr(conf_helps, self.__method_name__)(name=self.name, **args) +LayerV2 = Layer + data = DataLayerV2 fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) max_id = __convert_to_v2__( diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index ea504d5104..b569afe3a1 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -1,26 +1,23 @@ import numpy as np -from . import layer as v2_layer import py_paddle.swig_paddle as api from paddle.proto.ParameterConfig_pb2 import ParameterConfig +import topology as v2_topology + __all__ = ['Parameters', 'create'] -def create(*layers): +def create(topology): """ - Create parameter pool by layers. In paddle, layer can be represent a - model config. - - :param layers: + Create parameter pool by topology. + :param topology: :return: """ - for layer in layers: - if not isinstance(layer, v2_layer.Layer): - raise ValueError( - 'create must pass a topologies which type is paddle.layer.Layer') - model_config = v2_layer.parse_network(*layers) + if not isinstance(topology, v2_topology.Topology): + raise ValueError( + 'create must pass a topology which type is topology.Topology') pool = Parameters() - for param in model_config.parameters: + for param in topology.proto().parameters: pool.__append_config__(param) return pool diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index ddba1b2345..6508b3ce88 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from . import layer +from paddle.proto.ModelConfig_pb2 import ModelConfig +import paddle.trainer_config_helpers as conf_helps +import layer as v2_layer +import data_type __all__ = ['Topology'] @@ -23,22 +26,101 @@ class Topology(object): and network configs. """ - def __init__(self, cost): - self.cost = cost - self.__model_config__ = layer.parse_network(cost) + def __init__(self, *layers): + for layer in layers: + if not isinstance(layer, v2_layer.LayerV2): + raise ValueError('create must pass a topologies ' + 'which type is paddle.layer.Layer') + self.layers = layers + self.__model_config__ = v2_layer.parse_network(*layers) + assert isinstance(self.__model_config__, ModelConfig) - def __call__(self): + def proto(self): return self.__model_config__ def get_layer(self, name): + """ + get v2.Layer Class instance by layer name + :param name: + :return: + """ + result_layer = [] + + def find_layer_by_name(layer, layer_name): + if layer.name == layer_name and len(result_layer) == 0: + result_layer.append(layer) + for parent_layer in layer.__parent_layers__.values(): + find_layer_by_name(parent_layer, layer_name) + + for layer in self.layers: + find_layer_by_name(layer, name) + + return result_layer[0] + + def get_data_layer(self): + """ + get all data layer + :return: + """ + data_layers = [] + + def find_data_layer(layer): + assert isinstance(layer, layer.LayerV2) + if isinstance(layer, v2_layer.DataLayerV2): + if len( + filter(lambda data_layer: data_layer.name == layer.name, + data_layers)) == 0: + data_layers.append(layer) + for parent_layer in layer.__parent_layers__.values(): + find_data_layer(parent_layer) + + for layer in self.layers: + find_data_layer(layer) + + return data_layers + + def get_layer_proto(self, name): """ get layer by layer name :param name: :return: """ - pass + layers = filter(lambda layer: layer.name == name, + self.__model_config__.layers) + if len(layers) is 1: + return layers[0] + else: + return None def data_type(self): """ + get data_type from proto, such as: + [('image', dense_vector(768)), ('label', integer_value(10))] + the order is the same with __model_config__.input_layer_names """ - pass + data_types_lists = [] + for layer_name in self.__model_config__.input_layer_names: + data_types_lists.append( + (layer_name, self.get_layer(layer_name).type)) + + return data_types_lists + + +if __name__ == '__main__': + pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) + label = v2_layer.data(name='label', type=data_type.integer_value(10)) + hidden = v2_layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = v2_layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = v2_layer.max_id(input=inference) + cost1 = v2_layer.classification_cost(input=inference, label=label) + cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) + + print Topology(cost1).proto() + print Topology(cost2).proto() + print Topology(cost1, cost2).proto() + print Topology(cost2).proto() + print Topology(inference, maxid).proto() diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 4365bd41e7..c8da6e70cf 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,13 +1,12 @@ import collections import py_paddle.swig_paddle as api -from paddle.proto.ModelConfig_pb2 import ModelConfig from py_paddle import DataProviderConverter from . import event as v2_event -from . import layer as v2_layer from . import optimizer as v2_optimizer from . import parameters as v2_parameters +from . import topology as v2_topology __all__ = ['ITrainer', 'SGD'] @@ -88,12 +87,11 @@ class SGD(ITrainer): if event_handler is None: event_handler = default_event_handler - topology = v2_layer.parse_network(topology) - __check_train_args__(**locals()) gm = api.GradientMachine.createFromConfigProto( - topology, api.CREATE_MODE_NORMAL, self.__optimizer__.enable_types()) + topology.proto(), api.CREATE_MODE_NORMAL, + self.__optimizer__.enable_types()) assert isinstance(gm, api.GradientMachine) parameters.append_gradient_machine(gm) @@ -102,13 +100,7 @@ class SGD(ITrainer): gm.start() out_args = api.Arguments.createArguments(0) - - data_types_lists = [] - for each in topology.input_layer_names: - if each not in data_types: - raise ValueError() - data_types_lists.append(data_types[each]) - + data_types_lists = [data_type[1] for data_type in topology.data_type()] converter = DataProviderConverter(input_types=data_types_lists) for pass_id in xrange(num_passes): @@ -141,7 +133,7 @@ def __data_reader_to_batch__(reader, batch_size, topology): def input_reorder(func): for item in func(): retv = [] - for __layer_name__ in topology.input_layer_names: + for __layer_name__ in topology.proto().input_layer_names: retv.append(item[__layer_name__]) yield retv @@ -178,7 +170,7 @@ def __check_train_args__(train_data_reader, topology, parameters, raise ValueError('test_data_reader should be a function, which can ' 'return a iterator') - if not isinstance(topology, ModelConfig): + if not isinstance(topology, v2_topology.Topology): raise ValueError('topology should be a model config') if not isinstance(parameters, v2_parameters.Parameters): From b9dd33f815ed94237ddda930c99db838b76460e1 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 23 Feb 2017 23:30:17 +0800 Subject: [PATCH 03/17] hide Topology --- demo/mnist/api_train_v2.py | 6 ++---- python/paddle/v2/parameters.py | 8 +++----- python/paddle/v2/topology.py | 14 +++++++++----- python/paddle/v2/trainer.py | 4 +++- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index f6edd1f34f..cc45229fbd 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,9 +26,7 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - topology = paddle.topology.Topology(cost) - - parameters = paddle.parameters.create(topology) + parameters = paddle.parameters.create([cost]) for param_name in parameters.keys(): array = parameters.get(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) @@ -49,7 +47,7 @@ def main(): trainer.train( train_data_reader=train_reader, - topology=topology, + topology=[cost], parameters=parameters, event_handler=event_handler, batch_size=32) # batch size should be refactor in Data reader diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index b569afe3a1..b8d4b28703 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -7,15 +7,13 @@ import topology as v2_topology __all__ = ['Parameters', 'create'] -def create(topology): +def create(layers): """ Create parameter pool by topology. - :param topology: + :param layers: :return: """ - if not isinstance(topology, v2_topology.Topology): - raise ValueError( - 'create must pass a topology which type is topology.Topology') + topology = v2_topology.Topology(layers) pool = Parameters() for param in topology.proto().parameters: pool.__append_config__(param) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 6508b3ce88..bfd7ef171a 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from paddle.proto.ModelConfig_pb2 import ModelConfig +import collections + import paddle.trainer_config_helpers as conf_helps -import layer as v2_layer +from paddle.proto.ModelConfig_pb2 import ModelConfig + import data_type +import layer as v2_layer __all__ = ['Topology'] @@ -26,11 +29,12 @@ class Topology(object): and network configs. """ - def __init__(self, *layers): + def __init__(self, layers): + if not isinstance(layers, collections.Sequence): + raise ValueError("input of Topology should be a list of Layer") for layer in layers: if not isinstance(layer, v2_layer.LayerV2): - raise ValueError('create must pass a topologies ' - 'which type is paddle.layer.Layer') + raise ValueError('layer should have type paddle.layer.Layer') self.layers = layers self.__model_config__ = v2_layer.parse_network(*layers) assert isinstance(self.__model_config__, ModelConfig) diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index c8da6e70cf..969aa6e0e0 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -73,7 +73,7 @@ class SGD(ITrainer): Training method. Will train num_passes of input data. :param train_data_reader: - :param topology: Network Topology, use one or more Layers to represent it. + :param topology: cost layers, use one or more Layers to represent it. :param parameters: The parameter pools. :param num_passes: The total train passes. :param test_data_reader: @@ -87,6 +87,8 @@ class SGD(ITrainer): if event_handler is None: event_handler = default_event_handler + topology = v2_topology.Topology(topology) + __check_train_args__(**locals()) gm = api.GradientMachine.createFromConfigProto( From 775f019fa1d9fcd120ae6fc66f5c0caa9333ebca Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 23 Feb 2017 23:44:57 +0800 Subject: [PATCH 04/17] remove unused get_layer_proto in Topology --- python/paddle/v2/topology.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index bfd7ef171a..3e07c4106e 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -83,19 +83,6 @@ class Topology(object): return data_layers - def get_layer_proto(self, name): - """ - get layer by layer name - :param name: - :return: - """ - layers = filter(lambda layer: layer.name == name, - self.__model_config__.layers) - if len(layers) is 1: - return layers[0] - else: - return None - def data_type(self): """ get data_type from proto, such as: From 909bd2690adb96cc68852856b9a6d8643459ca73 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 10:05:35 +0800 Subject: [PATCH 05/17] add topology test --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/data_type.py | 4 +- python/paddle/v2/tests/CMakeLists.txt | 4 ++ python/paddle/v2/tests/topology_test.py | 79 +++++++++++++++++++++++++ python/paddle/v2/topology.py | 14 +++-- 5 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 python/paddle/v2/tests/CMakeLists.txt create mode 100644 python/paddle/v2/tests/topology_test.py diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index cc45229fbd..99cc344a5e 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -26,7 +26,7 @@ def main(): act=paddle.activation.Softmax()) cost = paddle.layer.classification_cost(input=inference, label=label) - parameters = paddle.parameters.create([cost]) + parameters = paddle.parameters.create(cost) for param_name in parameters.keys(): array = parameters.get(param_name) array[:] = numpy.random.uniform(low=-1.0, high=1.0, size=array.shape) diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index 5b01ba4cd4..cd9ce6e513 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -14,9 +14,9 @@ from paddle.trainer.PyDataProvider2 import \ InputType, dense_vector, sparse_binary_vector,\ - sparse_vector, integer_value + sparse_vector, integer_value, DataType __all__ = [ 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', - 'integer_value' + 'integer_value', 'DataType' ] diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt new file mode 100644 index 0000000000..3a257af2fc --- /dev/null +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +add_test(NAME topology_test + COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/topology_test.py + WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/topology_test.py new file mode 100644 index 0000000000..7360ed8f7b --- /dev/null +++ b/python/paddle/v2/tests/topology_test.py @@ -0,0 +1,79 @@ +# 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 unittest +import paddle.v2.layer as layer +import paddle.v2.topology as topology +import paddle.v2.data_type as data_type +import paddle.trainer_config_helpers as conf_helps + + +class TestTopology(unittest.TestCase): + def test_parse(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = layer.max_id(input=inference) + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.cross_entropy_cost(input=inference, label=label) + + print topology.Topology(cost2).proto() + print topology.Topology([cost1]).proto() + print topology.Topology([cost1, cost2]).proto() + print topology.Topology(cost2).proto() + print topology.Topology([inference, maxid]).proto() + + def test_data_type(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + cost = layer.classification_cost(input=inference, label=label) + topo = topology.Topology(cost) + type = topo.data_type() + self.assertEqual(len(type), 2) + self.assertEqual(type[0][0], "pixel") + self.assertEqual(type[0][1].type, data_type.DataType.Dense) + self.assertEqual(type[0][1].dim, 784) + self.assertEqual(type[1][0], "label") + self.assertEqual(type[1][1].type, data_type.DataType.Index) + self.assertEqual(type[1][1].dim, 10) + + def test_get_layer(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + cost = layer.classification_cost(input=inference, label=label) + topo = topology.Topology(cost) + pixel_layer = topo.get_layer("pixel") + label_layer = topo.get_layer("label") + self.assertEqual(pixel_layer, pixel) + self.assertEqual(label_layer, label) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 3e07c4106e..28cc8892e1 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -31,7 +31,8 @@ class Topology(object): def __init__(self, layers): if not isinstance(layers, collections.Sequence): - raise ValueError("input of Topology should be a list of Layer") + __check_layer_type__(layers) + layers = [layers] for layer in layers: if not isinstance(layer, v2_layer.LayerV2): raise ValueError('layer should have type paddle.layer.Layer') @@ -97,6 +98,11 @@ class Topology(object): return data_types_lists +def __check_layer_type__(layer): + if not isinstance(layer, v2_layer.LayerV2): + raise ValueError('layer should have type paddle.layer.Layer') + + if __name__ == '__main__': pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) label = v2_layer.data(name='label', type=data_type.integer_value(10)) @@ -110,8 +116,8 @@ if __name__ == '__main__': cost1 = v2_layer.classification_cost(input=inference, label=label) cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) - print Topology(cost1).proto() print Topology(cost2).proto() - print Topology(cost1, cost2).proto() + print Topology([cost1]).proto() + print Topology([cost1, cost2]).proto() print Topology(cost2).proto() - print Topology(inference, maxid).proto() + print Topology([inference, maxid]).proto() From 12cac800acf29c39c717e03f934abe35ad5ab0e7 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 10:13:53 +0800 Subject: [PATCH 06/17] clean topology.py --- python/paddle/v2/tests/topology_test.py | 37 ++++++++++++------------- python/paddle/v2/topology.py | 24 +--------------- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/topology_test.py index 7360ed8f7b..be60a577be 100644 --- a/python/paddle/v2/tests/topology_test.py +++ b/python/paddle/v2/tests/topology_test.py @@ -19,25 +19,6 @@ import paddle.trainer_config_helpers as conf_helps class TestTopology(unittest.TestCase): - def test_parse(self): - pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) - label = layer.data(name='label', type=data_type.integer_value(10)) - hidden = layer.fc(input=pixel, - size=100, - act=conf_helps.SigmoidActivation()) - inference = layer.fc(input=hidden, - size=10, - act=conf_helps.SoftmaxActivation()) - maxid = layer.max_id(input=inference) - cost1 = layer.classification_cost(input=inference, label=label) - cost2 = layer.cross_entropy_cost(input=inference, label=label) - - print topology.Topology(cost2).proto() - print topology.Topology([cost1]).proto() - print topology.Topology([cost1, cost2]).proto() - print topology.Topology(cost2).proto() - print topology.Topology([inference, maxid]).proto() - def test_data_type(self): pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -74,6 +55,24 @@ class TestTopology(unittest.TestCase): self.assertEqual(pixel_layer, pixel) self.assertEqual(label_layer, label) + def test_parse(self): + pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) + label = layer.data(name='label', type=data_type.integer_value(10)) + hidden = layer.fc(input=pixel, + size=100, + act=conf_helps.SigmoidActivation()) + inference = layer.fc(input=hidden, + size=10, + act=conf_helps.SoftmaxActivation()) + maxid = layer.max_id(input=inference) + cost1 = layer.classification_cost(input=inference, label=label) + cost2 = layer.cross_entropy_cost(input=inference, label=label) + + topology.Topology(cost2).proto() + topology.Topology([cost1]).proto() + topology.Topology([cost1, cost2]).proto() + topology.Topology([inference, maxid]).proto() + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 28cc8892e1..20fa891d65 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -14,10 +14,8 @@ import collections -import paddle.trainer_config_helpers as conf_helps from paddle.proto.ModelConfig_pb2 import ModelConfig -import data_type import layer as v2_layer __all__ = ['Topology'] @@ -62,7 +60,7 @@ class Topology(object): return result_layer[0] - def get_data_layer(self): + def data_layer(self): """ get all data layer :return: @@ -101,23 +99,3 @@ class Topology(object): def __check_layer_type__(layer): if not isinstance(layer, v2_layer.LayerV2): raise ValueError('layer should have type paddle.layer.Layer') - - -if __name__ == '__main__': - pixel = v2_layer.data(name='pixel', type=data_type.dense_vector(784)) - label = v2_layer.data(name='label', type=data_type.integer_value(10)) - hidden = v2_layer.fc(input=pixel, - size=100, - act=conf_helps.SigmoidActivation()) - inference = v2_layer.fc(input=hidden, - size=10, - act=conf_helps.SoftmaxActivation()) - maxid = v2_layer.max_id(input=inference) - cost1 = v2_layer.classification_cost(input=inference, label=label) - cost2 = v2_layer.cross_entropy_cost(input=inference, label=label) - - print Topology(cost2).proto() - print Topology([cost1]).proto() - print Topology([cost1, cost2]).proto() - print Topology(cost2).proto() - print Topology([inference, maxid]).proto() From fb45cc3519b23da0862195bd316370d3f6c17f38 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 24 Feb 2017 16:17:54 +0800 Subject: [PATCH 07/17] refine code --- python/paddle/v2/topology.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 20fa891d65..9c57f1f8e6 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -32,8 +32,7 @@ class Topology(object): __check_layer_type__(layers) layers = [layers] for layer in layers: - if not isinstance(layer, v2_layer.LayerV2): - raise ValueError('layer should have type paddle.layer.Layer') + __check_layer_type__(layer) self.layers = layers self.__model_config__ = v2_layer.parse_network(*layers) assert isinstance(self.__model_config__, ModelConfig) From 976a6982baa8a5fb4839d036f7f403ef4b22b0c7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Fri, 24 Feb 2017 16:46:14 +0800 Subject: [PATCH 08/17] Add cifar dataset --- python/paddle/v2/data_set/cifar.py | 173 +++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 python/paddle/v2/data_set/cifar.py diff --git a/python/paddle/v2/data_set/cifar.py b/python/paddle/v2/data_set/cifar.py new file mode 100644 index 0000000000..54289430d4 --- /dev/null +++ b/python/paddle/v2/data_set/cifar.py @@ -0,0 +1,173 @@ +""" +CIFAR Dataset. + +URL: https://www.cs.toronto.edu/~kriz/cifar.html + +the default train_creator, test_creator used for CIFAR-10 dataset. +""" +from config import DATA_HOME +import os +import hashlib +import urllib2 +import shutil +import tarfile +import cPickle +import itertools +import numpy + +__all__ = ['CIFAR10', 'CIFAR100', 'train_creator', 'test_creator'] + + +def __download_file__(filename, url, md5): + def __file_ok__(): + if not os.path.exists(filename): + return False + md5_hash = hashlib.md5() + with open(filename, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(filename, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + + +def __read_one_batch__(batch): + data = batch['data'] + labels = batch.get('labels', batch.get('fine_labels', None)) + assert labels is not None + for sample, label in itertools.izip(data, labels): + yield (sample / 255.0).astype(numpy.float32), int(label) + + +CIFAR10_URL = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' +CIFAR10_MD5 = 'c58f30108f718f92721af3b95e74349a' +CIFAR100_URL = 'https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz' +CIFAR100_MD5 = 'eb9058c3a382ffc7106e4002c42a8d85' + + +class CIFAR(object): + """ + CIFAR dataset reader. The base class for CIFAR-10 and CIFAR-100 + + :param url: Download url. + :param md5: File md5sum + :param meta_filename: Meta file name in package. + :param train_filename: Train file name in package. + :param test_filename: Test file name in package. + """ + + def __init__(self, url, md5, meta_filename, train_filename, test_filename): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + + self.__full_file__ = os.path.join(filepath, filename) + self.__meta_filename__ = meta_filename + self.__train_filename__ = train_filename + self.__test_filename__ = test_filename + __download_file__(filename=self.__full_file__, url=url, md5=md5) + + def labels(self): + """ + labels get all dataset label in order. + :return: a list of label. + :rtype: list[string] + """ + with tarfile.open(self.__full_file__, mode='r') as f: + name = [ + each_item.name for each_item in f + if self.__meta_filename__ in each_item.name + ][0] + meta_f = f.extractfile(name) + meta = cPickle.load(meta_f) + for key in meta: + if 'label' in key: + return meta[key] + else: + raise RuntimeError("Unexpected branch.") + + def train(self): + """ + Train Reader + """ + return self.__read_batch__(self.__train_filename__) + + def test(self): + """ + Test Reader + """ + return self.__read_batch__(self.__test_filename__) + + def __read_batch__(self, sub_name): + with tarfile.open(self.__full_file__, mode='r') as f: + names = (each_item.name for each_item in f + if sub_name in each_item.name) + + for name in names: + batch = cPickle.load(f.extractfile(name)) + for item in __read_one_batch__(batch): + yield item + + +class CIFAR10(CIFAR): + """ + CIFAR-10 dataset, images are classified in 10 classes. + """ + + def __init__(self): + super(CIFAR10, self).__init__( + CIFAR10_URL, + CIFAR10_MD5, + meta_filename='batches.meta', + train_filename='data_batch', + test_filename='test_batch') + + +class CIFAR100(CIFAR): + """ + CIFAR-100 dataset, images are classified in 100 classes. + """ + + def __init__(self): + super(CIFAR100, self).__init__( + CIFAR100_URL, + CIFAR100_MD5, + meta_filename='meta', + train_filename='train', + test_filename='test') + + +def train_creator(): + """ + Default train reader creator. Use CIFAR-10 dataset. + """ + cifar = CIFAR10() + return cifar.train + + +def test_creator(): + """ + Default test reader creator. Use CIFAR-10 dataset. + """ + cifar = CIFAR10() + return cifar.test + + +def unittest(label_count=100): + cifar = globals()["CIFAR%d" % label_count]() + assert len(cifar.labels()) == label_count + for _ in cifar.test(): + pass + for _ in cifar.train(): + pass + + +if __name__ == '__main__': + unittest(10) + unittest(100) From 5258bcf3eee7f1ca24af04759b0cf4f21e8b5f0a Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Fri, 24 Feb 2017 17:41:58 +0800 Subject: [PATCH 09/17] implement more layers in v2 --- doc/api/trainer_config_helpers/layers.rst | 36 ++- .../paddle/trainer_config_helpers/layers.py | 214 ++++++++-------- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/layer.py | 235 ++++++++++++++---- python/paddle/v2/pooling.py | 24 ++ 5 files changed, 353 insertions(+), 159 deletions(-) create mode 100644 python/paddle/v2/pooling.py diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 2793d6afd9..bbea823de4 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -139,24 +139,12 @@ lstmemory :members: lstmemory :noindex: -lstm_step_layer ---------------- -.. automodule:: paddle.trainer_config_helpers.layers - :members: lstm_step_layer - :noindex: - grumemory --------- .. automodule:: paddle.trainer_config_helpers.layers :members: grumemory :noindex: -gru_step_layer ---------------- -.. automodule:: paddle.trainer_config_helpers.layers - :members: gru_step_layer - :noindex: - Recurrent Layer Group ===================== @@ -172,6 +160,18 @@ recurrent_group :members: recurrent_group :noindex: +lstm_step_layer +--------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: lstm_step_layer + :noindex: + +gru_step_layer +--------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: gru_step_layer + :noindex: + beam_search ------------ .. automodule:: paddle.trainer_config_helpers.layers @@ -308,6 +308,12 @@ repeat_layer :members: repeat_layer :noindex: +rotate_layer +------------ +.. automodule:: paddle.trainer_config_helpers.layers + :members: rotate_layer + :noindex: + seq_reshape_layer ----------------- .. automodule:: paddle.trainer_config_helpers.layers @@ -462,6 +468,12 @@ ctc_layer :members: ctc_layer :noindex: +warp_ctc_layer +-------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: warp_ctc_layer + :noindex: + nce_layer ----------- .. automodule:: paddle.trainer_config_helpers.layers diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 00aef80691..de903f8c74 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -30,88 +30,28 @@ except ImportError: import copy __all__ = [ - "full_matrix_projection", - "AggregateLevel", - "ExpandLevel", - "identity_projection", - "dotmul_projection", - "dotmul_operator", - "repeat_layer", - "seq_reshape_layer", - "table_projection", - "mixed_layer", - "data_layer", - "embedding_layer", - "fc_layer", - "grumemory", - "pooling_layer", - "lstmemory", - "last_seq", - "first_seq", - "cos_sim", - "hsigmoid", - "conv_projection", - "regression_cost", - 'classification_cost', - "LayerOutput", - 'img_conv_layer', - 'img_pool_layer', - 'batch_norm_layer', - 'img_cmrnorm_layer', - 'addto_layer', - 'concat_layer', - 'seq_concat_layer', - 'lstm_step_layer', - 'recurrent_group', - 'memory', - 'StaticInput', - 'expand_layer', - 'scaling_layer', - 'scaling_projection', - 'power_layer', - 'interpolation_layer', - 'bilinear_interp_layer', - 'trans_layer', - 'rotate_layer', - 'sum_to_one_norm_layer', - 'get_output_layer', - 'LayerType', - 'context_projection', - 'beam_search', - 'maxid_layer', - 'GeneratedInput', - 'SubsequenceInput', - 'gru_step_layer', - 'recurrent_layer', - 'BaseGeneratedInput', - 'conv_operator', - 'conv_shift_layer', - 'tensor_layer', - 'selective_fc_layer', - 'sampling_id_layer', - 'slope_intercept_layer', - 'trans_full_matrix_projection', - 'linear_comb_layer', - 'convex_comb_layer', - 'ctc_layer', - 'warp_ctc_layer', - 'crf_layer', - 'crf_decoding_layer', - 'nce_layer', - 'cross_entropy_with_selfnorm', - 'cross_entropy', - 'multi_binary_label_cross_entropy', - 'sum_cost', - 'rank_cost', - 'lambda_cost', - 'huber_cost', - 'block_expand_layer', - 'maxout_layer', - 'out_prod_layer', - 'print_layer', - 'priorbox_layer', - 'spp_layer', - 'pad_layer', + "full_matrix_projection", "AggregateLevel", "ExpandLevel", + "identity_projection", "dotmul_projection", "dotmul_operator", + "repeat_layer", "seq_reshape_layer", "table_projection", "mixed_layer", + "data_layer", "embedding_layer", "fc_layer", "grumemory", "pooling_layer", + "lstmemory", "last_seq", "first_seq", "cos_sim", "hsigmoid", + "conv_projection", "regression_cost", 'classification_cost', "LayerOutput", + 'img_conv_layer', 'img_pool_layer', 'batch_norm_layer', 'img_cmrnorm_layer', + 'addto_layer', 'concat_layer', 'seq_concat_layer', 'lstm_step_layer', + 'recurrent_group', 'memory', 'StaticInput', 'expand_layer', 'scaling_layer', + 'scaling_projection', 'power_layer', 'interpolation_layer', + 'bilinear_interp_layer', 'trans_layer', 'rotate_layer', + 'sum_to_one_norm_layer', 'get_output_layer', 'LayerType', + 'context_projection', 'beam_search', 'maxid_layer', 'GeneratedInput', + 'SubsequenceInput', 'gru_step_layer', 'recurrent_layer', + 'BaseGeneratedInput', 'conv_operator', 'conv_shift_layer', 'tensor_layer', + 'selective_fc_layer', 'sampling_id_layer', 'slope_intercept_layer', + 'trans_full_matrix_projection', 'linear_comb_layer', 'convex_comb_layer', + 'ctc_layer', 'warp_ctc_layer', 'crf_layer', 'crf_decoding_layer', + 'nce_layer', 'cross_entropy_with_selfnorm', 'cross_entropy', + 'multi_binary_label_cross_entropy', 'sum_cost', 'rank_cost', 'lambda_cost', + 'huber_cost', 'block_expand_layer', 'maxout_layer', 'out_prod_layer', + 'print_layer', 'priorbox_layer', 'spp_layer', 'pad_layer', 'eos_layer' ] @@ -1287,6 +1227,12 @@ def last_seq(input, """ Get Last Timestamp Activation of a sequence. + The simple usage is: + + .. code-block:: python + + seq = last_seq(input=layer) + :param agg_level: Aggregated level :param name: Layer name. :type name: basestring @@ -1325,6 +1271,12 @@ def first_seq(input, """ Get First Timestamp Activation of a sequence. + The simple usage is: + + .. code-block:: python + + seq = first_seq(input=layer) + :param agg_level: aggregation level :param name: Layer name. :type name: basestring @@ -1425,7 +1377,7 @@ def repeat_layer(input, num_repeats, name=None, layer_attr=None): .. code-block:: python - expand = repeat_layer(layer, 4) + expand = repeat_layer(input=layer, num_repeats=4) :param input: Input layer :type input: LayerOutput @@ -1797,6 +1749,12 @@ def cos_sim(a, b, scale=1, size=1, name=None, layer_attr=None): Note that the above computation is for one sample. Multiple samples are processed in one batch. + The example usage is: + + .. code-block:: python + + cos = cos_sim(a=layer1, b=layer2, size=3) + :param name: layer name :type name: basestring :param a: input layer a @@ -1958,6 +1916,16 @@ def img_conv_layer(input, pieces. First 256/4 = 64 channels will process by first 32 filters. The rest channels will be processed by rest group of filters. + The example usage is: + + .. code-block:: python + + conv = img_conv_layer(input=data, filter_size=1, filter_size_y=1, + num_channels=8, + num_filters=16, stride=1, + bias_attr=False, + act=ReluActivation()) + :param name: Layer name. :type name: basestring :param input: Layer Input. @@ -2097,6 +2065,34 @@ def img_pool_layer(input, .. _pooling: http://ufldl.stanford.edu/tutorial/supervised/Pooling/ + - ceil_mode=True: + + .. math:: + + w = 1 + int(ceil(input\_width + 2 * padding - pool\_size) / float(stride)) + h = 1 + int(ceil(input\_height + 2 * padding\_y - pool\_size\_y) / float(stride\_y)) + + - ceil_mode=False: + + .. math:: + + w = 1 + int(floor(input\_width + 2 * padding - pool\_size) / float(stride)) + h = 1 + int(floor(input\_height + 2 * padding\_y - pool\_size\_y) / float(stride\_y)) + + The example usage is: + + .. code-block:: python + + maxpool = img_pool_layer(input=conv, + pool_size=3, + pool_size_y=5, + num_channels=8, + stride=1, + stride_y=2, + padding=1, + padding_y=2, + pool_type=MaxPooling()) + :param padding: pooling padding width. :type padding: int :param padding_y: pooling padding height. It's equal to padding by default. @@ -2123,19 +2119,6 @@ def img_pool_layer(input, :param ceil_mode: Wether to use ceil mode to calculate output height and with. Defalut is True. If set false, Otherwise use floor. - - ceil_mode=True: - - .. math:: - - w = 1 + int(ceil(input_width + 2 * padding - pool_size) / float(stride)) - h = 1 + int(ceil(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) - - - ceil_mode=False: - - .. math:: - - w = 1 + int(floor(input_width + 2 * padding - pool_size) / float(stride)) - h = 1 + int(floor(input_height + 2 * padding_y - pool_size_y) / float(stride_y)) :type ceil_mode: bool :return: LayerOutput object. :rtype: LayerOutput @@ -2197,6 +2180,15 @@ def spp_layer(input, The details please refer to `Kaiming He's paper `_. + The example usage is: + + .. code-block:: python + + spp = spp_layer(input=data, + pyramid_height=2, + num_channels=16, + pool_type=MaxPooling()) + :param name: layer name. :type name: basestring :param input: layer's input. @@ -2285,6 +2277,12 @@ def img_cmrnorm_layer(input, The details please refer to `Alex's paper `_. + The example usage is: + + .. code-block:: python + + norm = img_cmrnorm_layer(input=net, size=5) + :param name: layer name. :type name: None|basestring :param input: layer's input. @@ -2340,6 +2338,12 @@ def batch_norm_layer(input, The details of batch normalization please refer to this `paper `_. + The example usage is: + + .. code-block:: python + + norm = batch_norm_layer(input=net, act=ReluActivation()) + :param name: layer name. :type name: basestring :param input: batch normalization input. Better be linear activation. @@ -3903,13 +3907,13 @@ def conv_shift_layer(a, b, name=None, layer_attr=None): .. code-block:: python - conv_shift = conv_shift_layer(input=[layer1, layer2]) + conv_shift = conv_shift_layer(a=layer1, b=layer2) :param name: layer name :type name: basestring :param a: Input layer a. :type a: LayerOutput - :param b: input layer b + :param b: input layer b. :type b: LayerOutput :param layer_attr: layer's extra attribute. :type layer_attr: ExtraLayerAttribute @@ -4001,8 +4005,8 @@ def tensor_layer(a, @wrap_act_default() @layer_support() def selective_fc_layer(input, - select, size, + select=None, act=None, name=None, pass_generation=False, @@ -4029,6 +4033,7 @@ def selective_fc_layer(input, :type input: LayerOutput|list|tuple :param select: The select layer. The output of select layer should be a sparse binary matrix, and treat as the mask of selective fc. + If is None, acts exactly like fc_layer. :type select: LayerOutput :param size: The layer dimension. :type size: int @@ -4257,7 +4262,7 @@ def block_expand_layer(input, .. code-block:: python - block_expand = block_expand_layer(input, + block_expand = block_expand_layer(input=layer, num_channels=128, stride_x=1, stride_y=1, @@ -4461,7 +4466,7 @@ def warp_ctc_layer(input, - You can set 'blank' to any value ranged in [0, num_classes], which should be consistent as that used in your labels. - As a native 'softmax' activation is interated to the warp-ctc library, - 'linear' activation is expected instead in the 'input' layer. + 'linear' activation is expected instead in the 'input' layer. The simple usage: @@ -4594,6 +4599,13 @@ def crf_decoding_layer(input, this layer will also calculate error. output.value[i] is 1 for incorrect decoding or 0 for correct decoding. + The simple usage: + + .. code-block:: python + + crf_decoding = crf_decoding_layer(input=input, + size=label_dim) + :param input: The first input layer. :type input: LayerOutput :param size: size of this layer. diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 0cf7b8e903..ab352e880e 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -19,11 +19,12 @@ import trainer import event import data_type import attr +import pooling import py_paddle.swig_paddle as api __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', - 'event', 'data_type', 'attr' + 'event', 'data_type', 'attr', 'pooling' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 3920d4a08f..f4a85e9d03 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -76,12 +76,20 @@ from paddle.trainer_config_helpers.default_decorators import wrap_name_default import data_type import activation import attr +import pooling __all__ = [ - 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', - 'cross_entropy_cost', 'cross_entropy_with_selfnorm_cost', 'regression_cost', + 'parse_network', 'data', 'fc', 'conv_shift', 'img_conv', 'img_pool', 'spp', + 'maxout', 'img_cmrnorm', 'batch_norm', 'sum_to_one_norm', 'recurrent', + 'lstmemory', 'grumemory', 'pool', 'last_seq', 'first_seq', 'concat', + 'seq_concat', 'block_expand', 'expand', 'repeat', 'seq_reshape', 'addto', + 'linear_comb', 'interpolation', 'bilinear_interp', 'power', 'scaling', + 'slope_intercept', 'tensor', 'cos_sim', 'trans', 'max_id', 'sampling_id', + 'pad', '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', 'crf', 'crf_decoding', 'ctc', 'warp_ctc', 'nce', + 'hsigmoid', 'eos' ] @@ -130,11 +138,8 @@ class Layer(object): raise NotImplementedError() -def __convert_to_v2__(method_name, name_prefix, parent_names): - if name_prefix is not None: - wrapper = wrap_name_default(name_prefix=name_prefix) - else: - wrapper = None +def __convert_to_v2__(method_name, parent_names): + wrapper = wrap_name_default(name_prefix=method_name) class V2LayerImpl(Layer): def __init__(self, name=None, **kwargs): @@ -192,44 +197,92 @@ class DataLayerV2(Layer): data = DataLayerV2 -fc = __convert_to_v2__('fc_layer', name_prefix='fc', parent_names=['input']) -max_id = __convert_to_v2__( - 'maxid_layer', name_prefix='maxid', parent_names=['input']) -classification_cost = __convert_to_v2__( - 'classification_cost', - name_prefix='classification_cost', - parent_names=['input', 'label', 'weight']) -regression_cost = __convert_to_v2__( - 'regression_cost', - name_prefix='regression_cost', - parent_names=['input', 'label', 'weight']) -cross_entropy_cost = __convert_to_v2__( - 'cross_entropy', - name_prefix='cross_entropy', - parent_names=['input', 'label']) -cross_entropy_with_selfnorm_cost = __convert_to_v2__( - 'cross_entropy_with_selfnorm', - name_prefix='cross_entropy_with_selfnorm', - parent_names=['input', 'label']) -multi_binary_label_cross_entropy_cost = __convert_to_v2__( - 'multi_binary_label_cross_entropy', - name_prefix='multi_binary_label_cross_entropy', - parent_names=['input', 'label']) -rank_cost = __convert_to_v2__( - 'rank_cost', - name_prefix='rank_cost', - parent_names=['left', 'right', 'label', 'weight']) -lambda_cost = __convert_to_v2__( - 'lambda_cost', name_prefix='lambda_cost', parent_names=['input', 'score']) -sum_cost = __convert_to_v2__( - 'sum_cost', name_prefix='sum_cost', parent_names=['input']) -huber_cost = __convert_to_v2__( - 'huber_cost', name_prefix='huber_cost', parent_names=['input', 'label']) +AggregateLevel = conf_helps.layers.AggregateLevel +ExpandLevel = conf_helps.layers.ExpandLevel + +layer_list = [ + # [V2LayerImpl, V1_method_name, parent_names] + # fully connected layers + ['fc', 'fc_layer', ['input']], + # conv layers + ['conv_shift', 'conv_shift_layer', ['a', 'b']], + ['img_conv', 'img_conv_layer', ['input']], + # image pooling layers + ['img_pool', 'img_pool_layer', ['input']], + ['spp', 'spp_layer', ['input']], + ['maxout', 'maxout_layer', ['input']], + # norm layers + ['img_cmrnorm', 'img_cmrnorm_layer', ['input']], + ['batch_norm', 'batch_norm_layer', ['input']], + ['sum_to_one_norm', 'sum_to_one_norm_layer', ['input']], + # recurrent layers + ['recurrent', 'recurrent_layer', ['input']], + ['lstmemory', 'lstmemory', ['input']], + ['grumemory', 'grumemory', ['input']], + # aggregate layers + ['pool', 'pooling_layer', ['input']], + ['last_seq', 'last_seq', ['input']], + ['first_seq', 'first_seq', ['input']], + ['concat', 'concat_layer', ['input']], + ['seq_concat', 'seq_concat_layer', ['a', 'b']], + # reshaping layers + ['block_expand', 'block_expand_layer', ['input']], + ['expand', 'expand_layer', ['input', 'expand_as']], + ['repeat', 'repeat_layer', ['input']], + ['rotate', 'rotate_layer', ['input']], + ['seq_reshape', 'seq_reshape_layer', ['input']], + # math layers + ['addto', 'addto_layer', ['input']], + ['linear_comb', 'linear_comb_layer', ['weights', 'vectors']], + ['interpolation', 'interpolation_layer', ['input', 'weight']], + ['bilinear_interp', 'bilinear_interp_layer', ['input']], + ['power', 'power_layer', ['input', 'weight']], + ['scaling', 'scaling_layer', ['input', 'weight']], + ['slope_intercept', 'slope_intercept_layer', ['input']], + ['tensor', 'tensor_layer', ['a', 'b']], + ['cos_sim', 'cos_sim', ['a', 'b']], + ['trans', 'trans_layer', ['input']], + # sampling layers + ['max_id', 'maxid_layer', ['input']], + ['sampling_id', 'sampling_id_layer', ['input']], + # slicing and joining layers + ['pad', 'pad_layer', ['input']], + # cost layers + [ + 'classification_cost', 'classification_cost', + ['input', 'label', 'weight'] + ], + ['regression_cost', 'regression_cost', ['input', 'label', 'weight']], + ['cross_entropy_cost', 'cross_entropy', ['input', 'label']], + [ + 'cross_entropy_with_selfnorm_cost', 'cross_entropy_with_selfnorm', + ['input', 'label'] + ], + [ + 'multi_binary_label_cross_entropy_cost', + 'multi_binary_label_cross_entropy', ['input', 'label'] + ], + ['rank_cost', 'rank_cost', ['left', 'right', 'label', 'weight']], + ['lambda_cost', 'lambda_cost', ['input', 'score']], + ['sum_cost', 'sum_cost', ['input']], + ['huber_cost', 'huber_cost', ['input', 'label']], + ['crf', 'crf_layer', ['input', 'label']], + ['crf_decoding', 'crf_decoding_layer', ['input']], + ['ctc', 'ctc_layer', ['input', 'label']], + ['warp_ctc', 'warp_ctc_layer', ['input', 'label']], + ['nce', 'nce_layer', ['input', 'label']], + ['hsigmoid', 'hsigmoid', ['input', 'label']], + # check layers + ['eos', 'eos_layer', ['input']] +] +for l in layer_list: + globals()[l[0]] = __convert_to_v2__(l[1], l[2]) if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(784)) + pixel = data(name='pixel', type=data_type.dense_vector(128)) label = data(name='label', type=data_type.integer_value(10)) weight = data(name='weight', type=data_type.dense_vector(10)) + word = data(name='word', type=data_type.integer_value(12)) score = data(name='score', type=data_type.dense_vector(1)) hidden = fc(input=pixel, @@ -237,7 +290,90 @@ if __name__ == '__main__': act=activation.Sigmoid(), param_attr=attr.Param(name='hidden')) inference = fc(input=hidden, size=10, act=activation.Softmax()) + print parse_network(inference) + + # test conv layers + conv1 = conv_shift(a=pixel, b=score) + conv2 = img_conv( + input=pixel, + filter_size=1, + filter_size_y=1, + num_channels=8, + num_filters=16, + act=activation.Linear()) + print parse_network(conv1, conv2) + + # test image pooling layers + maxpool = img_pool( + input=conv2, + pool_size=2, + num_channels=16, + padding=1, + pool_type=pooling.Max()) + spp = spp(input=conv2, + pyramid_height=2, + num_channels=16, + pool_type=pooling.Max()) + maxout = maxout(input=conv2, num_channels=16, groups=4) + print parse_network(maxpool, spp, maxout) + + # test norm layers + norm1 = img_cmrnorm(input=maxpool, size=5) + norm2 = batch_norm(input=maxpool) + norm3 = sum_to_one_norm(input=maxpool) + print parse_network(norm1, norm2, norm3) + + # test recurrent layers + recurrent = recurrent(input=word) + lstm = lstmemory(input=word) + gru = grumemory(input=word) + print parse_network(recurrent, lstm, gru) + + # test aggregate layers + pool = pool( + input=pixel, + pooling_type=pooling.Avg(), + agg_level=AggregateLevel.EACH_SEQUENCE) + last_seq = last_seq(input=pixel) + first_seq = first_seq(input=pixel) + concat = concat(input=[last_seq, first_seq]) + seq_concat = seq_concat(a=last_seq, b=first_seq) + print parse_network(pool, last_seq, first_seq, concat, seq_concat) + + # test reshaping layers + block_expand = block_expand( + input=maxout, num_channels=4, stride_x=1, block_x=1) + expand = expand( + input=last_seq, expand_as=pixel, expand_level=ExpandLevel.FROM_TIMESTEP) + repeat = repeat(input=last_seq, num_repeats=4) + reshape = seq_reshape(input=last_seq, reshape_size=4) + rotate = rotate(input=pixel, height=16, width=49) + print parse_network(block_expand, expand, repeat, reshape, rotate) + + # test math layers + addto = addto(input=[last_seq, first_seq]) + linear_comb = linear_comb(weights=weight, vectors=hidden, size=10) + interpolation = interpolation(input=[hidden, hidden], weight=score) + bilinear = bilinear_interp(input=conv2, out_size_x=4, out_size_y=4) + power = power(input=conv1, weight=score) + scaling = scaling(input=conv1, weight=score) + slope = slope_intercept(input=conv1) + tensor = tensor(a=last_seq, b=first_seq, size=1000) + cos_sim = cos_sim(a=last_seq, b=first_seq) + trans = trans(input=tensor) + print parse_network(addto, linear_comb, interpolation, bilinear, power, + scaling, slope, tensor, cos_sim, trans) + + # test sampling layers maxid = max_id(input=inference) + sampling_id = sampling_id(input=inference) + print parse_network(maxid, sampling_id) + + # test slicing and joining layers + pad = pad(input=maxpool, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) + print parse_network(pad) + + # test cost layers cost1 = classification_cost(input=inference, label=label) cost2 = classification_cost(input=inference, label=label, weight=weight) cost3 = cross_entropy_cost(input=inference, label=label) @@ -249,9 +385,18 @@ if __name__ == '__main__': cost9 = lambda_cost(input=inference, score=score) cost10 = sum_cost(input=inference) cost11 = huber_cost(input=score, label=label) - - 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) + + crf = crf(input=inference, label=label) + crf_decoding = crf_decoding(input=inference, size=3) + ctc = ctc(input=inference, label=label) + warp_ctc = warp_ctc(input=pixel, label=label) + nce = nce(input=inference, label=label, num_classes=3) + hsigmoid = hsigmoid(input=inference, label=label, num_classes=3) + print parse_network(crf, crf_decoding, ctc, warp_ctc, nce, hsigmoid) + + # test check layers + eos = eos(input=maxid, eos_id=5) + print parse_network(eos) diff --git a/python/paddle/v2/pooling.py b/python/paddle/v2/pooling.py new file mode 100644 index 0000000000..9076a159bb --- /dev/null +++ b/python/paddle/v2/pooling.py @@ -0,0 +1,24 @@ +# 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 paddle.trainer_config_helpers.poolings import * + +__all__ = ["Max", "CudnnMax", "Avg", "CudnnAvg", "Sum", "SquareRootN"] + +Max = MaxPooling +CudnnMax = CudnnMaxPooling +Avg = AvgPooling +CudnnAvg = CudnnAvgPooling +Sum = SumPooling +SquareRootN = SquareRootNPooling From 5d7e7bc042e3118e9cf4a1899bc08dd44a1cf34c Mon Sep 17 00:00:00 2001 From: Luo Tao Date: Mon, 27 Feb 2017 13:37:53 +0800 Subject: [PATCH 10/17] add test_layer for v2 --- python/paddle/v2/layer.py | 126 --------------------------- python/paddle/v2/tests/test_layer.py | 122 ++++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 133 deletions(-) diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index f4a85e9d03..f0e4f972fe 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -74,9 +74,6 @@ from paddle.trainer_config_helpers.config_parser_utils import \ from paddle.trainer_config_helpers.default_decorators import wrap_name_default import data_type -import activation -import attr -import pooling __all__ = [ 'parse_network', 'data', 'fc', 'conv_shift', 'img_conv', 'img_pool', 'spp', @@ -277,126 +274,3 @@ layer_list = [ ] for l in layer_list: globals()[l[0]] = __convert_to_v2__(l[1], l[2]) - -if __name__ == '__main__': - pixel = data(name='pixel', type=data_type.dense_vector(128)) - label = data(name='label', type=data_type.integer_value(10)) - weight = data(name='weight', type=data_type.dense_vector(10)) - word = data(name='word', type=data_type.integer_value(12)) - 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()) - print parse_network(inference) - - # test conv layers - conv1 = conv_shift(a=pixel, b=score) - conv2 = img_conv( - input=pixel, - filter_size=1, - filter_size_y=1, - num_channels=8, - num_filters=16, - act=activation.Linear()) - print parse_network(conv1, conv2) - - # test image pooling layers - maxpool = img_pool( - input=conv2, - pool_size=2, - num_channels=16, - padding=1, - pool_type=pooling.Max()) - spp = spp(input=conv2, - pyramid_height=2, - num_channels=16, - pool_type=pooling.Max()) - maxout = maxout(input=conv2, num_channels=16, groups=4) - print parse_network(maxpool, spp, maxout) - - # test norm layers - norm1 = img_cmrnorm(input=maxpool, size=5) - norm2 = batch_norm(input=maxpool) - norm3 = sum_to_one_norm(input=maxpool) - print parse_network(norm1, norm2, norm3) - - # test recurrent layers - recurrent = recurrent(input=word) - lstm = lstmemory(input=word) - gru = grumemory(input=word) - print parse_network(recurrent, lstm, gru) - - # test aggregate layers - pool = pool( - input=pixel, - pooling_type=pooling.Avg(), - agg_level=AggregateLevel.EACH_SEQUENCE) - last_seq = last_seq(input=pixel) - first_seq = first_seq(input=pixel) - concat = concat(input=[last_seq, first_seq]) - seq_concat = seq_concat(a=last_seq, b=first_seq) - print parse_network(pool, last_seq, first_seq, concat, seq_concat) - - # test reshaping layers - block_expand = block_expand( - input=maxout, num_channels=4, stride_x=1, block_x=1) - expand = expand( - input=last_seq, expand_as=pixel, expand_level=ExpandLevel.FROM_TIMESTEP) - repeat = repeat(input=last_seq, num_repeats=4) - reshape = seq_reshape(input=last_seq, reshape_size=4) - rotate = rotate(input=pixel, height=16, width=49) - print parse_network(block_expand, expand, repeat, reshape, rotate) - - # test math layers - addto = addto(input=[last_seq, first_seq]) - linear_comb = linear_comb(weights=weight, vectors=hidden, size=10) - interpolation = interpolation(input=[hidden, hidden], weight=score) - bilinear = bilinear_interp(input=conv2, out_size_x=4, out_size_y=4) - power = power(input=conv1, weight=score) - scaling = scaling(input=conv1, weight=score) - slope = slope_intercept(input=conv1) - tensor = tensor(a=last_seq, b=first_seq, size=1000) - cos_sim = cos_sim(a=last_seq, b=first_seq) - trans = trans(input=tensor) - print parse_network(addto, linear_comb, interpolation, bilinear, power, - scaling, slope, tensor, cos_sim, trans) - - # test sampling layers - maxid = max_id(input=inference) - sampling_id = sampling_id(input=inference) - print parse_network(maxid, sampling_id) - - # test slicing and joining layers - pad = pad(input=maxpool, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) - print parse_network(pad) - - # test cost layers - 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(cost3, cost4) - print parse_network(cost5, cost6) - print parse_network(cost7, cost8, cost9, cost10, cost11) - - crf = crf(input=inference, label=label) - crf_decoding = crf_decoding(input=inference, size=3) - ctc = ctc(input=inference, label=label) - warp_ctc = warp_ctc(input=pixel, label=label) - nce = nce(input=inference, label=label, num_classes=3) - hsigmoid = hsigmoid(input=inference, label=label, num_classes=3) - print parse_network(crf, crf_decoding, ctc, warp_ctc, nce, hsigmoid) - - # test check layers - eos = eos(input=maxid, eos_id=5) - print parse_network(eos) diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index b600e8cf76..2f139866e8 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -19,18 +19,106 @@ 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.pooling as pooling 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)) +pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) 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()) +conv = layer.img_conv( + input=pixel, + filter_size=1, + filter_size_y=1, + num_channels=8, + num_filters=16, + act=activation.Linear()) + + +class ImageLayerTest(unittest.TestCase): + def test_conv_layer(self): + conv_shift = layer.conv_shift(a=pixel, b=score) + print layer.parse_network(conv, conv_shift) + + def test_pooling_layer(self): + maxpool = layer.img_pool( + input=conv, + pool_size=2, + num_channels=16, + padding=1, + pool_type=pooling.Max()) + spp = layer.spp(input=conv, + pyramid_height=2, + num_channels=16, + pool_type=pooling.Max()) + maxout = layer.maxout(input=conv, num_channels=16, groups=4) + print layer.parse_network(maxpool, spp, maxout) + + def test_norm_layer(self): + norm1 = layer.img_cmrnorm(input=conv, size=5) + norm2 = layer.batch_norm(input=conv) + norm3 = layer.sum_to_one_norm(input=conv) + print layer.parse_network(norm1, norm2, norm3) + + +class AggregateLayerTest(unittest.TestCase): + def test_aggregate_layer(self): + pool = layer.pool( + input=pixel, + pooling_type=pooling.Avg(), + agg_level=layer.AggregateLevel.EACH_SEQUENCE) + last_seq = layer.last_seq(input=pixel) + first_seq = layer.first_seq(input=pixel) + concat = layer.concat(input=[last_seq, first_seq]) + seq_concat = layer.seq_concat(a=last_seq, b=first_seq) + print layer.parse_network(pool, last_seq, first_seq, concat, seq_concat) + + +class MathLayerTest(unittest.TestCase): + def test_math_layer(self): + addto = layer.addto(input=[pixel, pixel]) + linear_comb = layer.linear_comb(weights=weight, vectors=hidden, size=10) + interpolation = layer.interpolation( + input=[hidden, hidden], weight=score) + bilinear = layer.bilinear_interp(input=conv, out_size_x=4, out_size_y=4) + power = layer.power(input=pixel, weight=score) + scaling = layer.scaling(input=pixel, weight=score) + slope = layer.slope_intercept(input=pixel) + tensor = layer.tensor(a=pixel, b=pixel, size=1000) + cos_sim = layer.cos_sim(a=pixel, b=pixel) + trans = layer.trans(input=tensor) + print layer.parse_network(addto, linear_comb, interpolation, power, + scaling, slope, tensor, cos_sim, trans) + + +class ReshapeLayerTest(unittest.TestCase): + def test_reshape_layer(self): + block_expand = layer.block_expand( + input=conv, num_channels=4, stride_x=1, block_x=1) + expand = layer.expand( + input=weight, + expand_as=pixel, + expand_level=layer.ExpandLevel.FROM_TIMESTEP) + repeat = layer.repeat(input=pixel, num_repeats=4) + reshape = layer.seq_reshape(input=pixel, reshape_size=4) + rotate = layer.rotate(input=pixel, height=16, width=49) + print layer.parse_network(block_expand, expand, repeat, reshape, rotate) + + +class RecurrentLayerTest(unittest.TestCase): + def test_recurrent_layer(self): + word = layer.data(name='word', type=data_type.integer_value(12)) + recurrent = layer.recurrent(input=word) + lstm = layer.lstmemory(input=word) + gru = layer.grumemory(input=word) + print layer.parse_network(recurrent, lstm, gru) class CostLayerTest(unittest.TestCase): @@ -51,12 +139,32 @@ class CostLayerTest(unittest.TestCase): 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) + + crf = layer.crf(input=inference, label=label) + crf_decoding = layer.crf_decoding(input=inference, size=3) + ctc = layer.ctc(input=inference, label=label) + warp_ctc = layer.warp_ctc(input=pixel, label=label) + nce = layer.nce(input=inference, label=label, num_classes=3) + hsigmoid = layer.hsigmoid(input=inference, label=label, num_classes=3) + + print layer.parse_network(crf, crf_decoding, ctc, warp_ctc, nce, + hsigmoid) + + +class OtherLayerTest(unittest.TestCase): + def test_sampling_layer(self): + maxid = layer.max_id(input=inference) + sampling_id = layer.sampling_id(input=inference) + eos = layer.eos(input=maxid, eos_id=5) + print layer.parse_network(maxid, sampling_id, eos) + + def test_slicing_joining_layer(self): + pad = layer.pad(input=conv, pad_c=[2, 3], pad_h=[1, 2], pad_w=[3, 1]) + print layer.parse_network(pad) if __name__ == '__main__': From 434ada47ef0bb039192d4de5d969fc70ae033a0b Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 17:05:18 +0800 Subject: [PATCH 11/17] Up to date --- python/paddle/v2/{data_set => dataset}/cifar.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/paddle/v2/{data_set => dataset}/cifar.py (100%) diff --git a/python/paddle/v2/data_set/cifar.py b/python/paddle/v2/dataset/cifar.py similarity index 100% rename from python/paddle/v2/data_set/cifar.py rename to python/paddle/v2/dataset/cifar.py From 0bcc4d48defeb00f191c04d868098523965bc0d2 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 17:19:29 +0800 Subject: [PATCH 12/17] Simplize cifar --- python/paddle/v2/dataset/cifar.py | 170 ++++++++++-------------------- 1 file changed, 53 insertions(+), 117 deletions(-) diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 54289430d4..9a999de7e0 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -15,33 +15,10 @@ import cPickle import itertools import numpy -__all__ = ['CIFAR10', 'CIFAR100', 'train_creator', 'test_creator'] - - -def __download_file__(filename, url, md5): - def __file_ok__(): - if not os.path.exists(filename): - return False - md5_hash = hashlib.md5() - with open(filename, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - md5_hash.update(chunk) - - return md5_hash.hexdigest() == md5 - - while not __file_ok__(): - response = urllib2.urlopen(url) - with open(filename, mode='wb') as of: - shutil.copyfileobj(fsrc=response, fdst=of) - - -def __read_one_batch__(batch): - data = batch['data'] - labels = batch.get('labels', batch.get('fine_labels', None)) - assert labels is not None - for sample, label in itertools.izip(data, labels): - yield (sample / 255.0).astype(numpy.float32), int(label) - +__all__ = [ + 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', + 'test_creator' +] CIFAR10_URL = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' CIFAR10_MD5 = 'c58f30108f718f92721af3b95e74349a' @@ -49,125 +26,84 @@ CIFAR100_URL = 'https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz' CIFAR100_MD5 = 'eb9058c3a382ffc7106e4002c42a8d85' -class CIFAR(object): - """ - CIFAR dataset reader. The base class for CIFAR-10 and CIFAR-100 - - :param url: Download url. - :param md5: File md5sum - :param meta_filename: Meta file name in package. - :param train_filename: Train file name in package. - :param test_filename: Test file name in package. - """ +def __read_batch__(filename, sub_name): + def reader(): + def __read_one_batch_impl__(batch): + data = batch['data'] + labels = batch.get('labels', batch.get('fine_labels', None)) + assert labels is not None + for sample, label in itertools.izip(data, labels): + yield (sample / 255.0).astype(numpy.float32), int(label) - def __init__(self, url, md5, meta_filename, train_filename, test_filename): - filename = os.path.split(url)[-1] - assert DATA_HOME is not None - filepath = os.path.join(DATA_HOME, md5) - if not os.path.exists(filepath): - os.makedirs(filepath) - - self.__full_file__ = os.path.join(filepath, filename) - self.__meta_filename__ = meta_filename - self.__train_filename__ = train_filename - self.__test_filename__ = test_filename - __download_file__(filename=self.__full_file__, url=url, md5=md5) - - def labels(self): - """ - labels get all dataset label in order. - :return: a list of label. - :rtype: list[string] - """ - with tarfile.open(self.__full_file__, mode='r') as f: - name = [ - each_item.name for each_item in f - if self.__meta_filename__ in each_item.name - ][0] - meta_f = f.extractfile(name) - meta = cPickle.load(meta_f) - for key in meta: - if 'label' in key: - return meta[key] - else: - raise RuntimeError("Unexpected branch.") - - def train(self): - """ - Train Reader - """ - return self.__read_batch__(self.__train_filename__) - - def test(self): - """ - Test Reader - """ - return self.__read_batch__(self.__test_filename__) - - def __read_batch__(self, sub_name): - with tarfile.open(self.__full_file__, mode='r') as f: + with tarfile.open(filename, mode='r') as f: names = (each_item.name for each_item in f if sub_name in each_item.name) for name in names: batch = cPickle.load(f.extractfile(name)) - for item in __read_one_batch__(batch): + for item in __read_one_batch_impl__(batch): yield item + return reader -class CIFAR10(CIFAR): - """ - CIFAR-10 dataset, images are classified in 10 classes. - """ - def __init__(self): - super(CIFAR10, self).__init__( - CIFAR10_URL, - CIFAR10_MD5, - meta_filename='batches.meta', - train_filename='data_batch', - test_filename='test_batch') +def download(url, md5): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + __full_file__ = os.path.join(filepath, filename) + def __file_ok__(): + if not os.path.exists(__full_file__): + return False + md5_hash = hashlib.md5() + with open(__full_file__, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(__full_file__, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + return __full_file__ + + +def cifar_100_train_creator(): + fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) + return __read_batch__(fn, 'train') -class CIFAR100(CIFAR): - """ - CIFAR-100 dataset, images are classified in 100 classes. - """ - def __init__(self): - super(CIFAR100, self).__init__( - CIFAR100_URL, - CIFAR100_MD5, - meta_filename='meta', - train_filename='train', - test_filename='test') +def cifar_100_test_creator(): + fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) + return __read_batch__(fn, 'test') def train_creator(): """ Default train reader creator. Use CIFAR-10 dataset. """ - cifar = CIFAR10() - return cifar.train + fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) + return __read_batch__(fn, 'data_batch') def test_creator(): """ Default test reader creator. Use CIFAR-10 dataset. """ - cifar = CIFAR10() - return cifar.test + fn = download(url=CIFAR10_URL, md5=CIFAR10_MD5) + return __read_batch__(fn, 'test_batch') -def unittest(label_count=100): - cifar = globals()["CIFAR%d" % label_count]() - assert len(cifar.labels()) == label_count - for _ in cifar.test(): +def unittest(): + for _ in train_creator()(): pass - for _ in cifar.train(): + for _ in test_creator()(): pass if __name__ == '__main__': - unittest(10) - unittest(100) + unittest() From de9012a50450da19a9227bc28d5bb042ac66fcf7 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Mon, 27 Feb 2017 20:32:44 +0800 Subject: [PATCH 13/17] Add MovieLens Dataset --- python/paddle/v2/dataset/cifar.py | 35 +------- python/paddle/v2/dataset/config.py | 30 ++++++- python/paddle/v2/dataset/movielens.py | 120 ++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 32 deletions(-) create mode 100644 python/paddle/v2/dataset/movielens.py diff --git a/python/paddle/v2/dataset/cifar.py b/python/paddle/v2/dataset/cifar.py index 9a999de7e0..2ac71c6eff 100644 --- a/python/paddle/v2/dataset/cifar.py +++ b/python/paddle/v2/dataset/cifar.py @@ -5,16 +5,14 @@ URL: https://www.cs.toronto.edu/~kriz/cifar.html the default train_creator, test_creator used for CIFAR-10 dataset. """ -from config import DATA_HOME -import os -import hashlib -import urllib2 -import shutil -import tarfile import cPickle import itertools +import tarfile + import numpy +from config import download + __all__ = [ 'cifar_100_train_creator', 'cifar_100_test_creator', 'train_creator', 'test_creator' @@ -47,31 +45,6 @@ def __read_batch__(filename, sub_name): return reader -def download(url, md5): - filename = os.path.split(url)[-1] - assert DATA_HOME is not None - filepath = os.path.join(DATA_HOME, md5) - if not os.path.exists(filepath): - os.makedirs(filepath) - __full_file__ = os.path.join(filepath, filename) - - def __file_ok__(): - if not os.path.exists(__full_file__): - return False - md5_hash = hashlib.md5() - with open(__full_file__, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - md5_hash.update(chunk) - - return md5_hash.hexdigest() == md5 - - while not __file_ok__(): - response = urllib2.urlopen(url) - with open(__full_file__, mode='wb') as of: - shutil.copyfileobj(fsrc=response, fdst=of) - return __full_file__ - - def cifar_100_train_creator(): fn = download(url=CIFAR100_URL, md5=CIFAR100_MD5) return __read_batch__(fn, 'train') diff --git a/python/paddle/v2/dataset/config.py b/python/paddle/v2/dataset/config.py index 69e96d65ef..02a009f09c 100644 --- a/python/paddle/v2/dataset/config.py +++ b/python/paddle/v2/dataset/config.py @@ -1,8 +1,36 @@ +import hashlib import os +import shutil +import urllib2 -__all__ = ['DATA_HOME'] +__all__ = ['DATA_HOME', 'download'] DATA_HOME = os.path.expanduser('~/.cache/paddle_data_set') if not os.path.exists(DATA_HOME): os.makedirs(DATA_HOME) + + +def download(url, md5): + filename = os.path.split(url)[-1] + assert DATA_HOME is not None + filepath = os.path.join(DATA_HOME, md5) + if not os.path.exists(filepath): + os.makedirs(filepath) + __full_file__ = os.path.join(filepath, filename) + + def __file_ok__(): + if not os.path.exists(__full_file__): + return False + md5_hash = hashlib.md5() + with open(__full_file__, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5_hash.update(chunk) + + return md5_hash.hexdigest() == md5 + + while not __file_ok__(): + response = urllib2.urlopen(url) + with open(__full_file__, mode='wb') as of: + shutil.copyfileobj(fsrc=response, fdst=of) + return __full_file__ diff --git a/python/paddle/v2/dataset/movielens.py b/python/paddle/v2/dataset/movielens.py new file mode 100644 index 0000000000..314329e91c --- /dev/null +++ b/python/paddle/v2/dataset/movielens.py @@ -0,0 +1,120 @@ +import zipfile +from config import download +import re +import random +import functools + +__all__ = ['train_creator', 'test_creator'] + + +class MovieInfo(object): + def __init__(self, index, categories, title): + self.index = int(index) + self.categories = categories + self.title = title + + def value(self): + return [ + self.index, [CATEGORIES_DICT[c] for c in self.categories], + [MOVIE_TITLE_DICT[w.lower()] for w in self.title.split()] + ] + + +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.job_id = int(job_id) + + def value(self): + return [self.index, 0 if self.is_male else 1, self.age, self.job_id] + + +MOVIE_INFO = None +MOVIE_TITLE_DICT = None +CATEGORIES_DICT = None +USER_INFO = None + + +def __initialize_meta_info__(): + fn = download( + url='http://files.grouplens.org/datasets/movielens/ml-1m.zip', + md5='c4d9eecfca2ab87c1945afe126590906') + global MOVIE_INFO + if MOVIE_INFO is None: + pattern = re.compile(r'^(.*)\((\d+)\)$') + with zipfile.ZipFile(file=fn) as package: + for info in package.infolist(): + assert isinstance(info, zipfile.ZipInfo) + MOVIE_INFO = dict() + title_word_set = set() + categories_set = set() + with package.open('ml-1m/movies.dat') as movie_file: + for i, line in enumerate(movie_file): + movie_id, title, categories = line.strip().split('::') + categories = categories.split('|') + for c in categories: + categories_set.add(c) + title = pattern.match(title).group(1) + MOVIE_INFO[int(movie_id)] = MovieInfo( + index=movie_id, categories=categories, title=title) + for w in title.split(): + title_word_set.add(w.lower()) + + global MOVIE_TITLE_DICT + MOVIE_TITLE_DICT = dict() + for i, w in enumerate(title_word_set): + MOVIE_TITLE_DICT[w] = i + + global CATEGORIES_DICT + CATEGORIES_DICT = dict() + for i, c in enumerate(categories_set): + CATEGORIES_DICT[c] = i + + global USER_INFO + USER_INFO = dict() + with package.open('ml-1m/users.dat') as user_file: + for line in user_file: + uid, gender, age, job, _ = line.strip().split("::") + USER_INFO[int(uid)] = UserInfo( + index=uid, gender=gender, age=age, job_id=job) + return fn + + +def __reader__(rand_seed=0, test_ratio=0.1, is_test=False): + fn = __initialize_meta_info__() + rand = random.Random(x=rand_seed) + with zipfile.ZipFile(file=fn) as package: + with package.open('ml-1m/ratings.dat') as rating: + for line in rating: + if (rand.random() < test_ratio) == is_test: + uid, mov_id, rating, _ = line.strip().split("::") + uid = int(uid) + mov_id = int(mov_id) + rating = float(rating) * 2 - 5.0 + + mov = MOVIE_INFO[mov_id] + usr = USER_INFO[uid] + yield usr.value() + mov.value() + [[rating]] + + +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) + + +def unittest(): + for train_count, _ in enumerate(train_creator()()): + pass + for test_count, _ in enumerate(test_creator()()): + pass + + print train_count, test_count + + +if __name__ == '__main__': + unittest() From 40427979a7f621257d7171dfaefeb3afe9a0b45e Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 27 Feb 2017 23:36:28 +0800 Subject: [PATCH 14/17] refine code --- demo/mnist/api_train_v2.py | 6 ++-- python/paddle/v2/data_feeder.py | 2 +- python/paddle/v2/data_type.py | 6 ++-- python/paddle/v2/layer.py | 1 + python/paddle/v2/parameters.py | 4 +-- python/paddle/v2/tests/CMakeLists.txt | 2 +- .../{topology_test.py => test_topology.py} | 21 +++++++++----- python/paddle/v2/topology.py | 29 ++++++++----------- python/paddle/v2/trainer.py | 14 +++------ 9 files changed, 41 insertions(+), 44 deletions(-) rename python/paddle/v2/tests/{topology_test.py => test_topology.py} (81%) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index cb1191eddd..a23ddfaca0 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -41,10 +41,12 @@ def main(): trainer.train( train_data_reader=train_reader, - topology=[cost], + topology=cost, parameters=parameters, event_handler=event_handler, - batch_size=32) # batch size should be refactor in Data reader + batch_size=32, # batch size should be refactor in Data reader + reader_dict={images.name: 0, + label.name: 1}) if __name__ == '__main__': diff --git a/python/paddle/v2/data_feeder.py b/python/paddle/v2/data_feeder.py index 2a16d46dda..3b106e100c 100644 --- a/python/paddle/v2/data_feeder.py +++ b/python/paddle/v2/data_feeder.py @@ -23,7 +23,7 @@ class DataFeeder(DataProviderConverter): """ DataFeeder converts the data returned by paddle.reader into a data structure of Arguments which is defined in the API. The paddle.reader usually returns - a list of mini-batch data entries. Each data entry in the list is one sampe. + a list of mini-batch data entries. Each data entry in the list is one sample. Each sample is a list or a tuple with one feature or multiple features. DataFeeder converts this mini-batch data entries into Arguments in order to feed it to C++ interface. diff --git a/python/paddle/v2/data_type.py b/python/paddle/v2/data_type.py index dd3ebfcb42..522ddfdaac 100644 --- a/python/paddle/v2/data_type.py +++ b/python/paddle/v2/data_type.py @@ -13,10 +13,10 @@ # limitations under the License. from paddle.trainer.PyDataProvider2 import \ - InputType, dense_vector, sparse_binary_vector,\ + InputType, DataType, dense_vector, sparse_binary_vector,\ sparse_vector, integer_value, integer_value_sequence __all__ = [ - 'InputType', 'dense_vector', 'sparse_binary_vector', 'sparse_vector', - 'integer_value', 'integer_value_sequence' + 'InputType', 'DataType', 'dense_vector', 'sparse_binary_vector', + 'sparse_vector', 'integer_value', 'integer_value_sequence' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index d15e6398f5..faf5b8bd87 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -284,6 +284,7 @@ def mixed(size=0, return MixedLayerV2(size, input, name, act, bias_attr, layer_attr) +LayerV2 = Layer data = DataLayerV2 AggregateLevel = conf_helps.layers.AggregateLevel ExpandLevel = conf_helps.layers.ExpandLevel diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index b8d4b28703..7c3cde7727 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -2,7 +2,7 @@ import numpy as np import py_paddle.swig_paddle as api from paddle.proto.ParameterConfig_pb2 import ParameterConfig -import topology as v2_topology +from topology import Topology __all__ = ['Parameters', 'create'] @@ -13,7 +13,7 @@ def create(layers): :param layers: :return: """ - topology = v2_topology.Topology(layers) + topology = Topology(layers) pool = Parameters() for param in topology.proto().parameters: pool.__append_config__(param) diff --git a/python/paddle/v2/tests/CMakeLists.txt b/python/paddle/v2/tests/CMakeLists.txt index c77df827d9..46b5d08b87 100644 --- a/python/paddle/v2/tests/CMakeLists.txt +++ b/python/paddle/v2/tests/CMakeLists.txt @@ -8,5 +8,5 @@ add_test(NAME test_v2_api add_test(NAME topology_test COMMAND ${PROJ_ROOT}/paddle/.set_python_path.sh -d ${PROJ_ROOT}/python/ - ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/topology_test.py + ${PYTHON_EXECUTABLE} ${PROJ_ROOT}/python/paddle/v2/tests/test_topology.py WORKING_DIRECTORY ${PROJ_ROOT}/python/paddle) diff --git a/python/paddle/v2/tests/topology_test.py b/python/paddle/v2/tests/test_topology.py similarity index 81% rename from python/paddle/v2/tests/topology_test.py rename to python/paddle/v2/tests/test_topology.py index be60a577be..1bf55a5bc6 100644 --- a/python/paddle/v2/tests/topology_test.py +++ b/python/paddle/v2/tests/test_topology.py @@ -30,14 +30,19 @@ class TestTopology(unittest.TestCase): act=conf_helps.SoftmaxActivation()) cost = layer.classification_cost(input=inference, label=label) topo = topology.Topology(cost) - type = topo.data_type() - self.assertEqual(len(type), 2) - self.assertEqual(type[0][0], "pixel") - self.assertEqual(type[0][1].type, data_type.DataType.Dense) - self.assertEqual(type[0][1].dim, 784) - self.assertEqual(type[1][0], "label") - self.assertEqual(type[1][1].type, data_type.DataType.Index) - self.assertEqual(type[1][1].dim, 10) + data_types = topo.data_type() + self.assertEqual(len(data_types), 2) + 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].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].dim, 10) def test_get_layer(self): pixel = layer.data(name='pixel', type=data_type.dense_vector(784)) diff --git a/python/paddle/v2/topology.py b/python/paddle/v2/topology.py index 9c57f1f8e6..a51b1073b4 100644 --- a/python/paddle/v2/topology.py +++ b/python/paddle/v2/topology.py @@ -49,30 +49,30 @@ class Topology(object): result_layer = [] def find_layer_by_name(layer, layer_name): - if layer.name == layer_name and len(result_layer) == 0: + if len(result_layer) == 1: + return + elif layer.name == layer_name: result_layer.append(layer) - for parent_layer in layer.__parent_layers__.values(): - find_layer_by_name(parent_layer, layer_name) + else: + for parent_layer in layer.__parent_layers__.values(): + find_layer_by_name(parent_layer, layer_name) for layer in self.layers: find_layer_by_name(layer, name) + assert len(result_layer) == 1 return result_layer[0] - def data_layer(self): + def data_layers(self): """ get all data layer :return: """ - data_layers = [] + data_layers = set() def find_data_layer(layer): - assert isinstance(layer, layer.LayerV2) if isinstance(layer, v2_layer.DataLayerV2): - if len( - filter(lambda data_layer: data_layer.name == layer.name, - data_layers)) == 0: - data_layers.append(layer) + data_layers.add(layer) for parent_layer in layer.__parent_layers__.values(): find_data_layer(parent_layer) @@ -85,14 +85,9 @@ class Topology(object): """ get data_type from proto, such as: [('image', dense_vector(768)), ('label', integer_value(10))] - the order is the same with __model_config__.input_layer_names """ - data_types_lists = [] - for layer_name in self.__model_config__.input_layer_names: - data_types_lists.append( - (layer_name, self.get_layer(layer_name).type)) - - return data_types_lists + return [(data_layer.name, data_layer.type) + for data_layer in self.data_layers()] def __check_layer_type__(layer): diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 96a3ee4fd4..3bf2128e16 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -1,13 +1,12 @@ import collections import py_paddle.swig_paddle as api -from py_paddle import DataProviderConverter from data_feeder import DataFeeder +from topology import Topology from . import event as v2_event from . import optimizer as v2_optimizer from . import parameters as v2_parameters -from . import topology as v2_topology __all__ = ['ITrainer', 'SGD'] @@ -69,7 +68,6 @@ class SGD(ITrainer): test_data_reader=None, event_handler=None, batch_size=32, - data_types=None, reader_dict=None): """ Training method. Will train num_passes of input data. @@ -83,13 +81,12 @@ class SGD(ITrainer): occurred. :type event_handler: (BaseEvent) => None :param batch_size: Not important, will be removed after data refactor. - :param data_types: Not important, will be removed after data refactor. :return: """ if event_handler is None: event_handler = default_event_handler - topology = v2_topology.Topology(topology) + topology = Topology(topology) __check_train_args__(**locals()) @@ -109,10 +106,7 @@ class SGD(ITrainer): assert isinstance(pass_evaluator, api.Evaluator) out_args = api.Arguments.createArguments(0) - data_types_lists = [data_type[1] for data_type in topology.data_type()] - converter = DataProviderConverter(input_types=data_types_lists) - - feeder = DataFeeder(data_types, reader_dict) + feeder = DataFeeder(topology.data_type(), reader_dict) for pass_id in xrange(num_passes): event_handler(v2_event.BeginPass(pass_id)) @@ -195,7 +189,7 @@ def __check_train_args__(train_data_reader, topology, parameters, raise ValueError('test_data_reader should be a function, which can ' 'return a iterator') - if not isinstance(topology, v2_topology.Topology): + if not isinstance(topology, Topology): raise ValueError('topology should be a model config') if not isinstance(parameters, v2_parameters.Parameters): From 305566eed4a62a7af178b78ea21f89c8eb73b59b Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Mon, 27 Feb 2017 15:09:56 -0800 Subject: [PATCH 15/17] fix parameters.append_gradient_machine append_gradient_machine should append __gradient_machines__ in all conditions. --- python/paddle/v2/parameters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/parameters.py b/python/paddle/v2/parameters.py index ea504d5104..f2c5a4d49c 100644 --- a/python/paddle/v2/parameters.py +++ b/python/paddle/v2/parameters.py @@ -224,7 +224,8 @@ class Parameters(object): except ValueError: # If no such parameter in gradient machine, then don't copy pass - self.__gradient_machines__.append(gradient_machine) + + self.__gradient_machines__.append(gradient_machine) def __get_parameter_in_gradient_machine__(gradient_machine, name): From 20d9220c9145e937da9f0fb9b99323a06b6983bc Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 28 Feb 2017 10:27:46 +0800 Subject: [PATCH 16/17] change the parameter topology of trainer to cost --- demo/mnist/api_train_v2.py | 2 +- python/paddle/v2/trainer.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/mnist/api_train_v2.py b/demo/mnist/api_train_v2.py index a23ddfaca0..8a612cbc66 100644 --- a/demo/mnist/api_train_v2.py +++ b/demo/mnist/api_train_v2.py @@ -41,7 +41,7 @@ def main(): trainer.train( train_data_reader=train_reader, - topology=cost, + cost=cost, parameters=parameters, event_handler=event_handler, batch_size=32, # batch size should be refactor in Data reader diff --git a/python/paddle/v2/trainer.py b/python/paddle/v2/trainer.py index 3bf2128e16..be33b91080 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -62,7 +62,7 @@ class SGD(ITrainer): def train(self, train_data_reader, - topology, + cost, parameters, num_passes=1, test_data_reader=None, @@ -73,7 +73,7 @@ class SGD(ITrainer): Training method. Will train num_passes of input data. :param train_data_reader: - :param topology: cost layers, use one or more Layers to represent it. + :param cost: cost layers, to be optimized. :param parameters: The parameter pools. :param num_passes: The total train passes. :param test_data_reader: @@ -86,7 +86,7 @@ class SGD(ITrainer): if event_handler is None: event_handler = default_event_handler - topology = Topology(topology) + topology = Topology(cost) __check_train_args__(**locals()) From 5f5e5c32e50099df02e516647192c5a07b588f99 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Tue, 28 Feb 2017 10:33:46 +0800 Subject: [PATCH 17/17] modify train in ITrainer --- 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 be33b91080..2aeddaff89 100644 --- a/python/paddle/v2/trainer.py +++ b/python/paddle/v2/trainer.py @@ -29,7 +29,7 @@ class ITrainer(object): def train(self, train_data_reader, - topology, + cost, parameters, test_data_reader=None, event_handler=None): @@ -37,7 +37,7 @@ class ITrainer(object): train method. :param train_data_reader: - :param topology: + :param cost: :param parameters: :param test_data_reader: :param event_handler: