From cfbfa0a1f2fd789036510a84ea4ff60e026d44a6 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 13:02:19 +0800 Subject: [PATCH 1/6] Fix typo --- python/paddle/v2/config_base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index 1ec1d7bbdf..abf77125e3 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -65,7 +65,7 @@ class Layer(object): def __init__(self, name=None, parent_layers=None): assert isinstance(parent_layers, dict) self.name = name - self.__contex__ = {} + self.__context__ = {} self.__parent_layers__ = parent_layers def to_proto(self, context): @@ -87,7 +87,7 @@ class Layer(object): return self.to_proto_impl(**kwargs) elif self.context_name() not in context: context[self.context_name()] = self.to_proto_impl(**kwargs) - self.__contex__ = context + self.__context__ = context if self.use_context_name(): return context[self.context_name()] else: @@ -113,7 +113,7 @@ class Layer(object): this layer is called. :return: """ - return self.__contex__[self.context_name()].size + return self.__context__[self.context_name()].size def __convert_to_v2__(method_name, parent_names, is_default_name=True): From abd6e0cd1351d9871d0d04704666b3d0a1ac22aa Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 13:52:30 +0800 Subject: [PATCH 2/6] Complete Evaluators in paddle.v2 --- python/paddle/v2/__init__.py | 3 +- python/paddle/v2/config_base.py | 62 +++++++++++++++++++++++----- python/paddle/v2/evaluators.py | 40 ++++++++++++++++++ python/paddle/v2/tests/test_layer.py | 16 +++++++ 4 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 python/paddle/v2/evaluators.py diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index 2c5daeb9b0..e8eb88a7c8 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -21,6 +21,7 @@ import data_type import topology import data_feeder import networks +import evaluators from . import dataset from . import reader from . import plot @@ -35,7 +36,7 @@ import plot __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader', - 'topology', 'networks', 'infer', 'plot' + 'topology', 'networks', 'infer', 'plot', 'evaluators' ] diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index abf77125e3..0069f1e594 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -67,11 +67,25 @@ class Layer(object): self.name = name self.__context__ = {} self.__parent_layers__ = parent_layers + self.__children_layers__ = [] # used for evaluator. + + def append_child(self, layer, parent_names): + self.__children_layers__.append((layer, parent_names)) def to_proto(self, context): """ function to set proto attribute """ + self.__context__ = context + + # short cut if myself is parsed before. + if self.context_name() in context: + if self.use_context_name(): + return context[self.context_name()] + else: + return context[self.name] + + # parse parent before myself kwargs = dict() for layer_name in self.__parent_layers__: if not isinstance(self.__parent_layers__[layer_name], @@ -83,15 +97,27 @@ class Layer(object): self.__parent_layers__[layer_name]) kwargs[layer_name] = v1_layer - if self.context_name() is None: - return self.to_proto_impl(**kwargs) - elif self.context_name() not in context: - context[self.context_name()] = self.to_proto_impl(**kwargs) - self.__context__ = context - if self.use_context_name(): - return context[self.context_name()] - else: - return context[self.name] + # parse myself. + ret_val = self.to_proto_impl(**kwargs) + if self.context_name() is not None: + assert self.context_name() not in context + # add myself to context + context[self.context_name()] = ret_val + + # parse children. + for layer, pnames in self.__children_layers__: + drop = False + + # child will only be parsed if all parents are in context. + for pname in pnames: + if pname not in context: + drop = True + break + if drop: + continue + layer.to_proto(context=context) + + return ret_val def to_proto_impl(self, **kwargs): raise NotImplementedError() @@ -116,7 +142,10 @@ class Layer(object): return self.__context__[self.context_name()].size -def __convert_to_v2__(method_name, parent_names, is_default_name=True): +def __convert_to_v2__(method_name, + parent_names, + is_default_name=True, + attach_parent=False): if is_default_name: wrapper = wrap_name_default(name_prefix=method_name) else: @@ -129,9 +158,20 @@ def __convert_to_v2__(method_name, parent_names, is_default_name=True): parent_layers = dict() other_kwargs = dict() for pname in parent_names: - if kwargs.has_key(pname): + if pname in kwargs: parent_layers[pname] = kwargs[pname] + if attach_parent: + pnames = [x.name for x in parent_layers.values()] + + for pname in parent_layers: + layers = kwargs[pname] + if not isinstance(layers, collections.Sequence): + layers = [layers] + + for layer in layers: + layer.append_child(self, pnames) + for key in kwargs.keys(): if key not in parent_names: other_kwargs[key] = kwargs[key] diff --git a/python/paddle/v2/evaluators.py b/python/paddle/v2/evaluators.py new file mode 100644 index 0000000000..5cda1a2597 --- /dev/null +++ b/python/paddle/v2/evaluators.py @@ -0,0 +1,40 @@ +# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import paddle.trainer_config_helpers.evaluators as evs +import inspect +from config_base import __convert_to_v2__ + +__all__ = [] + + +def initialize(): + for __ev_name__ in filter(lambda x: x.endswith('_evaluator'), evs.__all__): + __ev__ = getattr(evs, __ev_name__) + if hasattr(__ev__, 'argspec'): + argspec = __ev__.argspec + else: + argspec = inspect.getargspec(__ev__) + parent_names = filter(lambda x: x in ['input', 'label'], argspec.args) + v2_ev = __convert_to_v2__( + __ev_name__, + parent_names=parent_names, + is_default_name='name' in argspec.args, + attach_parent=True) + globals()[__ev_name__] = v2_ev + globals()[__ev_name__].__name__ = __ev_name__ + __all__.append(__ev_name__) + + +initialize() diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 89cc928dd7..0fb76363f9 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -19,6 +19,7 @@ import paddle.v2.data_type as data_type import paddle.v2.layer as layer import paddle.v2.pooling as pooling import paddle.v2.networks as networks +import paddle.v2.evaluators as evaluators pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -262,5 +263,20 @@ class NetworkTests(unittest.TestCase): print layer.parse_network(vgg_out) +class EvaluatorTest(unittest.TestCase): + def test_evaluator(self): + img = layer.data(name='pixel', type=data_type.dense_vector(784)) + output = layer.fc(input=img, + size=10, + act=activation.Softmax(), + name='fc_here') + lbl = layer.data(name='label', type=data_type.integer_value(10)) + cost = layer.cross_entropy_cost(input=output, label=lbl) + + evaluators.classification_error_evaluator(input=output, label=lbl) + print layer.parse_network(cost) + print layer.parse_network(output) + + if __name__ == '__main__': unittest.main() From b968b5ef66131887023ab4d465d4d66dfa78bd55 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 13:55:48 +0800 Subject: [PATCH 3/6] Use context name instead of name --- python/paddle/v2/config_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index 0069f1e594..cce12c5bf9 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -162,7 +162,7 @@ def __convert_to_v2__(method_name, parent_layers[pname] = kwargs[pname] if attach_parent: - pnames = [x.name for x in parent_layers.values()] + pnames = [x.context_name() for x in parent_layers.values()] for pname in parent_layers: layers = kwargs[pname] From 606a99d935aac8384593b3550eceb90c44faab57 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 15:44:02 +0800 Subject: [PATCH 4/6] Fix unittest for rnn. --- python/paddle/v2/config_base.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index cce12c5bf9..96a1c70ede 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -99,9 +99,9 @@ class Layer(object): # parse myself. ret_val = self.to_proto_impl(**kwargs) - if self.context_name() is not None: - assert self.context_name() not in context - # add myself to context + + if self.context_name() is not None and \ + self.context_name() not in context: context[self.context_name()] = ret_val # parse children. @@ -117,7 +117,10 @@ class Layer(object): continue layer.to_proto(context=context) - return ret_val + if self.use_context_name(): + return context[self.context_name()] + else: + return context[self.name] def to_proto_impl(self, **kwargs): raise NotImplementedError() From a125ef1abd699adac966868dd8d02ff06a61ccfd Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 16:40:47 +0800 Subject: [PATCH 5/6] Fix unittest --- python/paddle/v2/config_base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/paddle/v2/config_base.py b/python/paddle/v2/config_base.py index 96a1c70ede..cb98866d87 100644 --- a/python/paddle/v2/config_base.py +++ b/python/paddle/v2/config_base.py @@ -117,7 +117,9 @@ class Layer(object): continue layer.to_proto(context=context) - if self.use_context_name(): + if self.context_name() is None: + return ret_val + elif self.use_context_name(): return context[self.context_name()] else: return context[self.name] From e7b3a5f1c8ac7cb384d6a593f58018596806051c Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 16:50:32 +0800 Subject: [PATCH 6/6] Follow comments --- python/paddle/v2/__init__.py | 4 ++-- python/paddle/v2/{evaluators.py => evaluator.py} | 15 +++++++++++---- python/paddle/v2/tests/test_layer.py | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) rename python/paddle/v2/{evaluators.py => evaluator.py} (76%) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index e8eb88a7c8..7c8f6ea62f 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -21,7 +21,7 @@ import data_type import topology import data_feeder import networks -import evaluators +import evaluator from . import dataset from . import reader from . import plot @@ -36,7 +36,7 @@ import plot __all__ = [ 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', 'event', 'data_type', 'attr', 'pooling', 'data_feeder', 'dataset', 'reader', - 'topology', 'networks', 'infer', 'plot', 'evaluators' + 'topology', 'networks', 'infer', 'plot', 'evaluator' ] diff --git a/python/paddle/v2/evaluators.py b/python/paddle/v2/evaluator.py similarity index 76% rename from python/paddle/v2/evaluators.py rename to python/paddle/v2/evaluator.py index 5cda1a2597..588eefa391 100644 --- a/python/paddle/v2/evaluators.py +++ b/python/paddle/v2/evaluator.py @@ -20,21 +20,28 @@ __all__ = [] def initialize(): + def convert_to_new_name(nm): + return nm[:-len("_evaluator")] + for __ev_name__ in filter(lambda x: x.endswith('_evaluator'), evs.__all__): __ev__ = getattr(evs, __ev_name__) if hasattr(__ev__, 'argspec'): argspec = __ev__.argspec else: argspec = inspect.getargspec(__ev__) - parent_names = filter(lambda x: x in ['input', 'label'], argspec.args) + parent_names = filter(lambda x: x in ['input', 'label', 'weight'], + argspec.args) v2_ev = __convert_to_v2__( __ev_name__, parent_names=parent_names, is_default_name='name' in argspec.args, attach_parent=True) - globals()[__ev_name__] = v2_ev - globals()[__ev_name__].__name__ = __ev_name__ - __all__.append(__ev_name__) + + __new_name__ = convert_to_new_name(__ev_name__) + + globals()[__new_name__] = v2_ev + globals()[__new_name__].__name__ = __new_name__ + __all__.append(__new_name__) initialize() diff --git a/python/paddle/v2/tests/test_layer.py b/python/paddle/v2/tests/test_layer.py index 0fb76363f9..2378f68ea8 100644 --- a/python/paddle/v2/tests/test_layer.py +++ b/python/paddle/v2/tests/test_layer.py @@ -19,7 +19,7 @@ import paddle.v2.data_type as data_type import paddle.v2.layer as layer import paddle.v2.pooling as pooling import paddle.v2.networks as networks -import paddle.v2.evaluators as evaluators +import paddle.v2.evaluator as evaluator pixel = layer.data(name='pixel', type=data_type.dense_vector(128)) label = layer.data(name='label', type=data_type.integer_value(10)) @@ -273,7 +273,7 @@ class EvaluatorTest(unittest.TestCase): lbl = layer.data(name='label', type=data_type.integer_value(10)) cost = layer.cross_entropy_cost(input=output, label=lbl) - evaluators.classification_error_evaluator(input=output, label=lbl) + evaluator.classification_error(input=output, label=lbl) print layer.parse_network(cost) print layer.parse_network(output)