From abd6e0cd1351d9871d0d04704666b3d0a1ac22aa Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 5 Apr 2017 13:52:30 +0800 Subject: [PATCH] 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 2c5daeb9b09..e8eb88a7c84 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 abf77125e38..0069f1e5948 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 00000000000..5cda1a25977 --- /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 89cc928dd7f..0fb76363f95 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() -- GitLab