diff --git a/demo/mnist/api_train.py b/demo/mnist/api_train.py index 8573d8143a085b8d2e0bcf7df17b1abe177029df..6d071cdffe120f7d37edfa53b9813d138fdf76d0 100644 --- a/demo/mnist/api_train.py +++ b/demo/mnist/api_train.py @@ -6,25 +6,16 @@ passed to C++ side of Paddle. The user api could be simpler and carefully designed. """ -import py_paddle.swig_paddle as api -from py_paddle import DataProviderConverter -import paddle.trainer.PyDataProvider2 as dp -import numpy as np import random -from mnist_util import read_from_mnist -from paddle.trainer_config_helpers import * -import paddle.v2 +import numpy as np +import paddle.trainer.PyDataProvider2 as dp +import paddle.v2 +import py_paddle.swig_paddle as api +from paddle.trainer_config_helpers import * +from py_paddle import DataProviderConverter -def network_config(): - imgs = data_layer(name='pixel', size=784) - hidden1 = fc_layer(input=imgs, size=200) - hidden2 = fc_layer(input=hidden1, size=200) - inference = fc_layer(input=hidden2, size=10, act=SoftmaxActivation()) - cost = classification_cost( - input=inference, label=data_layer( - name='label', size=10)) - outputs(cost) +from mnist_util import read_from_mnist def init_parameter(network): @@ -79,8 +70,17 @@ def main(): updater = optimizer.create_local_updater() assert isinstance(updater, api.ParameterUpdater) + # define network + images = paddle.v2.layers.data_layer(name='pixel', size=784) + label = paddle.v2.layers.data_layer(name='label', size=10) + hidden1 = paddle.v2.layers.fc_layer(input=images, size=200) + hidden2 = paddle.v2.layers.fc_layer(input=hidden1, size=200) + inference = paddle.v2.layers.fc_layer( + input=hidden2, size=10, act=SoftmaxActivation()) + cost = paddle.v2.layers.classification_cost(input=inference, label=label) + # Create Simple Gradient Machine. - model_config = parse_network_config(network_config) + model_config = paddle.v2.layers.parse_network(cost) m = api.GradientMachine.createFromConfigProto(model_config, api.CREATE_MODE_NORMAL, optimizer.enable_types()) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index b2ea87b086101d71e89c33ce7c1f4eb21afade5a..c04c0cc73a800a2c0bf12d2efb176e6683f185ee 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -13,5 +13,6 @@ # limitations under the License. import optimizer +import layers -__all__ = ['optimizer'] +__all__ = ['optimizer', 'layers'] diff --git a/python/paddle/v2/layers.py b/python/paddle/v2/layers.py new file mode 100644 index 0000000000000000000000000000000000000000..14efe9412c3582054598e986d31c694eef8bee97 --- /dev/null +++ b/python/paddle/v2/layers.py @@ -0,0 +1,112 @@ +# 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 as conf_helps +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 + + +class Layer(object): + def __init__(self, name, parent_layer): + assert isinstance(parent_layer, dict) + assert isinstance(name, basestring) + self.name = name + self.__parent_layer__ = parent_layer + + def to_proto(self, context): + """ + function to set proto attribute + """ + kwargs = dict() + for param_name in self.__parent_layer__: + if not isinstance(self.__parent_layer__[param_name], + collections.Sequence): + param_value = self.__parent_layer__[param_name].to_proto( + context=context) + else: + param_value = map(lambda x: x.to_proto(context=context), + self.__parent_layer__[param_name]) + kwargs[param_name] = param_value + + if self.name not in context: + context[self.name] = self.to_proto_impl(**kwargs) + return context[self.name] + + def to_proto_impl(self, **kwargs): + raise NotImplementedError() + + +def parse_network(*outputs): + def __real_func__(): + context = dict() + real_output = [each.to_proto(context=context) for each in outputs] + conf_helps.outputs(real_output) + + return __parse__(__real_func__) + + +def __convert__(method_name, name_prefix, parent_names): + if name_prefix is not None: + wrapper = wrap_name_default(name_prefix=name_prefix) + else: + wrapper = None + + class __Impl__(Layer): + def __init__(self, name=None, **kwargs): + parent_layers = dict() + other_kwargs = dict() + for pname in parent_names: + parent_layers[pname] = kwargs[pname] + + for key in kwargs.keys(): + if key not in parent_names: + other_kwargs[key] = kwargs[key] + + super(__Impl__, self).__init__(name, parent_layers) + self.__other_kwargs__ = other_kwargs + + if wrapper is not None: + __init__ = wrapper(__init__) + + def to_proto_impl(self, **kwargs): + args = dict() + for each in kwargs: + args[each] = kwargs[each] + for each in self.__other_kwargs__: + args[each] = self.__other_kwargs__[each] + return getattr(conf_helps, method_name)(name=self.name, **args) + + return __Impl__ + + +data_layer = __convert__('data_layer', None, []) +fc_layer = __convert__('fc_layer', name_prefix='fc', parent_names=['input']) +classification_cost = __convert__( + 'classification_cost', + name_prefix='classification_cost', + parent_names=['input', 'label']) + +__all__ = ['data_layer', 'fc_layer', 'classification_cost', 'parse_network'] + +if __name__ == '__main__': + data = data_layer(name='pixel', size=784) + hidden = fc_layer(input=data, size=100, act=conf_helps.SigmoidActivation()) + predict = fc_layer( + input=[hidden, data], size=10, act=conf_helps.SoftmaxActivation()) + cost = classification_cost( + input=predict, label=data_layer( + name='label', size=10)) + print parse_network(cost)