import copy import inspect from collections import OrderedDict try: from torch.nn import Sequential as tSeq from federatedml.nn.backend.torch import optim, init, nn from federatedml.nn.backend.torch import operation from federatedml.nn.backend.torch.base import Sequential, get_torch_instance from federatedml.nn.backend.torch.cust import CustModel, CustLoss from federatedml.nn.backend.torch.interactive import InteractiveLayer except ImportError: pass def recover_layer_from_dict(nn_define, nn_dict): init_param_dict = copy.deepcopy(nn_define) if 'layer' in nn_define: class_name = nn_define['layer'] init_param_dict.pop('layer') elif 'op' in nn_define: class_name = nn_define['op'] init_param_dict.pop('op') else: raise ValueError( 'no layer or operation info found in nn define, please check your layer config and make' 'sure they are correct for pytorch backend') if 'initializer' in init_param_dict: init_param_dict.pop('initializer') # find corresponding class if class_name == CustModel.__name__: nn_layer_class = CustModel elif class_name == InteractiveLayer.__name__: nn_layer_class = InteractiveLayer else: nn_layer_class = nn_dict[class_name] # create layer or Module if nn_layer_class == CustModel: # converto to pytorch model layer: CustModel = CustModel(module_name=init_param_dict['module_name'], class_name=init_param_dict['class_name'], **init_param_dict['param']) layer = layer.get_pytorch_model() elif nn_layer_class == InteractiveLayer: layer: InteractiveLayer = InteractiveLayer(**init_param_dict) else: layer = get_torch_instance(nn_layer_class, init_param_dict) # initialize if there are configs if 'initializer' in nn_define: if 'weight' in nn_define['initializer']: init_para = nn_define['initializer']['weight'] init_func = init.str_fate_torch_init_func_map[init_para['init_func']] init_func(layer, **init_para['param']) if 'bias' in nn_define['initializer']: init_para = nn_define['initializer']['bias'] init_func = init.str_fate_torch_init_func_map[init_para['init_func']] init_func(layer, init='bias', **init_para['param']) return layer, class_name def recover_sequential_from_dict(nn_define): nn_define_dict = nn_define nn_dict = dict(inspect.getmembers(nn)) op_dict = dict(inspect.getmembers(operation)) nn_dict.update(op_dict) class_name_list = [] try: # submitted model have int prefixes, they make sure that layers are in # order add_dict = OrderedDict() keys = list(nn_define_dict.keys()) keys = sorted(keys, key=lambda x: int(x.split('-')[0])) for k in keys: layer, class_name = recover_layer_from_dict(nn_define_dict[k], nn_dict) add_dict[k] = layer class_name_list.append(class_name) except BaseException: add_dict = OrderedDict() for k, v in nn_define_dict.items(): layer, class_name = recover_layer_from_dict(v, nn_dict) add_dict[k] = layer class_name_list.append(class_name) if len(class_name_list) == 1 and class_name_list[0] == CustModel.__name__: # If there are only a CustModel, return the model only return list(add_dict.values())[0] else: return tSeq(add_dict) def recover_optimizer_from_dict(define_dict): opt_dict = dict(inspect.getmembers(optim)) from federatedml.util import LOGGER LOGGER.debug('define dict is {}'.format(define_dict)) if 'optimizer' not in define_dict: raise ValueError('please specify optimizer type in the json config') opt_class = opt_dict[define_dict['optimizer']] param_dict = copy.deepcopy(define_dict) if 'optimizer' in param_dict: param_dict.pop('optimizer') if 'config_type' in param_dict: param_dict.pop('config_type') return opt_class(**param_dict) def recover_loss_fn_from_dict(define_dict): loss_fn_dict = dict(inspect.getmembers(nn)) if 'loss_fn' not in define_dict: raise ValueError('please specify loss function in the json config') param_dict = copy.deepcopy(define_dict) param_dict.pop('loss_fn') if define_dict['loss_fn'] == CustLoss.__name__: return CustLoss(loss_module_name=param_dict['loss_module_name'], class_name=param_dict['class_name'], **param_dict['param']).get_pytorch_model() else: return loss_fn_dict[define_dict['loss_fn']](**param_dict) if __name__ == '__main__': pass