From 281652d5a510b6d5acfee320b082a52f3b3a701c Mon Sep 17 00:00:00 2001 From: Gai Yu Date: Sun, 14 May 2017 00:47:53 +0800 Subject: [PATCH 1/5] fix travis error --- minpy/nn/model_builder.py | 48 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/minpy/nn/model_builder.py b/minpy/nn/model_builder.py index 9c33023..099b6fa 100644 --- a/minpy/nn/model_builder.py +++ b/minpy/nn/model_builder.py @@ -127,8 +127,8 @@ def __str__(self): def forward(self, *args): # It is recommended that all forward functions, especially those in Sequential, only receive positional arguments. - to_tuple = lambda results : results if isinstance(results, tuple) else (results,) - forward_module = lambda args, module : to_tuple(module(*args)) + to_tuple = lambda results: results if isinstance(results, tuple) else (results,) + forward_module = lambda args, module: to_tuple(module(*args)) result = _reduce(forward_module, self._modules, args) if len(result) == 1: result, = result return result @@ -200,8 +200,8 @@ def __init__(self, left, right, name=None): # TODO div etc. def _register_configs(configs, to_register): - ''' param dict configs: pair param_name(str) : param_configs(dict) - param to_register: pair param_name(str) : param_configs(dict) or attr(str) : attr_value(object) + ''' param dict configs: pair param_name(str): param_configs(dict) + param to_register: pair param_name(str): param_configs(dict) or attr(str): attr_value(object) ''' _configs = {} @@ -250,21 +250,21 @@ def __init__(self, params=None, aux_params=None, name=None): # default init configs default_init_configs = \ - {name : self._get_default_init_config(name) for name in self._module_param_names} + {name: self._get_default_init_config(name) for name in self._module_param_names} default_init_configs.update( - {name : self._get_default_init_config(name) for name in self._module_aux_param_names} + {name: self._get_default_init_config(name) for name in self._module_aux_param_names} ) - self._init_configs = {name : {} for name in self._param_names} - self._init_configs.update({name : {} for name in self._aux_param_names}) + self._init_configs = {name: {} for name in self._param_names} + self._init_configs.update({name: {} for name in self._aux_param_names}) self._register_init_configs(default_init_configs) # default update configs # user must specify update configs explicitly - default_update_configs = {'update_rule' : 'unspecified'} + default_update_configs = {'update_rule': 'unspecified'} - self._update_configs = {name : {} for name in self._param_names} + self._update_configs = {name: {} for name in self._param_names} self._register_update_configs(default_update_configs) @@ -278,9 +278,9 @@ def __call__(self, *args, **kwargs): assert bool(self._model), 'A parameterized layer must be bound to a model.' array_args = tuple(filter(_is_array, args)) - array_kwargs = {key : value for key, value in kwargs.items() if is_array(value)} + array_kwargs = {key: value for key, value in kwargs.items() if is_array(value)} - get_shape = lambda array : array.shape + get_shape = lambda array: array.shape arg_shapes = tuple(map(get_shape, array_args)) kwarg_shapes = dict(zip(array_kwargs.keys(), tuple(map(get_shape, array_kwargs.values())))) @@ -310,19 +310,19 @@ def _affiliate_to(self, model): @staticmethod def _get_default_init_config(param_name): if 'weight' in param_name: - return {'init_rule' : 'xavier'} + return {'init_rule': 'xavier'} elif 'bias' in param_name: - return {'init_rule' : 'constant', 'value' : 0} + return {'init_rule': 'constant', 'value': 0} elif 'beta' in param_name: - return {'init_rule' : 'constant', 'value' : 0} + return {'init_rule': 'constant', 'value': 0} elif 'gamma' in param_name: - return {'init_rule' : 'constant', 'value' : 1} + return {'init_rule': 'constant', 'value': 1} elif 'moving_mean' in param_name: - return {'init_rule' : 'constant', 'value' : 0} + return {'init_rule': 'constant', 'value': 0} elif 'moving_var' in param_name: - return {'init_rule' : 'constant', 'value' : 1} + return {'init_rule': 'constant', 'value': 1} else: - return {'init_rule' : 'constant', 'value' : 0} + return {'init_rule': 'constant', 'value': 0} def _init_params(self, param_shapes, context): # param_shapes: dict @@ -367,12 +367,12 @@ def _get_aux_params(self, *aux_param_names): def _parse_param_configs(self, configs): ''' parsed configs might contain: - 1. pair param_name(str) : configs(dict), which are parameter-specific configs - 2. pair attr_name(str) : attr_value(object), which are global configs + 1. pair param_name(str): configs(dict), which are parameter-specific configs + 2. pair attr_name(str): attr_value(object), which are global configs ''' if configs is None: return {} - _configs = {key : value for key, value in configs.items()} + _configs = {key: value for key, value in configs.items()} for identifier in _configs: if isinstance(identifier, tuple): # configs applied to a group of parameters @@ -477,8 +477,8 @@ def __setattr__(self, attr, attr_value): object.__setattr__(self, attr, attr_value) def _register_model(self, model): - model.attach = lambda _, name, array : self.attach(name, array) - model.detach = lambda _, name : self.detach(name) + model.attach = lambda _, name, array: self.attach(name, array) + model.detach = lambda _, name: self.detach(name) def _register_module(self, module): # check duplication From a275265362b5151e1bdb46e6f4c779b3fcefaabb Mon Sep 17 00:00:00 2001 From: Gai Yu Date: Sun, 14 May 2017 01:23:00 +0800 Subject: [PATCH 2/5] fix travis errors --- minpy/nn/model_builder.py | 86 ++++++++++++++++++++++++++++++++++++++- minpy/nn/modules.py | 54 +++++++++++++----------- 2 files changed, 115 insertions(+), 25 deletions(-) diff --git a/minpy/nn/model_builder.py b/minpy/nn/model_builder.py index 099b6fa..5b9abdf 100644 --- a/minpy/nn/model_builder.py +++ b/minpy/nn/model_builder.py @@ -1,3 +1,8 @@ +""" +Infrastructures for building models. +""" + + from functools import reduce as _reduce import operator as _operator @@ -10,6 +15,7 @@ import minpy.nn.model as _model +# pylint: disable=locally-disabled, invalid-name _module_counter = {} @@ -43,9 +49,13 @@ def __init__(self, name): @property def name(self): + """ A module's unique name. + """ return self._name def forward(self, *args, **kwargs): + """ A virtual method. + """ raise NotImplementedError() def __call__(self, *args, **kwargs): @@ -84,6 +94,8 @@ def _affiliate_to(self, model): class Container(Module): + """ An abstract class for containers of modules. + """ # TODO provide an interface for indexing contained modules def __init__(self, name): super(Container, self).__init__(name) @@ -92,13 +104,19 @@ def __call__(self, *args, **kwargs): return self.forward(*args, **kwargs) def param_shapes(self, input_shape): + """ Infer the shapes of parameters given input shape. + """ return {} def aux_param_shapes(self, input_shape): + """ Infer the shapes of auxiliary parameters given input shape. + """ return {} class Sequential(Container): + """ A sequentially-arranged group of modules. + """ _module_name = 'sequential' def __init__(self, *args, **kwargs): """ Sequential network. @@ -134,10 +152,14 @@ def forward(self, *args): return result def training(self): + """ Set module's state to training. + """ for module in self._modules: module.training() def inference(self): + """ Set module's state to inference. + """ for module in self._modules: module.inference() @@ -145,12 +167,17 @@ def _affiliate_to(self, model): for module in self._modules: module._affiliate_to(model) + class Parallel(Container): + """ An abstract class for implementing containers of parallel modules. + """ def __init__(self, name=None): super(Parallel, self).__init__(name) class Binary(Parallel): + """ An abstract class for implementing containers of binary parallel modules. + """ # TODO training/inference def __init__(self, left, right, operator, name): super(Binary, self).__init__(name) @@ -167,10 +194,14 @@ def forward(self, X): return self._operator(left, right) def training(self): + """ Set module's state to training. + """ self._left.training() self._right.training() def inference(self): + """ Set module's state to inference. + """ self._left.inference() self._right.inference() @@ -180,18 +211,24 @@ def _affiliate_to(self, model): class Add(Binary): + """ lhs_module + rhs_module + """ _module_name = 'add' def __init__(self, left, right, name=None): super(Add, self).__init__(left, right, _operator.add, name) class Sub(Binary): + """ lhs_module - rhs_module + """ _module_name = 'sub' def __init__(self, left, right, name=None): super(Sub, self).__init__(left, right, _operator.sub, name) class Mul(Binary): + """ lhs_module * rhs_module + """ _module_name = 'mul' def __init__(self, left, right, name=None): super(Mul, self).__init__(left, right, _operator.mul, name) @@ -199,6 +236,7 @@ def __init__(self, left, right, name=None): # TODO div etc. + def _register_configs(configs, to_register): ''' param dict configs: pair param_name(str): param_configs(dict) param to_register: pair param_name(str): param_configs(dict) or attr(str): attr_value(object) @@ -226,6 +264,8 @@ def _register_configs(configs, to_register): class Layer(Module): + """ An abstract class for parameterized layers. + """ def __init__(self, params=None, aux_params=None, name=None): ''' Currently, a layer must be bound to a model. @@ -412,29 +452,45 @@ def forward(self, *args, **kwargs): raise NotImplementedError() def training(self): + """ Set module's state to training. + """ self._mode = 'training' def inference(self): + """ Set module's state to inference. + """ self._mode = 'inference' @property def param_dict(self): + """ Returns a dict containing the parameters of a layer. + """ return dict(zip(self._param_names, self._get_params(*self._param_names))) @property def aux_param_dict(self): + """ Returns a dict containing the auxiliary parameters of a layer. + """ return dict(zip(self._aux_param_names, self._get_aux_params(*self._aux_param_names))) + # TODO privatize method def param_shapes(self, *args, **kwargs): + """ Infer parameter shapes. + """ # customized layer must specify the shapes of ALL params return {} + # TODO privatize method def aux_param_shapes(self, *args, **kwargs): + """ Infer auxiliary parameter shapes. + """ # customized layer must specify the shapes of ALL aux params return {} class Model(_model.ModelBase): + """ A trainable model. + """ # TODO detach/resume (parameter, layer) # TODO check duplicated layers def __init__(self, loss=None, attach_all=True, jit=True): @@ -529,6 +585,8 @@ def forward_batch(self): @staticmethod def decorator(f): + """ Decorator for model.forward and model.loss. + """ def wrapped(self, *args, **kwargs): is_train = kwargs.pop('is_train', False) @@ -555,29 +613,45 @@ def wrapped(self, *args, **kwargs): return wrapped def attach(self, name, array): + """ Attach an array to computation graph. + Inputs: + - name: a str + - array: mxnet.ndarray.NDArray + """ if name not in self.grad_dict: self.grad_dict[name] = _nd.NDArray(_nd._new_alloc_handle(array.shape, array.context, True, array.dtype)) _autograd.mark_variables((array,), (self.grad_dict[name],)) return self def detach(self, name): + """ Detach an array from computation graph. + (not implemented) + """ raise NotImplementedError() def grad(self): + """ Returns a function that computes gradients. + (not implemented) + """ raise NotImplementedError() def grad_and_loss(self, data, labels): + """ Returns a function that computes gradients and loss. + (not implemented) + """ raise NotImplementedError() # TODO load/save (inherited method) def training(self): - # training mode + """ Set model's state to training. + """ for module in self._modules: module.training() def inference(self): - # inference mode + """ Set model's state to inference. + """ for module in self._modules: module.inference() @@ -614,16 +688,24 @@ def __setitem__(self, param_name, configs): self._configs[param_name] = dict(configs) def keys(self): + """ Returns keys of configuration dict. + """ return self._configs.keys() def values(self): + """ Returns keys of configuration dict. + """ return self._configs.values() def items(self): + """ Returns items of configuration dict. + """ return self._configs.items() class Updater(_ConfigParser): + """ Optimizer. + """ def __init__(self, model, **kwargs): # duplicate so that there could be multiple updaters for one model configs = dict(model._update_configs) diff --git a/minpy/nn/modules.py b/minpy/nn/modules.py index 08d0b92..5e6eb8b 100644 --- a/minpy/nn/modules.py +++ b/minpy/nn/modules.py @@ -1,3 +1,8 @@ +""" +Modules +""" + + import mxnet.ndarray as _nd import mxnet.symbol as _symbol @@ -17,14 +22,14 @@ def __init__(self, operator_name, **kwargs): self._kwargs = dict(kwargs) - kwargs.update({v : _symbol.Variable(v) for v in self._variables}) + kwargs.update({v: _symbol.Variable(v) for v in self._variables}) self._symbol = getattr(_symbol, operator_name)(name='symbol', **kwargs) self._operator = getattr(_nd, operator_name) self._module_name = operator_name.lower() - eliminate_prefix = lambda name : name.replace('symbol_', '') + eliminate_prefix = lambda name: name.replace('symbol_', '') params = set(self._symbol.list_arguments()) params = params.difference(set(self._variables)) @@ -36,7 +41,7 @@ def __init__(self, operator_name, **kwargs): super(_Operatorized, self).__init__(params, aux_params, name) def forward(self, *args, **kwargs): - is_array = lambda array : isinstance(array, _nd.NDArray) + is_array = lambda array: isinstance(array, _nd.NDArray) kwarg_dict = dict(zip(self._variables, filter(is_array, args))) for key, value in kwargs.items(): @@ -60,7 +65,7 @@ def param_shapes(self, *args, **kwargs): for param_name, shape in shapes.items(): shapes[param_name.replace('symbol_', '')] = shapes.pop(param_name) local_to_global = dict(zip(self._module_param_names, self._param_names)) - shapes = {local_to_global[name] : shape for name, shape in shapes.items()} + shapes = {local_to_global[name]: shape for name, shape in shapes.items()} return shapes # TODO @@ -75,26 +80,29 @@ def aux_param_shapes(self, *args, **kwargs): 1. an operator is parameterized 2. an operator fits into frameworks of containers, especially Sequential ''' -Activation = lambda **kwargs : _Operatorized('Activation', **kwargs) -BatchNorm = lambda **kwargs : _Operatorized('BatchNorm', **kwargs) -Convolution = lambda **kwargs : _Operatorized('Convolution', **kwargs) -Deconvolution = lambda **kwargs : _Operatorized('Deconvolution', **kwargs) -Dropout = lambda **kwargs : _Operatorized('Dropout', **kwargs) -Embedding = lambda **kwargs : _Operatorized('Embedding', **kwargs) -FullyConnected = lambda **kwargs : _Operatorized('FullyConnected', **kwargs) -LeakyReLU = lambda **kwargs : _Operatorized('LeakyReLU', **kwargs) -Pooling = lambda **kwargs : _Operatorized('Pooling', **kwargs) -RNN = lambda **kwargs : _Operatorized('RNN', **kwargs) +# pylint: disable=locally-disabled, invalid-name +Activation = lambda **kwargs: _Operatorized('Activation', **kwargs) +BatchNorm = lambda **kwargs: _Operatorized('BatchNorm', **kwargs) +Convolution = lambda **kwargs: _Operatorized('Convolution', **kwargs) +Deconvolution = lambda **kwargs: _Operatorized('Deconvolution', **kwargs) +Dropout = lambda **kwargs: _Operatorized('Dropout', **kwargs) +Embedding = lambda **kwargs: _Operatorized('Embedding', **kwargs) +FullyConnected = lambda **kwargs: _Operatorized('FullyConnected', **kwargs) +LeakyReLU = lambda **kwargs: _Operatorized('LeakyReLU', **kwargs) +Pooling = lambda **kwargs: _Operatorized('Pooling', **kwargs) +RNN = lambda **kwargs: _Operatorized('RNN', **kwargs) # grammar sugar -ReLU = lambda : _Operatorized('Activation', act_type='relu') -Sigmoid = lambda : _Operatorized('Activation', act_type='sigmoid') -Tanh = lambda : _Operatorized('Activation', act_type='tanh') +# pylint: disable=locally-disabled, invalid-name +ReLU = lambda: _Operatorized('Activation', act_type='relu') +Sigmoid = lambda: _Operatorized('Activation', act_type='sigmoid') +Tanh = lambda: _Operatorized('Activation', act_type='tanh') -RNNReLU = lambda **kwargs : _Operatorized('RNN', mode='rnn_relu', **kwargs) -RNNTanh = lambda **kwargs : _Operatorized('RNN', mode='rnn_tanh', **kwargs) -GRU = lambda **kwargs : _Operatorized('RNN', mode='gru', **kwargs) -LSTM = lambda **kwargs : _Operatorized('RNN', mode='lstm', **kwargs) +# pylint: disable=locally-disabled, invalid-name +RNNReLU = lambda **kwargs: _Operatorized('RNN', mode='rnn_relu', **kwargs) +RNNTanh = lambda **kwargs: _Operatorized('RNN', mode='rnn_tanh', **kwargs) +GRU = lambda **kwargs: _Operatorized('RNN', mode='gru', **kwargs) +LSTM = lambda **kwargs: _Operatorized('RNN', mode='lstm', **kwargs) class Variable(_Layer): _module_name = 'variable' @@ -110,7 +118,7 @@ def forward(self): return self._get_param(self.variable) def param_shapes(self, *args): - return {self.variable : self._shape} + return {self.variable: self._shape} class Identity(_Layer): @@ -172,4 +180,4 @@ def param_shapes(self, xshape): indim = 1 for i in range(1, len(xshape)): indim *= xshape[i] - return {self.weight : (indim, self._num_hidden), self.bias : (self._num_hidden,)} + return {self.weight: (indim, self._num_hidden), self.bias: (self._num_hidden,)} From 3b6719caf567d4fc6a1ebcf17d4eb9805df1c049 Mon Sep 17 00:00:00 2001 From: Gai Yu Date: Sun, 14 May 2017 02:06:21 +0800 Subject: [PATCH 3/5] trailing whitespaces --- minpy/nn/model_builder.py | 32 ++++++++++++++++---------------- minpy/nn/modules.py | 10 +++++----- minpy/nn/utils.py | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/minpy/nn/model_builder.py b/minpy/nn/model_builder.py index 5b9abdf..01d0e9b 100644 --- a/minpy/nn/model_builder.py +++ b/minpy/nn/model_builder.py @@ -60,7 +60,7 @@ def forward(self, *args, **kwargs): def __call__(self, *args, **kwargs): raise NotImplementedError() - + def __setitem__(self, _): raise NotImplementedError() @@ -208,7 +208,7 @@ def inference(self): def _affiliate_to(self, model): for module in (self._left, self._right): module._affiliate_to(model) - + class Add(Binary): """ lhs_module + rhs_module @@ -251,7 +251,7 @@ def _register_configs(configs, to_register): # identifier is a param name and attr_value is a dict containing configs specific to this parameter # memorize and skip it _configs[identifier] = attr_value - else: + else: # a global attribute, modify this attribute for all parameters for config in configs.values(): # TODO the modification might be ineligible @@ -342,7 +342,7 @@ def __call__(self, *args, **kwargs): def _assign_param_names(self, *params): return tuple('%s_%s' % (self._name, param) for param in params) - + def _affiliate_to(self, model): model._update_configs.update(self._update_configs) self._model = model @@ -363,7 +363,7 @@ def _get_default_init_config(param_name): return {'init_rule': 'constant', 'value': 1} else: return {'init_rule': 'constant', 'value': 0} - + def _init_params(self, param_shapes, context): # param_shapes: dict for name, shape in param_shapes.items(): @@ -379,7 +379,7 @@ def _init_params(self, param_shapes, context): self._model.attach(name, self._model.params[name]) # register update_configs in model - + def _init_aux_params(self, aux_param_shapes, context): # aux_param_shapes: dict for name, shape in aux_param_shapes.items(): @@ -472,7 +472,7 @@ def aux_param_dict(self): """ Returns a dict containing the auxiliary parameters of a layer. """ return dict(zip(self._aux_param_names, self._get_aux_params(*self._aux_param_names))) - + # TODO privatize method def param_shapes(self, *args, **kwargs): """ Infer parameter shapes. @@ -543,7 +543,7 @@ def _register_module(self, module): self._modules.add(module) self._module_names.add(module.name) - + module._affiliate_to(self) def _register_iterable(self, iterable): @@ -565,20 +565,20 @@ def param_configs(self): def aux_param_configs(self): raise NotImplementedError() ''' - + def add_param(*args, **kwargs): raise NotImplementedError() - + def add_params(*args, **kwargs): raise NotImplementedError() - + def add_aux_param(*args, **kwargs): raise NotImplementedError() - + # requires implementation def forward(self): raise NotImplementedError() - + def forward_batch(self): # TODO eliminate? raise NotImplementedError() @@ -648,7 +648,7 @@ def training(self): """ for module in self._modules: module.training() - + def inference(self): """ Set model's state to inference. """ @@ -668,7 +668,7 @@ def __setattr__(self, attr, attr_value): def __init__(self, configs): object.__setattr__(self, '_configs', configs) - + def __getattr__(self, attr): attr_values = set(config[attr] for config in self._configs.values() if attr in config) assert len(attr_values) == 1, 'Inconsistent or non-existent attribute.' @@ -716,7 +716,7 @@ def __init__(self, model, **kwargs): # those attributes are local to self for attr, attr_value in kwargs.items(): setattr(self, attr, attr_value) - + def __call__(self, grad_dict): """ Only update parameters corresponding to gradients contained in grad_dict. User could update parameters selectively by manipulating grad_dict. diff --git a/minpy/nn/modules.py b/minpy/nn/modules.py index 5e6eb8b..81cf688 100644 --- a/minpy/nn/modules.py +++ b/minpy/nn/modules.py @@ -19,7 +19,7 @@ def __init__(self, operator_name, **kwargs): variables = kwargs.pop('variables', None) self._variables = ('data',) if variables is None else variables - + self._kwargs = dict(kwargs) kwargs.update({v: _symbol.Variable(v) for v in self._variables}) @@ -39,17 +39,17 @@ def __init__(self, operator_name, **kwargs): aux_params = tuple(map(eliminate_prefix, aux_params)) super(_Operatorized, self).__init__(params, aux_params, name) - + def forward(self, *args, **kwargs): is_array = lambda array: isinstance(array, _nd.NDArray) - kwarg_dict = dict(zip(self._variables, filter(is_array, args))) + kwarg_dict = dict(zip(self._variables, filter(is_array, args))) for key, value in kwargs.items(): if is_array(value): kwarg_dict[key] = value - + kwarg_dict.update(dict(zip(self._module_param_names, self._get_params(*self._param_names)))) kwarg_dict.update(dict(zip(self._module_aux_param_names, self._get_aux_params(*self._aux_param_names)))) - + kwarg_dict.update(self._kwargs) return self._operator(**kwarg_dict) diff --git a/minpy/nn/utils.py b/minpy/nn/utils.py index 87afe53..2adeb16 100644 --- a/minpy/nn/utils.py +++ b/minpy/nn/utils.py @@ -12,7 +12,7 @@ def wrapped(*args, **kwargs): return f(*args, **kwargs) return wrapped - + @_np_decorator def cross_entropy(p, labels): @@ -61,5 +61,5 @@ def copy_arrays(arrays, context=None): if isinstance(arrays, dict): return dict(zip(arrays.keys(), map(copy, arrays.values()))) - else: + else: return map(copy, arrays) From 31bc098919edc03355c10f9456e83aae4d1f4218 Mon Sep 17 00:00:00 2001 From: Gai Yu Date: Sun, 14 May 2017 17:06:08 +0800 Subject: [PATCH 4/5] fix travis errors --- minpy/nn/model_builder.py | 96 +++++++++++++++++++++++++++------------ minpy/nn/modules.py | 5 +- minpy/nn/utils.py | 10 +++- 3 files changed, 80 insertions(+), 31 deletions(-) diff --git a/minpy/nn/model_builder.py b/minpy/nn/model_builder.py index 01d0e9b..0b6f8b9 100644 --- a/minpy/nn/model_builder.py +++ b/minpy/nn/model_builder.py @@ -1,11 +1,16 @@ +# pylint: disable-all +# TODO fix pylint warnings """ Infrastructures for building models. """ +from collections import Iterable as _Iterable from functools import reduce as _reduce import operator as _operator +# pylint: disable=locally-disabled, no-name-in-module +# pylint: disable=locally-disabled, import-error import mxnet.minpy import mxnet.ndarray as _nd import mxnet.contrib.autograd as _autograd @@ -30,7 +35,6 @@ def _is_array(array): return isinstance(array, _nd.NDArray) -from collections import Iterable as _Iterable def _is_iterable(instance): return isinstance(instance, _Iterable) @@ -44,7 +48,8 @@ class Module(object): _module_name = None def __init__(self, name): super(Module, self).__init__() - if self._module_name is None: raise NotImplementedError() + if self._module_name is None: + raise NotImplementedError() self._name = _module_prefix(self._module_name) if name is None else name @property @@ -61,12 +66,6 @@ def forward(self, *args, **kwargs): def __call__(self, *args, **kwargs): raise NotImplementedError() - def __setitem__(self, _): - raise NotImplementedError() - - def __setitem__(self, _): - raise NotImplementedError() - def __repr__(self): return str(self) @@ -98,21 +97,38 @@ class Container(Module): """ # TODO provide an interface for indexing contained modules def __init__(self, name): + # pylint: disable=locally-disabled, useless-super-delegation super(Container, self).__init__(name) def __call__(self, *args, **kwargs): return self.forward(*args, **kwargs) - def param_shapes(self, input_shape): + def param_shapes(self, _): + # pylint: disable=locally-disabled, no-self-use """ Infer the shapes of parameters given input shape. """ return {} - def aux_param_shapes(self, input_shape): + def aux_param_shapes(self, _): + # pylint: disable=locally-disabled, no-self-use """ Infer the shapes of auxiliary parameters given input shape. """ return {} + def _affiliate_to(self, model): + ''' + responsible for + (1). refering to model.params and model.aux_params + (2). update model._update_configs + (3). if isinstance(self, Container): call _affiliate_to of contained modules + ''' + raise NotImplementedError() + + def forward(self, *args, **kwargs): + """ A virtual method. + """ + raise NotImplementedError() + class Sequential(Container): """ A sequentially-arranged group of modules. @@ -143,12 +159,16 @@ def __repr__(self): def __str__(self): return str(self._modules) - def forward(self, *args): - # It is recommended that all forward functions, especially those in Sequential, only receive positional arguments. + def forward(self, *args, **kwargs): + """ + It is recommended that all forward functions, especially those in Sequential, + only receive positional arguments. + """ to_tuple = lambda results: results if isinstance(results, tuple) else (results,) forward_module = lambda args, module: to_tuple(module(*args)) result = _reduce(forward_module, self._modules, args) - if len(result) == 1: result, = result + if len(result) == 1: + result, = result return result def training(self): @@ -164,10 +184,13 @@ def inference(self): module.inference() def _affiliate_to(self, model): + # pylint: disable=locally-disabled, protected-access for module in self._modules: module._affiliate_to(model) +# pylint: disable=locally-disabled, abstract-method +# pylint: disable=locally-disabled, useless-super-delegation class Parallel(Container): """ An abstract class for implementing containers of parallel modules. """ @@ -239,16 +262,21 @@ def __init__(self, left, right, name=None): def _register_configs(configs, to_register): ''' param dict configs: pair param_name(str): param_configs(dict) - param to_register: pair param_name(str): param_configs(dict) or attr(str): attr_value(object) + param to_register: pair param_name(str): + param_configs(dict) or attr(str): attr_value(object) ''' _configs = {} # register global attributes for identifier, attr_value in to_register.items(): - assert isinstance(identifier, str), KeyError() # global attribute must be str (e.g. 'learning_rate') + # global attribute must be str (e.g. 'learning_rate') + assert isinstance(identifier, str), KeyError() if identifier in configs: - # identifier is a param name and attr_value is a dict containing configs specific to this parameter + ''' + identifier is a param name and + attr_value is a dict containing configs specific to this parameter + ''' # memorize and skip it _configs[identifier] = attr_value else: @@ -273,16 +301,22 @@ def __init__(self, params=None, aux_params=None, name=None): super(Layer, self).__init__(name) - if params is None: params = tuple() - self._module_param_names = params # local param names - self._param_names = self._assign_param_names(*params) # global param names (identifiable in model) + if params is None: + params = tuple() + # local param names + self._module_param_names = params + # global param names (identifiable in model) + self._param_names = self._assign_param_names(*params) for param, param_name in zip(params, self._param_names): setattr(self, param, param_name) # TODO Is it necessary to bind one layer to multiple models? - if aux_params is None: aux_params = tuple() - self._module_aux_param_names = aux_params # local aux param names - self._aux_param_names = self._assign_param_names(*aux_params) # global aux param names (identifiable in model) + if aux_params is None: + aux_params = tuple() + # local aux param names + self._module_aux_param_names = aux_params + # global aux param names (identifiable in model) + self._aux_param_names = self._assign_param_names(*aux_params) for aux_param, aux_param_name in zip(aux_params, self._aux_param_names): setattr(self, '_%s' % aux_param, aux_param_name) @@ -410,7 +444,8 @@ def _parse_param_configs(self, configs): 1. pair param_name(str): configs(dict), which are parameter-specific configs 2. pair attr_name(str): attr_value(object), which are global configs ''' - if configs is None: return {} + if configs is None: + return {} _configs = {key: value for key, value in configs.items()} @@ -418,7 +453,8 @@ def _parse_param_configs(self, configs): if isinstance(identifier, tuple): # configs applied to a group of parameters config = _configs.pop(identifier) # expand group configs to parameter-specific configs - for param_name in identifier: _configs[param_name] = config + for param_name in identifier: + _configs[param_name] = config # convert local (module) name to global name for module_param_name, param_name in \ @@ -550,7 +586,8 @@ def _register_iterable(self, iterable): for element in iterable: if isinstance(element, Module): self._register_module(element) - elif isinstance(element, str): continue + elif isinstance(element, str): + continue elif _is_iterable(element): self._register_iterable(element) @@ -590,11 +627,14 @@ def decorator(f): def wrapped(self, *args, **kwargs): is_train = kwargs.pop('is_train', False) - if is_train: self.training() - else: self.inference() + if is_train: + self.training() + else: + self.inference() with _autograd.TrainingStateScope(is_train): - if self._jit: mxnet.minpy.enable_jit() + if self._jit: + mxnet.minpy.enable_jit() results = f(self, *args, **kwargs) diff --git a/minpy/nn/modules.py b/minpy/nn/modules.py index 81cf688..96059bc 100644 --- a/minpy/nn/modules.py +++ b/minpy/nn/modules.py @@ -1,3 +1,5 @@ +# pylint: disable-all +# TODO fix pylint warnings """ Modules """ @@ -45,7 +47,8 @@ def forward(self, *args, **kwargs): kwarg_dict = dict(zip(self._variables, filter(is_array, args))) for key, value in kwargs.items(): - if is_array(value): kwarg_dict[key] = value + if is_array(value): + kwarg_dict[key] = value kwarg_dict.update(dict(zip(self._module_param_names, self._get_params(*self._param_names)))) kwarg_dict.update(dict(zip(self._module_aux_param_names, self._get_aux_params(*self._aux_param_names)))) diff --git a/minpy/nn/utils.py b/minpy/nn/utils.py index 2adeb16..1646410 100644 --- a/minpy/nn/utils.py +++ b/minpy/nn/utils.py @@ -1,3 +1,7 @@ +# pylint: disable-all +# TODO fix pylint warnings + + import numpy as _np import mxnet as _mx import mxnet.ndarray as _nd @@ -39,7 +43,8 @@ def count_params(params): Returns: - n: total number of parameters """ - if isinstance(params, dict): params = params.values() + if isinstance(params, dict): + params = params.values() assert all(isinstance(param, _nd.NDArray) for param in params), \ 'All parameters must be mxnet.ndarray.NDArray.' @@ -55,7 +60,8 @@ def copy_arrays(arrays, context=None): Returns: - arrays: a list, tuple or dict of duplicated arrays located in context """ - if context is None: context = _mx.cpu() + if context is None: + context = _mx.cpu() copy = lambda array : array.as_in_context(context) From 6d8ec861ed233cfe43f29882e967b387a3b45847 Mon Sep 17 00:00:00 2001 From: Gai Yu Date: Sun, 14 May 2017 17:26:26 +0800 Subject: [PATCH 5/5] fix pylint errors --- minpy/nn/init.py | 1 + minpy/nn/optim.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/minpy/nn/init.py b/minpy/nn/init.py index d00d5e0..dee17b3 100644 --- a/minpy/nn/init.py +++ b/minpy/nn/init.py @@ -68,6 +68,7 @@ def gaussian(shape, config): Initialized array of size `shape` """ + # pylint: disable=locally-disabled, invalid-name mu = config.setdefault('mu', 0.0) stdvar = config.setdefault('stdvar', 0.001) return _nd.random_normal(loc=mu, scale=stdvar, shape=shape) diff --git a/minpy/nn/optim.py b/minpy/nn/optim.py index bbf2cf2..5e308c6 100644 --- a/minpy/nn/optim.py +++ b/minpy/nn/optim.py @@ -38,7 +38,7 @@ def sgd(w, dw, config=None): config format: - lr: Scalar learning rate. - - wd: + - wd: - rescale_grad: - clip_gradient: """ @@ -57,7 +57,7 @@ def sgd_momentum(w, dw, config=None): - lr: Scalar learning rate. - momentum: Scalar between 0 and 1 giving the momentum value. Setting momentum = 0 reduces to sgd. - - wd: + - wd: - rescale_grad: - clip_gradient: """ @@ -79,7 +79,7 @@ def rmsprop(w, dw, config=None): - gamma1: Scalar between 0 and 1 giving the decay rate for the squared gradient cache. - epsilon: Small scalar used for smoothing to avoid dividing by zero. - - wd: + - wd: - rescale_grad: - clip_gradient: - clip_weights: