def __setattr__(self, name, value): """Protect keys, items, and values.""" if not "_att_dict" in self.__dict__: object.__setattr__(self, name, value) else: try: fun = self._att_dict[name] except KeyError: OrderedDict.__setattr__(self, name, value) else: fun(value)
def __setattr__(self, item, value): if not self.__dict__.has_key('_NamedDict__initialised'): return OrderedDict.__setattr__(self, item, value) elif self.__dict__.has_key(item): OrderedDict.__setattr__(self, item, value) else: self.__setitem__(item, value)
def __setattr__(self, key, value): """ An override of the standard __setattr_ in Python. Assumptions: This one tries to treat k as an object, if that fails it treats it as a key. Source: N/A Inputs: k [key] v [value] Outputs: N/A Properties Used: N/A """ # Setting a new item creates a new link which goes at the end of the linked # list, and the inherited dictionary is updated with the new key/value pair. if not hasattr(self,key) and not hasattr(self.__class__,key): #if not self.has_key(key) and not hasattr(self.__class__,key): root = dict.__getitem__(self,'_root') last = root[0] map = dict.__getitem__(self,'_map') last[1] = root[0] = map[key] = [last, root, key] OrderedDict.__setattr__(self,key, value)
def __setattr__(self, key, value): """ An override of the standard __setattr_ in Python. Assumptions: This one tries to treat k as an object, if that fails it treats it as a key. Source: N/A Inputs: key [key] value [value] Outputs: N/A Properties Used: N/A """ # Setting a new item creates a new link which goes at the end of the linked # list, and the inherited dictionary is updated with the new key/value pair. if not hasattr(self,key) and not hasattr(self.__class__,key): #if not self.has_key(key) and not hasattr(self.__class__,key): root = dict.__getitem__(self,'_root') last = root[0] map = dict.__getitem__(self,'_map') last[1] = root[0] = map[key] = [last, root, key] OrderedDict.__setattr__(self,key, value)
def __setitem__(self, key, value): keylike = 1 if key in self else 0 if len(self) - keylike >= self._cap: last = self.popitem(last=False) print("remove item is ", last) if keylike: del self[key] OrderedDict.__setattr__(self, key, value)
def __new__(cls, *args, **kwargs): attrs = getattr(OrderedDict(), '__dict__', {}) attrs.update(cls.__dict__) obj = type(cls.__name__, cls.__bases__, attrs) self = OrderedDict.__new__(obj, *args, **kwargs) OrderedDict.__setattr__(self, '__dict__', self) OrderedDict.__init__(self, *args, **kwargs) return self
def __setattr__(self, attr, value): """Implement basic functionality: Keys can be referenced as in dictionary methods, or as an attribute. """ #print '>> in __setattr__', attr, value # preserve OrderedDict implementation attributes if attr.startswith('_Ordered'): OrderedDict.__setattr__(self, attr, value) else: self[attr] = value
def __setattr__(self, key, value): # Setting a new item creates a new link which goes at the end of the linked # list, and the inherited dictionary is updated with the new key/value pair. if not hasattr(self, key) and not hasattr(self.__class__, key): #if not self.has_key(key) and not hasattr(self.__class__,key): root = dict.__getitem__(self, '_root') last = root[0] map = dict.__getitem__(self, '_map') last[1] = root[0] = map[key] = [last, root, key] OrderedDict.__setattr__(self, key, value)
def __setattr__(self, name, value): """Protect keys, items, and values.""" if not '_att_dict' in self.__dict__: object.__setattr__(self, name, value) else: try: fun = self._att_dict[name] except KeyError: OrderedDict.__setattr__(self, name, value) else: fun(value)
def __setitem__(self, key, value): containsKey = 1 if key in self else 0 if len(self) - containsKey >= self._capacity: last = self.popitem(last = False) print 'remove:',last if containsKey: del self[key] print 'set:',(key,value) else: print 'add:',(key,value) OrderedDict.__setattr__(self,key,value)
def __setitem__(self, key, value, *args, **kwargs): """ This method sets a key and sibling attribute with given value. :param key.: Key. ( Object ) :param value.: Value. ( Object ) :param \*args: Arguments. ( \* ) :param \*\*kwargs: Key / Value pairs. ( Key / Value pairs ) """ OrderedDict.__setitem__(self, key, value, *args, **kwargs) OrderedDict.__setattr__(self, key, value)
def __setattr__(self, attribute, value): """ This method sets both key and sibling attribute with given value. :param attribute.: Attribute. ( Object ) :param value.: Value. ( Object ) """ if hasattr(self, "_OrderedDict__root") and hasattr(self, "_OrderedDict__map"): if self._OrderedDict__root: OrderedDict.__setitem__(self, attribute, value) OrderedDict.__setattr__(self, attribute, value)
def __setattr__(self, name, value): if name in [ "_OrderedDict__root", "_OrderedDict__map", "_OrderedDict__hardroot" ]: return OrderedDict.__setattr__(self, name, value) self[name] = value
def __setattr__(self, key, val): if key in AttrDict.__reserved_names__: if key not in AttrDict.__pure_names__: return OrderedDict.__setattr__(self, key, val) else: raise AttributeError( "reserved name can only be set via dictionary interface". format(key)) else: self[key] = val
def __setattr__(self, key, val): if key in Dict.__reserved_names__: # Either let OrderedDict do its work, or disallow if key not in Dict.__pure_names__: return _dict.__setattr__(self, key, val) else: raise AttributeError('Reserved name, this key can only ' + 'be set via ``d[%r] = X``' % key) else: # if isinstance(val, dict): val = Dict(val) -> no, makes a copy! self[key] = val
def __setattr__(self, key, val): if key in Dict.__reserved_names__: # Either let OrderedDict do its work, or disallow if key not in Dict.__pure_names__: return _dict.__setattr__(self, key, val) else: raise AttributeError("Reserved name, this key can only " + "be set via ``d[%r] = X``" % key) else: # if isinstance(val, dict): val = Dict(val) -> no, makes a copy! self[key] = val
class Dictionary(): def __init__(self): self.__dictionary = OrderedDict() def clear(self): self.__dictionary.clear() def get_json(self): return json.dumps(self.__dictionary) def set_item(self, key, value): self.__dictionary.__setitem__(key, value) return self def values(self): return [value for value in self.__dictionary.values().__iter__()] def items(self): return self.__dictionary.items() def copy(self): self.__dictionary def constain(self, key): return key in self.get_list_of_key() def get(self, key): return self.__dictionary.get(key) def clear(self, key, default): self.__dictionary.pop(key, default) def format(self, *args, **kwargs): return self.__dictionary.__format__(*args, **kwargs) def ne(self, *args, **kwargs): return self.__dictionary.__ne__(*args, **kwargs) def repr(self, *args, **kwargs): return self.__dictionary.__repr__(*args, **kwargs) def ge(self, *args, **kwargs): return self.dictionary__ge__(*args, **kwargs) def __sizeof__(self): return self.__dictionary.__sizeof__() def setattr(self, *args, **kwargs): return self.__dictionary.__setattr__(*args, **kwargs) def dir(self): return self.__dictionary.__dir__() def le(self, *args, **kwargs): return self.__dictionary.__le__(*args, **kwargs) def delattr(self, *args, **kwargs): return self.__dictionary.__delattr__(*args, **kwargs) def hash(self, *args, **kwargs): return self.__dictionary.__hash__(*args, **kwargs) def gt(self, *args, **kwargs): return self.__dictionary.__gt__(*args, **kwargs) def eq(self, *args, **kwargs): return self.__dictionary.__eq__(*args, **kwargs) def getattribute(self, *args, **kwargs): return self.__dictionary.__getattribute__(*args, **kwargs) def str(self, *args, **kwargs): return self.__dictionary.__str__(*args, **kwargs) def reduce(self, *args, **kwargs): return self.__dictionary.__reduce__(*args, **kwargs) def reduce_ex(self, *args, **kwargs): return self.__dictionary.__reduce_ex__(*args, **kwargs) def lt(self, *args, **kwargs): return self.__dictionary.__lt__(*args, **kwargs) def keys(self): return self.get_list_of_key() def get_list_of_key(self): return [key for key in self.__dictionary.keys().__iter__()]
def __setattr__(self, name, value): if not name.startswith('_OrderedDict__'): self[name] = value else: OrderedDict.__setattr__(self, name, value)
def __setattr__(self, key, value): if not key.startswith('_OrderedDict__'): self[key] = value else: OrderedDict.__setattr__(self, key, value)
def __setattr__(self, name, value): """Set the given value into our dict""" if name in self.__reserved__: return OrderedDictPy3.__setattr__(self, name, value) self[name] = value
def load_model_ensemble_and_task( filenames, arg_overrides: Optional[Dict[str, Any]] = None, task=None, strict=True, suffix="", num_shards=1, state=None, ): assert state is None or len(filenames) == 1 from fairseq import tasks assert not ( strict and num_shards > 1 ), "Cannot load state dict with strict=True and checkpoint shards > 1" ensemble = [] cfg = None for filename in filenames: orig_filename = filename model_shard_state = {"shard_weights": [], "shard_metadata": []} assert num_shards > 0 st = time.time() for shard_idx in range(num_shards): filename = get_maybe_sharded_checkpoint_filename( orig_filename, suffix, shard_idx, num_shards ) if not PathManager.exists(filename): raise IOError("Model file not found: {}".format(filename)) if state is None: state = load_checkpoint_to_cpu(filename, arg_overrides) if "args" in state and state["args"] is not None: cfg = convert_namespace_to_omegaconf(state["args"]) elif "cfg" in state and state["cfg"] is not None: cfg = state["cfg"] else: raise RuntimeError( f"Neither args nor cfg exist in state keys = {state.keys()}" ) if task is None: task = tasks.setup_task(cfg.task) if "task_state" in state: task.load_state_dict(state["task_state"]) if "fsdp_metadata" in state and num_shards > 1: model_shard_state["shard_weights"].append(state["model"]) model_shard_state["shard_metadata"].append(state["fsdp_metadata"]) # check FSDP import before the code goes too far if not has_FSDP: raise ImportError( "Cannot find FullyShardedDataParallel. " "Please install fairscale with: pip install fairscale" ) if shard_idx == num_shards - 1: consolidated_model_state = FSDP.consolidate_shard_weights( shard_weights=model_shard_state["shard_weights"], shard_metadata=model_shard_state["shard_metadata"], ) model = task.build_model(cfg.model) model.load_state_dict( consolidated_model_state, strict=strict, model_cfg=cfg.model ) else: # model parallel checkpoint or unsharded checkpoint model = task.build_model(cfg.model) new_state_model = state["model"] '''=====The following if-else statement is a work-around ===== # the current metadata loading/saving of pytorch. # In Pytorch, if state["model"]["_metadata"] exists as dictionary, then model.load_state_dict(strict=True) # will throw an error for unexpected "_metadata" key. To avoid this error, we need the state_dict to be # in orderedDict format, which has new_state_model._metadata attribute but not as key. # TODO yuansg@ This issue should be fixed in pytorch ideally. ''' if new_state_model.get("_metadata", None) is not None: new_metadata = new_state_model.get("_metadata", None) del state["model"]["_metadata"] else: new_metadata = None # Construct state dict content. contents = OrderedDict(new_state_model) # We explicitly set _metadata for the state models. The _metadata is implicitly stored for pytorch models. # calling state["model"] in fairseq will not invoke metadata storage. if new_metadata is None: logger.warning("===Jit: state[\"model\"] does not contain key \"_metadata\"=====") logger.warning("===Jit: we will be filling in with current model's meta-data instead.") # For models trained before this diff, we do the following to be backward compatible. contents.__setattr__("_metadata", model.state_dict()._metadata) else: contents.__setattr__("_metadata", new_metadata) '''====End of work-around logic=====''' model.load_state_dict( contents, strict=strict, model_cfg=cfg.model ) # reset state so it gets loaded for the next model in ensemble state = None if shard_idx % 10 == 0 and shard_idx > 0: elapsed = time.time() - st logger.info( f"Loaded {shard_idx} shards in {elapsed:.2f}s, {elapsed / (shard_idx+1):.2f}s/shard" ) # build model for ensemble ensemble.append(model) return ensemble, cfg, task
def __setattr__(self, key, value): if key in self: self[key].value = value else: OrderedDict.__setattr__(self, key, value)
def __setattr__(self, name, value): if not hasattr(self, '_init'): return OrderedDict.__setattr__(self, name, value) return OrderedDict.__setitem__(self, name, value)
def main(): args = get_arguments() if args.solver_param != None: print(args.solver_param) args.solver_param = ast.literal_eval(args.solver_param) if args.config_param != None: print(args.config_param) args.config_param = ast.literal_eval(args.config_param) #Start populating config_param config_param = OrderedDict() #Names config_param.config_name = 'image-objdet' config_param.model_name = "jacintonet11" config_param.dataset = "nodataset" config_param.pretrain_model = None ### Modify the following parameters accordingly ### # The directory which contains the caffe code. # We assume you are running the script at the CAFFE_ROOT. config_param.caffe_root = os.environ[ 'CAFFE_ROOT'] if 'CAFFE_ROOT' in os.environ else None if config_param.caffe_root == None: config_param.caffe_root = os.environ[ 'CAFFE_HOME'] if 'CAFFE_HOME' in os.environ else None if config_param.caffe_root != None: config_param.caffe_root = config_param.caffe_root + '/build/tools/caffe.bin' config_param.caffe_cmd = 'train' print("caffe_root = : ", config_param.caffe_root) # Set true if you want to start training right after generating all files. config_param.run_soon = False # Set true if you want to load from most recently saved snapshot. # Otherwise, we will load from the pretrain_model defined below. config_param.resume_training = True # If true, Remove old model files. config_param.remove_old_models = False config_param.display_sparsity = False # Specify the batch sampler. config_param.resize_width = 512 config_param.resize_height = 512 config_param.crop_width = config_param.resize_width config_param.crop_height = config_param.resize_height #feature stride can be 8, 16, 32. 16 provides the best radeoff config_param.feature_stride = 16 config_param.num_feature = 512 #number of feature channels config_param.threads = 4 # The database file for training data. Created by data/VOC0712/create_data.sh config_param.train_data = "/data/hdd/datasets/object-detect/other/pascal-voc/VOCdevkit/VOC0712/lmdb/VOC0712_trainval_lmdb" # The database file for testing data. Created by data/VOC0712/create_data.sh config_param.test_data = "/data/hdd/datasets/object-detect/other/pascal-voc/VOCdevkit/VOC0712/lmdb/VOC0712_test_lmdb" config_param.stride_list = None config_param.dilation_list = None config_param.mean_value = 128 #used in a bias layer in the net. # If true, use batch norm for all newly added layers. # Currently only the non batch norm version has been tested. config_param.use_batchnorm = False config_param.use_scale = False config_param.lr_mult = 1 # Which layers to freeze (no backward) during training. config_param.freeze_layers = [] # Defining which GPUs to use. config_param.gpus = "0,1" #gpus = "0" config_param.batch_size = 32 config_param.accum_batch_size = 32 # Evaluate on whole test set. config_param.num_test_image = 4952 config_param.test_batch_size = 8 # Stores the test image names and sizes. Created by data/VOC0712/create_list.sh config_param.name_size_file = "/user/a0393608/files/work/code/vision/github/weiliu89_ssd/caffe/data/VOC0712/test_name_size.txt" # Stores LabelMapItem. config_param.label_map_file = "/user/a0393608/files/work/code/vision/github/weiliu89_ssd/caffe/data/VOC0712/labelmap_voc.prototxt" # minimum dimension of input image config_param.log_space_steps = False #True config_param.min_ratio = 10 #5 #20 # in percent % config_param.max_ratio = 90 # in percent % config_param.num_classes = 21 # MultiBoxLoss parameters initialization. config_param.share_location = True config_param.background_label_id = 0 config_param.use_difficult_gt = True config_param.ignore_difficult_gt = False config_param.evaluate_difficult_gt = False config_param.normalization_mode = P.Loss.VALID config_param.code_type = P.PriorBox.CENTER_SIZE config_param.ignore_cross_boundary_bbox = False config_param.mining_type = P.MultiBoxLoss.MAX_NEGATIVE config_param.neg_pos_ratio = 3. config_param.loc_weight = (config_param.neg_pos_ratio + 1.) / 4. config_param.min_dim = -1 config_param.aspect_ratios_type = 0 #need it for COCO which may have gray scale image config_param.force_color = 0 #Update from params given from outside #if args.config_param != None: # config_param.update(args.config_param) if args.config_param != None: for k in args.config_param.keys(): config_param.__setattr__(k, args.config_param[k]) config_param.__setitem__(k, args.config_param[k]) if config_param.min_dim == -1: config_param.min_dim = int( (config_param.crop_width + config_param.crop_height) / 2) if config_param.ds_fac == 16: config_param.stride_list = [2, 2, 2, 2, 1] config_param.dilation_list = [1, 1, 1, 1, 2] elif config_param.ds_fac == 32: config_param.stride_list = [2, 2, 2, 2, 2] config_param.dilation_list = [1, 1, 1, 1, 1] print("config_param.ds_fac :", config_param.ds_fac) print("config_param.stride_list :", config_param.stride_list) resize = "{}x{}".format(config_param.resize_width, config_param.resize_height) config_param.batch_sampler = [ { 'sampler': {}, 'max_trials': 1, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'min_jaccard_overlap': 0.1, }, 'max_trials': 50, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'min_jaccard_overlap': 0.3, }, 'max_trials': 50, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'min_jaccard_overlap': 0.5, }, 'max_trials': 50, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'min_jaccard_overlap': 0.7, }, 'max_trials': 50, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'min_jaccard_overlap': 0.9, }, 'max_trials': 50, 'max_sample': 1, }, { 'sampler': { 'min_scale': 0.3, 'max_scale': 1.0, 'min_aspect_ratio': 0.5, 'max_aspect_ratio': 2.0, }, 'sample_constraint': { 'max_jaccard_overlap': 1.0, }, 'max_trials': 50, 'max_sample': 1, }, ] config_param.train_transform_param = { 'mirror': True, 'mean_value': [0, 0, 0], 'force_color': config_param.force_color, 'resize_param': { 'prob': 1, 'resize_mode': P.Resize.WARP, 'height': config_param.resize_height, 'width': config_param.resize_width, 'interp_mode': [ P.Resize.LINEAR, P.Resize.AREA, P.Resize.NEAREST, P.Resize.CUBIC, P.Resize.LANCZOS4, ], }, 'distort_param': { 'brightness_prob': 0.5, 'brightness_delta': 32, 'contrast_prob': 0.5, 'contrast_lower': 0.5, 'contrast_upper': 1.5, 'hue_prob': 0.5, 'hue_delta': 18, 'saturation_prob': 0.5, 'saturation_lower': 0.5, 'saturation_upper': 1.5, 'random_order_prob': 0.0, }, 'expand_param': { 'prob': 0.5, 'max_expand_ratio': 4.0, }, 'emit_constraint': { 'emit_type': caffe_pb2.EmitConstraint.CENTER, }, 'crop_h': config_param.crop_height, 'crop_w': config_param.crop_width } config_param.test_transform_param = { 'mean_value': [0, 0, 0], 'force_color': config_param.force_color, 'resize_param': { 'prob': 1, 'resize_mode': P.Resize.WARP, 'height': config_param.resize_height, 'width': config_param.resize_width, 'interp_mode': [P.Resize.LINEAR], }, 'crop_h': config_param.crop_height, 'crop_w': config_param.crop_width } # Modify the job name if you want. #print("config_name is {}".format(config_param.config_name)) config_param.base_name = config_param.config_name config_param.job_name = config_param.base_name # Base dir config_param.base_dir = config_param.job_name # Directory which stores the model .prototxt file. config_param.save_dir = config_param.job_name # Directory which stores the snapshot of models. config_param.snapshot_dir = config_param.job_name # Directory which stores the job script and log file. config_param.job_dir = config_param.job_name # Directory which stores the detection results. config_param.output_result_dir = "" #"{}/results".format(config_param.job_name) # model definition files. config_param.train_net_file = "{}/train.prototxt".format( config_param.save_dir) config_param.test_net_file = "{}/test.prototxt".format( config_param.save_dir) config_param.deploy_net_file = "{}/deploy.prototxt".format( config_param.save_dir) config_param.solver_file = "{}/solver.prototxt".format( config_param.save_dir) # snapshot prefix. config_param.snapshot_prefix = "{}/{}_{}".format(config_param.snapshot_dir, config_param.dataset, config_param.model_name) # job script path. job_file_base_name = 'run' config_param.job_file_base = "{}/{}".format(config_param.job_dir, job_file_base_name) config_param.log_file = "{}.log".format(config_param.job_file_base) config_param.job_file = "{}.sh".format(config_param.job_file_base) # MultiBoxLoss parameters. multibox_loss_param = { 'loc_loss_type': P.MultiBoxLoss.SMOOTH_L1, 'conf_loss_type': P.MultiBoxLoss.SOFTMAX, 'loc_weight': config_param.loc_weight, 'num_classes': config_param.num_classes, 'share_location': config_param.share_location, 'match_type': P.MultiBoxLoss.PER_PREDICTION, 'overlap_threshold': 0.5, 'use_prior_for_matching': True, 'background_label_id': config_param.background_label_id, 'use_difficult_gt': config_param.use_difficult_gt, 'ignore_difficult_gt': config_param.ignore_difficult_gt, 'mining_type': config_param.mining_type, 'neg_pos_ratio': config_param.neg_pos_ratio, 'neg_overlap': 0.5, 'code_type': config_param.code_type, 'ignore_cross_boundary_bbox': config_param.ignore_cross_boundary_bbox, } loss_param = { 'normalization': config_param.normalization_mode, } if config_param.feature_stride != 16: ValueError("config_param.feature_stride {} is incorrect".format( config_param.feature_stride)) if (config_param.model_name == 'jdetnet21v2'): config_param.steps = [16, 32, 64, 128] config_param.mbox_source_layers = ['ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', \ 'ctx_output4/relu'] elif (config_param.model_name == 'jdetnet21v2-s8'): config_param.steps = [8, 16, 32, 64, 128, 128] config_param.mbox_source_layers = ['ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', \ 'ctx_output4/relu', 'ctx_output5/relu', 'ctx_output6/relu'] elif (config_param.model_name == 'jdetnet21v2-fpn'): config_param.steps = [16, 16, 32, 64, 128, 128] config_param.mbox_source_layers = ['ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', \ 'ctx_output4/relu', 'ctx_output5/relu', 'ctx_output6/relu'] if (config_param.model_name == 'ssdJacintoNetV2'): config_param.steps = [] #if config_param.resize_width == config_param.resize_height: #config_param.steps = [8, 16, 32, 64, 128, 256, 512] #config_param.mbox_source_layers = ['ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', \ # 'ctx_output4/relu', 'ctx_output5/relu', 'ctx_output6/relu'] if config_param.ds_type == 'DFLT': config_param.mbox_source_layers = [ 'res3a_branch2b/relu', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2', 'conv10_2' ] else: if config_param.stride_list[4] == 1: config_param.mbox_source_layers = [ 'ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', 'ctx_output4/relu', 'ctx_output5/relu', 'ctx_output6/relu', 'ctx_output7/relu' ] else: config_param.mbox_source_layers = [ 'ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', 'ctx_output4/relu', 'ctx_output5/relu', 'ctx_output6/relu' ] if config_param.base_nw_3_head: config_param.mbox_source_layers.append( 'ctx_output{}/relu'.format( len(config_param.mbox_source_layers) + 1)) elif config_param.model_name == 'vgg16': # conv4_3 ==> 38 x 38 # fc7 ==> 19 x 19 # conv6_2 ==> 10 x 10 # conv7_2 ==> 5 x 5 # conv8_2 ==> 3 x 3 # conv9_2 ==> 1 x 1 config_param.mbox_source_layers = [ 'conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2' ] config_param.steps = [8, 16, 32, 64, 100, 300] elif 'mobiledetnet' in config_param.model_name: config_param.mbox_source_layers = ['ctx_output1/relu', 'ctx_output2/relu', 'ctx_output3/relu', \ 'ctx_output4/relu', 'ctx_output5/relu'] config_param.steps = [16, 32, 64, 128, 128] else: ValueError("Invalid model name") # parameters for generating priors. config_param.num_steps = len(config_param.mbox_source_layers) config_param.step = int( math.floor((config_param.max_ratio - config_param.min_ratio) / config_param.num_steps)) config_param.min_sizes = [] config_param.max_sizes = [] print("min_dim = {}".format(config_param.min_dim)) min_dim_to_use = config_param.min_ratio * config_param.min_dim / 100 max_dim_to_use = config_param.max_ratio * config_param.min_dim / 100 if config_param.log_space_steps == 1: #log min_max_sizes = np.logspace(np.log2(min_dim_to_use), np.log2(max_dim_to_use), num=config_param.num_steps + 1, base=2) config_param.min_sizes = list(min_max_sizes[0:config_param.num_steps]) config_param.max_sizes = list(min_max_sizes[1:config_param.num_steps + 1]) elif config_param.log_space_steps == 0: #linear min_max_sizes = np.linspace(min_dim_to_use, max_dim_to_use, num=config_param.num_steps + 1) config_param.min_sizes = list(min_max_sizes[0:config_param.num_steps]) config_param.max_sizes = list(min_max_sizes[1:config_param.num_steps + 1]) else: #like original SSD config_param.min_sizes, config_param.max_sizes = set_min_max_sizes( config_param) print("minsizes = {}".format(config_param.min_sizes)) print("maxsizes = {}".format(config_param.max_sizes)) if config_param.aspect_ratios_type == 0: config_param.aspect_ratios = [[2]] * config_param.num_steps else: #like original SSD config_param.aspect_ratios = [[2, 3]] * config_param.num_steps config_param.aspect_ratios[0] = [2] config_param.aspect_ratios[-1] = [2] config_param.aspect_ratios[-2] = [2] print("ARs:", config_param.aspect_ratios) # L2 normalize conv4_3. config_param.normalizations = [ -1 ] * config_param.num_steps #[20, -1, -1, -1, -1, -1] # variance used to encode/decode prior bboxes. if config_param.code_type == P.PriorBox.CENTER_SIZE: config_param.prior_variance = [0.1, 0.1, 0.2, 0.2] else: config_param.prior_variance = [0.1] if config_param.chop_num_heads > 0: print("Chopping heads") del config_param.min_sizes[-config_param.chop_num_heads:] del config_param.max_sizes[-config_param.chop_num_heads:] del config_param.aspect_ratios[-config_param.chop_num_heads:] del config_param.normalizations[-config_param.chop_num_heads:] del config_param.mbox_source_layers[-config_param.chop_num_heads:] print("minsizes = {}".format(config_param.min_sizes)) print("maxsizes = {}".format(config_param.max_sizes)) print("aspect_ratios = {}".format(config_param.aspect_ratios)) print(config_param.mbox_source_layers) config_param.flip = True config_param.clip = False # Solver parameters. # Defining which GPUs to use. config_param.gpulist = config_param.gpus.split(",") config_param.num_gpus = len(config_param.gpulist) # Divide the mini-batch to different GPUs. iter_size = int( math.ceil(config_param.accum_batch_size / config_param.batch_size)) solver_mode = P.Solver.CPU device_id = 0 batch_size_per_device = config_param.batch_size if config_param.num_gpus > 0: batch_size_per_device = int( math.ceil(float(config_param.batch_size) / config_param.num_gpus)) iter_size = int( math.ceil( float(config_param.accum_batch_size) / (batch_size_per_device * config_param.num_gpus))) solver_mode = P.Solver.GPU device_id = int(config_param.gpulist[0]) # Ideally test_batch_size should be divisible by num_test_image, # otherwise mAP will be slightly off the true value. test_iter = int( math.ceil( float(config_param.num_test_image) / config_param.test_batch_size)) solver_param = { # Train parameters 'type': "SGD", 'base_lr': 1e-3, 'max_iter': 32000, 'weight_decay': 0.0005, 'lr_policy': "multistep", 'power': 1.0, 'stepvalue': [24000, 30000, 32000], 'gamma': 0.1, 'momentum': 0.9, 'iter_size': iter_size, 'snapshot': 2000, 'display': 100, 'average_loss': 10, 'type': "SGD", 'solver_mode': solver_mode, 'device_id': device_id, 'debug_info': False, 'snapshot_after_train': True, # Test parameters 'test_iter': [test_iter], 'test_interval': 2000, 'eval_type': "detection", 'ap_version': "11point", 'test_initialization': True, 'random_seed': 33, 'show_per_class_result': True, } #if args.solver_param != None: # solver_param.update(args.solver_param) if args.solver_param != None: for k in args.solver_param.keys(): solver_param.__setitem__(k, args.solver_param[k]) #solver_param.__setattr__(k,args.solver_param[k]) # parameters for generating detection output. det_out_param = { 'num_classes': config_param.num_classes, 'share_location': config_param.share_location, 'background_label_id': config_param.background_label_id, 'nms_param': { 'nms_threshold': 0.45, 'top_k': 400 }, 'save_output_param': { 'output_directory': config_param.output_result_dir, 'output_name_prefix': "comp4_det_test_", 'output_format': "VOC", 'label_map_file': config_param.label_map_file, 'name_size_file': config_param.name_size_file, 'num_test_image': config_param.num_test_image, }, 'keep_top_k': 200, 'confidence_threshold': 0.01, 'code_type': config_param.code_type, } # parameters for evaluating detection results. det_eval_param = { 'num_classes': config_param.num_classes, 'background_label_id': config_param.background_label_id, 'overlap_threshold': 0.5, 'evaluate_difficult_gt': config_param.evaluate_difficult_gt, 'name_size_file': config_param.name_size_file, } ### Hopefully you don't need to change the following ### # Check file. check_if_exist(config_param.train_data) check_if_exist(config_param.test_data) check_if_exist(config_param.label_map_file) if config_param.pretrain_model != None: check_if_exist(config_param.pretrain_model) make_if_not_exist(config_param.base_dir) make_if_not_exist(config_param.save_dir) make_if_not_exist(config_param.job_dir) make_if_not_exist(config_param.snapshot_dir) # Create train net. net = caffe.NetSpec() net.data, net.label = CreateAnnotatedDataLayer( config_param.train_data, batch_size=config_param.batch_size, train=True, output_label=True, label_map_file=config_param.label_map_file, transform_param=config_param.train_transform_param, batch_sampler=config_param.batch_sampler, threads=config_param.threads) out_layer = 'data' bias_kwargs = { #fixed value with lr_mult=0 'param': [dict(lr_mult=0, decay_mult=0)], 'filler': dict(type='constant', value=(-config_param.mean_value)), } net['data/bias'] = L.Bias(net[out_layer], in_place=False, **bias_kwargs) out_layer = 'data/bias' def core_network(net, from_layer): if config_param.model_name == 'jdetnet21v2': out_layer = models.jacintonet_v2.jdetnet21(net, from_layer=from_layer,\ num_output=config_param.num_feature,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers, output_stride=config_param.feature_stride) elif config_param.model_name == 'jdetnet21v2-s8': out_layer = models.jacintonet_v2.jdetnet21_s8(net, from_layer=from_layer,\ num_output=config_param.num_feature,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers, output_stride=config_param.feature_stride) elif config_param.model_name == 'jdetnet21v2-fpn': out_layer = models.jacintonet_v2.jdetnet21_fpn(net, from_layer=from_layer,\ num_output=config_param.num_feature,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers, output_stride=config_param.feature_stride) elif config_param.model_name == 'ssdJacintoNetV2': out_layer = models.jacintonet_v2.ssdJacintoNetV2(net, from_layer=from_layer,\ num_output=config_param.num_feature,stride_list=config_param.stride_list,\ dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers, output_stride=config_param.feature_stride,\ ds_type=config_param.ds_type, use_batchnorm_mbox=config_param.use_batchnorm_mbox,fully_conv_at_end=config_param.fully_conv_at_end, reg_head_at_ds8=config_param.reg_head_at_ds8, concat_reg_head=config_param.concat_reg_head, base_nw_3_head=config_param.base_nw_3_head, first_hd_same_op_ch=config_param.first_hd_same_op_ch, num_intermediate=config_param.num_intermediate, rhead_name_non_linear=config_param.rhead_name_non_linear, chop_num_heads=config_param.chop_num_heads) elif 'mobiledetnet' in config_param.model_name: #out_layer = models.mobilenet.mobiledetnet(net, from_layer=from_layer,\ # num_output=config_param.num_feature,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ # freeze_layers=config_param.freeze_layers, output_stride=config_param.feature_stride, wide_factor=wide_factor) wide_factor = float(config_param.model_name.split('-')[1]) out_layer = models.mobilenet.mobiledetnet(net, from_layer=from_layer, wide_factor=wide_factor) else: ValueError("Invalid model name") return net, out_layer net, out_layer = core_network(net, out_layer) mbox_layers = CreateMultiBoxHead( net, data_layer='data', from_layers=config_param.mbox_source_layers, use_batchnorm=config_param.use_batchnorm, use_scale=config_param.use_scale, min_sizes=config_param.min_sizes, max_sizes=config_param.max_sizes, aspect_ratios=config_param.aspect_ratios, steps=config_param.steps, normalizations=config_param.normalizations, num_classes=config_param.num_classes, share_location=config_param.share_location, flip=config_param.flip, clip=config_param.clip, prior_variance=config_param.prior_variance, kernel_size=config_param.ker_mbox_loc_conf, pad=1, lr_mult=config_param.lr_mult) # Create the MultiBoxLossLayer. name = "mbox_loss" mbox_layers.append(net.label) net[name] = L.MultiBoxLoss( *mbox_layers, multibox_loss_param=multibox_loss_param, loss_param=loss_param, include=dict(phase=caffe_pb2.Phase.Value('TRAIN')), propagate_down=[True, True, False, False]) with open(config_param.train_net_file, 'w') as f: print(config_param.train_net_file) print('name: "{}"'.format(config_param.model_name), file=f) print(net.to_proto(), file=f) #shutil.copy(train_net_file, job_dir) # Create test net. net = caffe.NetSpec() net.data, net.label = CreateAnnotatedDataLayer( config_param.test_data, batch_size=config_param.test_batch_size, train=False, output_label=True, label_map_file=config_param.label_map_file, transform_param=config_param.test_transform_param, threads=config_param.threads) out_layer = 'data' bias_kwargs = { #fixed value with lr_mult=0 'param': [dict(lr_mult=0, decay_mult=0)], 'filler': dict(type='constant', value=(-config_param.mean_value)), } net['data/bias'] = L.Bias(net[out_layer], in_place=False, **bias_kwargs) out_layer = 'data/bias' net, out_layer = core_network(net, out_layer) mbox_layers = CreateMultiBoxHead( net, data_layer='data', from_layers=config_param.mbox_source_layers, use_batchnorm=config_param.use_batchnorm, use_scale=config_param.use_scale, min_sizes=config_param.min_sizes, max_sizes=config_param.max_sizes, aspect_ratios=config_param.aspect_ratios, steps=config_param.steps, normalizations=config_param.normalizations, num_classes=config_param.num_classes, share_location=config_param.share_location, flip=config_param.flip, clip=config_param.clip, prior_variance=config_param.prior_variance, kernel_size=config_param.ker_mbox_loc_conf, pad=1, lr_mult=config_param.lr_mult) conf_name = "mbox_conf" if multibox_loss_param["conf_loss_type"] == P.MultiBoxLoss.SOFTMAX: reshape_name = "{}_reshape".format(conf_name) net[reshape_name] = L.Reshape( net[conf_name], shape=dict(dim=[0, -1, config_param.num_classes])) softmax_name = "{}_softmax".format(conf_name) net[softmax_name] = L.Softmax(net[reshape_name], axis=2) flatten_name = "{}_flatten".format(conf_name) net[flatten_name] = L.Flatten(net[softmax_name], axis=1) mbox_layers[1] = net[flatten_name] elif multibox_loss_param["conf_loss_type"] == P.MultiBoxLoss.LOGISTIC: sigmoid_name = "{}_sigmoid".format(conf_name) net[sigmoid_name] = L.Sigmoid(net[conf_name]) mbox_layers[1] = net[sigmoid_name] net.detection_out = L.DetectionOutput( *mbox_layers, detection_output_param=det_out_param, include=dict(phase=caffe_pb2.Phase.Value('TEST'))) net.detection_eval = L.DetectionEvaluate( net.detection_out, net.label, detection_evaluate_param=det_eval_param, include=dict(phase=caffe_pb2.Phase.Value('TEST'))) with open(config_param.test_net_file, 'w') as f: print('name: "{}_test"'.format(config_param.model_name), file=f) print(net.to_proto(verbose=False), file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(config_param.test_net_file, config_param.job_dir) # Create deploy net. # Remove the first and last layer from test net. deploy_net = net with open(config_param.deploy_net_file, 'w') as f: net_param = deploy_net.to_proto() # Remove the first (AnnotatedData) and last (DetectionEvaluate) layer from test net. del net_param.layer[0] del net_param.layer[-1] net_param.name = '{}_deploy'.format(config_param.model_name) net_param.input.extend(['data']) net_param.input_shape.extend([ caffe_pb2.BlobShape(dim=[ 1, 3, config_param.resize_height, config_param.resize_width ]) ]) print(net_param, file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(config_param.deploy_net_file, config_param.job_dir) # Create solver. solver = caffe_pb2.SolverParameter( train_net=config_param.train_net_file, test_net=[config_param.test_net_file], snapshot_prefix=config_param.snapshot_prefix, **solver_param) with open(config_param.solver_file, 'w') as f: print(solver, file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(solver_file, job_dir) max_iter = 0 # Find most recent snapshot. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format(config_param.model_name))[1]) if iter > max_iter: max_iter = iter train_src_param = None if config_param.pretrain_model != None: train_src_param = '--weights="{}" \\\n'.format( config_param.pretrain_model) if config_param.resume_training: if max_iter > 0: train_src_param = '--snapshot="{}_iter_{}.solverstate" \\\n'.format( config_param.snapshot_prefix, max_iter) if config_param.remove_old_models: # Remove any snapshots smaller than max_iter. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format( config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) if file.endswith(".caffemodel"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format( config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) # Create job file. with open(config_param.job_file, 'w') as f: #f.write('cd {}\n'.format(config_param.caffe_root)) f.write('{} {} \\\n'.format(config_param.caffe_root, config_param.caffe_cmd)) if (config_param.caffe_cmd == 'test' or config_param.caffe_cmd == 'test_detection'): f.write('--model="{}" \\\n'.format(config_param.test_net_file)) f.write('--iterations="{}" \\\n'.format( solver_param['test_iter'][0])) if config_param.display_sparsity: f.write('--display_sparsity=1 \\\n') else: f.write('--solver="{}" \\\n'.format(config_param.solver_file)) if train_src_param != None: f.write(train_src_param) if solver_param['solver_mode'] == P.Solver.GPU: f.write('--gpu "{}" 2>&1 | tee {}\n'.format( config_param.gpus, config_param.log_file)) else: f.write('2>&1 | tee {}\n'.format(config_param.log_file)) # Copy the python script to job_dir. py_file = os.path.abspath(__file__) shutil.copy(py_file, config_param.job_dir) #copy some other utils scripts shutil.copy(os.getcwd() + '/train_image_object_detection.sh', config_param.job_dir) shutil.copy(os.getcwd() + '/models/jacintonet_v2.py', config_param.job_dir) # Run the job. os.chmod(config_param.job_file, stat.S_IRWXU) if config_param.run_soon: subprocess.call(config_param.job_file, shell=True)
def main(): assert 'CAFFE_ROOT' in os.environ, 'CAFFE_ROOT shell variable must be set to your caffe-jacinto folder path. eg: export CAFFE_ROOT=/user/tomato/work/caffe-jacinto' args = get_arguments() if args.solver_param != None: args.solver_param = ast.literal_eval(args.solver_param) if args.config_param != None: args.config_param = ast.literal_eval(args.config_param) #Start populating config_param config_param = OrderedDict() #Names config_param.config_name = 'image_classification' config_param.model_name = "jacintonet11" config_param.dataset = "nodataset" config_param.pretrain_model = None ### Modify the following parameters accordingly ### # The directory which contains the caffe code. # We assume you are running the script at the CAFFE_ROOT. config_param.caffe_root = os.environ[ 'CAFFE_ROOT'] if 'CAFFE_ROOT' in os.environ else None if config_param.caffe_root == None: config_param.caffe_root = os.environ[ 'CAFFE_HOME'] if 'CAFFE_HOME' in os.environ else None if config_param.caffe_root != None: config_param.caffe_root = config_param.caffe_root + '/build/tools/caffe.bin' config_param.caffe_cmd = 'train' # Set true if you want to start training right after generating all files. config_param.run_soon = False # Set true if you want to load from most recently saved snapshot. # Otherwise, we will load from the pretrain_model defined below. config_param.resume_training = True # If true, Remove old model files. config_param.remove_old_models = False config_param.display_sparsity = False config_param.crop_size = 512 config_param.image_width = 640 config_param.image_height = 640 # Select betwen list based ImageData or lmdb config_param.use_image_list = True config_param.stride_list = [2, 2, 2, 2, 1] config_param.dilation_list = [1, 1, 1, 1, 2] #mean_value is used in a bias layer in the net. config_param.mean_value = 128 # Setup Default values # If true, use batch norm for all newly added layers. # Currently only the non batch norm version has been tested. config_param.use_batchnorm = True # Stores LabelMapItem. config_param.label_map_file = "" # Defining which GPUs to use. config_param.gpus = "0,1" #gpus = "0" config_param.num_output = 20 config_param.batch_size = 16 config_param.accum_batch_size = 16 # Which layers to freeze (no backward) during training. config_param.freeze_layers = [] # Evaluate on whole test set. config_param.num_test_image = 500 config_param.test_batch_size = 4 config_param.test_batch_size_in_proto = config_param.test_batch_size #more threads doesn't seem to help speed up - but you can try increasing this, at the cost of system becoming more slugginsh to respond if you are doing something else parallely. config_param.threads = 1 #4 #Update from params given from outside #if args.config_param != None: # config_param.update(args.config_param) if args.config_param != None: for k in args.config_param.keys(): config_param.__setattr__(k, args.config_param[k]) config_param.__setitem__(k, args.config_param[k]) ''' config_param.train_data = "data/train-image-list.txt" if config_param.use_image_list else 'data/train-image-lmdb' config_param.train_label = "data/train-label-list.txt" if config_param.use_image_list else 'data/train-label-lmdb' config_param.test_data = "data/val-image-list.txt" if config_param.use_image_list else 'data/val-image-lmdb' config_param.test_label = "data/val-label-list.txt" if config_param.use_image_list else 'data/val-label-lmdb' ''' config_param.train_data1 = "data/train-image-list1.txt" if config_param.use_image_list else 'data/train-image1-lmdb' config_param.train_data2 = "data/train-image-list2.txt" if config_param.use_image_list else 'data/train-image2-lmdb' config_param.train_label = "data/train-label-list.txt" if config_param.use_image_list else 'data/train-label-lmdb' config_param.test_data1 = "data/val-image-list1.txt" if config_param.use_image_list else 'data/val-image1-lmdb' config_param.test_data2 = "data/val-image-list2.txt" if config_param.use_image_list else 'data/val-image2-lmdb' config_param.test_label = "data/val-label-list.txt" if config_param.use_image_list else 'data/val-label-lmdb' # Modify the job name if you want. config_param.base_name = config_param.config_name config_param.job_name = config_param.base_name # Base dir config_param.base_dir = config_param.job_name # Directory which stores the model .prototxt file. config_param.save_dir = config_param.job_name # Directory which stores the snapshot of models. config_param.snapshot_dir = config_param.job_name # Directory which stores the job script and log file. config_param.job_dir = config_param.job_name # Directory which stores the detection results. config_param.output_result_dir = "training/{}".format( config_param.job_name) # model definition files. config_param.train_net_file = "{}/train.prototxt".format( config_param.save_dir) config_param.test_net_file = "{}/test.prototxt".format( config_param.save_dir) config_param.deploy_net_file = "{}/deploy.prototxt".format( config_param.save_dir) config_param.solver_file = "{}/solver.prototxt".format( config_param.save_dir) # snapshot prefix. config_param.snapshot_prefix = "{}/{}_{}".format(config_param.snapshot_dir, config_param.dataset, config_param.model_name) # job script path. job_file_base_name = 'run' config_param.job_file_base = "{}/{}".format(config_param.job_dir, job_file_base_name) config_param.log_file = "{}.log".format(config_param.job_file_base) config_param.job_file = "{}.sh".format(config_param.job_file_base) # Stores the test image names and sizes. Created by data/VOC0712/create_list.sh config_param.name_size_file = "" # Solver parameters. config_param.gpulist = config_param.gpus.split(",") config_param.num_gpus = 0 if ( config_param.gpulist == '' or len(config_param.gpulist) > 0 and config_param.gpulist[0] == '') else len(config_param.gpulist) print("num_gpus:", config_param.num_gpus, " gpulist:", config_param.gpulist) # Divide the mini-batch to different GPUs. # In BVLC caffe, this has to be divided by num GPUs - not required in NVIDIA/caffe config_param.train_batch_size_in_proto = config_param.batch_size #Solver params solver_param = { # Train parameters 'type': 'Adam', 'base_lr': 1e-4, 'max_iter': 32000, 'weight_decay': 0.0001, 'lr_policy': 'multistep', 'stepvalue': [24000], 'power': 1, 'gamma': 0.1, 'momentum': 0.9, 'iter_size': int(math.ceil(config_param.accum_batch_size / config_param.batch_size)), 'snapshot': 10000, 'display': 100, #'average_loss': 10, 'solver_mode': P.Solver.GPU if (config_param.num_gpus > 0) else P.Solver.CPU, 'device_id': int(config_param.gpulist[0]) if (config_param.num_gpus > 0) else 0, 'debug_info': False, 'snapshot_after_train': True, # Test parameters 'test_iter': [ int( math.ceil(config_param.num_test_image / config_param.test_batch_size)) ], 'test_interval': 2000, 'test_initialization': False, 'random_seed': 33, } #Update from params given from outside #if args.solver_param != None: # solver_param.update(args.solver_param) if args.solver_param != None: for k in args.solver_param.keys(): solver_param.__setitem__(k, args.solver_param[k]) #solver_param.__setattr__(k,args.solver_param[k]) config_param.train_transform_param = { 'mirror': True, 'mean_value': [0], #specify 1 or 3 values 'crop_size': config_param.crop_size, 'random_seed': 1 } config_param.test_transform_param = { 'mirror': False, 'mean_value': [0], #specify 1 or 3 values 'crop_size': config_param.crop_size, 'random_seed': 1 } ### Hopefully you don't need to change the following ### # Check file. check_if_exist(config_param.train_data1) check_if_exist(config_param.train_data2) check_if_exist(config_param.test_data1) check_if_exist(config_param.test_data2) check_if_exist(config_param.label_map_file) if config_param.pretrain_model != None: check_if_exist(config_param.pretrain_model) make_if_not_exist(config_param.base_dir) make_if_not_exist(config_param.save_dir) make_if_not_exist(config_param.job_dir) make_if_not_exist(config_param.snapshot_dir) #---------------------- #Net definition def define_net(phase): # Create train net. net = caffe.NetSpec() #if you want the train and test in same proto, #get the proto string for the data layer in train phase seperately and return it train_proto_str = [] if phase == 'train': if config_param.use_image_list: data_kwargs = { 'name': 'data', 'ntop': 2, 'image_data_param': { 'source': config_param.train_data, 'batch_size': config_param.train_batch_size_in_proto, 'shuffle': False } } net['data'], data_extra = L.ImageData( transform_param=config_param.train_transform_param, **data_kwargs) label_kwargs = { 'name': 'label3', 'ntop': 2, 'image_data_param': { 'source': config_param.train_label, 'batch_size': config_param.train_batch_size_in_proto, 'shuffle': False } } net['label3'], label_extra = L.ImageData( transform_param=config_param.train_transform_param, **label_kwargs) slice_kwargs = { 'name': 'label_slice', 'ntop': 3, 'slice_param': { 'axis': 1 } } slice_tops = L.Slice(net['label3'], **slice_kwargs) net['label'] = slice_tops[0] net['silence'] = L.Silence(data_extra, label_extra, slice_tops[1], slice_tops[2], ntop=0) else: data_kwargs = {'name': 'data1', 'ntop':1, 'data_param': { 'source': config_param.train_data1, 'batch_size': config_param.train_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['data1'] = L.Data( transform_param=config_param.train_transform_param, **data_kwargs) data_kwargs = {'name': 'data2', 'ntop':1, 'data_param': { 'source': config_param.train_data2, 'batch_size': config_param.train_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['data2'] = L.Data( transform_param=config_param.train_transform_param, **data_kwargs) net['data'] = L.Concat( net['data1'], net['data2'], axis=1) #concat the two images along channels label_kwargs = {'name': 'label', 'ntop':1, 'data_param': { 'source': config_param.train_label, 'batch_size': config_param.train_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['label'] = L.Data( transform_param=config_param.train_transform_param, **label_kwargs) out_layer = 'data' elif phase == 'test': if config_param.use_image_list: data_kwargs = { 'name': 'data', 'ntop': 2, 'image_data_param': { 'source': config_param.test_data, 'batch_size': config_param.test_batch_size_in_proto, 'shuffle': False } } net['data'], data_extra = L.ImageData( transform_param=config_param.test_transform_param, **data_kwargs) label_kwargs = { 'name': 'label3', 'ntop': 2, 'image_data_param': { 'source': config_param.test_label, 'batch_size': config_param.test_batch_size_in_proto, 'shuffle': False } } net['label3'], label_extra = L.ImageData( transform_param=config_param.test_transform_param, **label_kwargs) slice_kwargs = { 'name': 'label_slice', 'ntop': 3, 'slice_param': { 'axis': 1 } } slice_tops = L.Slice(net['label3'], **slice_kwargs) net['label'] = slice_tops[0] net['silence'] = L.Silence(data_extra, label_extra, slice_tops[1], slice_tops[2], ntop=0) else: data_kwargs = {'name': 'data1', 'ntop':1, 'data_param': { 'source': config_param.test_data1, 'batch_size': config_param.test_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['data1'] = L.Data( transform_param=config_param.test_transform_param, **data_kwargs) data_kwargs = {'name': 'data2', 'ntop':1, 'data_param': { 'source': config_param.test_data2, 'batch_size': config_param.test_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['data2'] = L.Data( transform_param=config_param.test_transform_param, **data_kwargs) net['data'] = L.Concat( net['data1'], net['data2'], axis=1) #concat the two images along channels label_kwargs = {'name': 'label', 'ntop':1, 'data_param': { 'source': config_param.test_label, 'batch_size': config_param.test_batch_size_in_proto, \ 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'shuffle': config_param.shuffle } } net['label'] = L.Data( transform_param=config_param.test_transform_param, **label_kwargs) out_layer = 'data' elif phase == 'deploy': net['data'] = L.Input(shape=[ dict(dim=[ 1, 6, config_param.image_height, config_param.image_width ]) ]) out_layer = 'data' #print('height:'+ str(config_param.image_height)) #print('width:' + str(config_param.image_width)) bias_kwargs = { #fixed value with lr_mult=0 'param': [dict(lr_mult=0, decay_mult=0)], 'filler': dict(type='constant', value=(-config_param.mean_value)), } net['data/bias'] = L.Bias(net[out_layer], in_place=False, **bias_kwargs) out_layer = 'data/bias' if config_param.model_name == 'jsegnet21v2': out_layer = models.jacintonet_v2.jsegnet21(net, from_layer=out_layer,\ num_output=config_param.num_output,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers) else: ValueError("Invalid model name") if phase == 'train' or phase == 'test': loss_param = { 'ignore_label': 255, 'normalization': caffe_pb2.LossParameter.NormalizationMode.Value('VALID') } net["loss"] = L.SoftmaxWithLoss(net[out_layer], net['label'], loss_param=loss_param, propagate_down=[True, False]) accuracy_param = {'ignore_label': 255} net["accuracy/top1"] = L.Accuracy( net[out_layer], net['label'], accuracy_param=accuracy_param, include=dict(phase=caffe_pb2.Phase.Value('TEST'))) accuracy_param_top5 = {'ignore_label': 255, 'top_k': 5} net["accuracy/top5"] = L.Accuracy( net[out_layer], net['label'], accuracy_param=accuracy_param_top5, include=dict(phase=caffe_pb2.Phase.Value('TEST'))) elif phase == 'deploy': argmax_param = {'axis': 1} net['argMaxOut'] = L.ArgMax(net[out_layer], argmax_param=argmax_param) return net #---------------------- net = define_net(phase='train') with open(config_param.train_net_file, 'w') as f: print('name: "{}_train"'.format(config_param.model_name), file=f) #if you want the train and test in same proto, #get the proto string for the data layer, train phase. #print(train_proto_str, file=f) print(net.to_proto(verbose=False), file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(config_param.train_net_file, config_param.job_dir) # Create test net. net = define_net(phase='test') with open(config_param.test_net_file, 'w') as f: print('name: "{}_test"'.format(config_param.model_name), file=f) print(net.to_proto(verbose=False), file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(config_param.test_net_file, config_param.job_dir) # Create deploy net. deploy_net = define_net(phase='deploy') with open(config_param.deploy_net_file, 'w') as f: net_param = deploy_net.to_proto(verbose=False) # Remove the few layers first del net_param.layer[0] #del net_param.layer[-1] #del net_param.layer[-1] #del net_param.layer[-1] net_param.name = '{}_deploy'.format(config_param.model_name) net_param.input.extend(['data']) net_param.input_shape.extend([ caffe_pb2.BlobShape(dim=[ 1, 6, config_param.image_height, config_param.image_width ]) ]) print(net_param, file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(config_param.deploy_net_file, config_param.job_dir) # Create solver. solver = caffe_pb2.SolverParameter( train_net=config_param.train_net_file, test_net=[config_param.test_net_file], snapshot_prefix=config_param.snapshot_prefix, **solver_param) with open(config_param.solver_file, 'w') as f: print(solver, file=f) if config_param.save_dir != config_param.job_dir: shutil.copy(solver_file, job_dir) max_iter = 0 # Find most recent snapshot. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format(config_param.model_name))[1]) if iter > max_iter: max_iter = iter train_src_param = None if config_param.pretrain_model != None: train_src_param = '--weights="{}" \\\n'.format( config_param.pretrain_model) if config_param.resume_training: if max_iter > 0: train_src_param = '--snapshot="{}_iter_{}.solverstate" \\\n'.format( config_param.snapshot_prefix, max_iter) if config_param.remove_old_models: # Remove any snapshots smaller than max_iter. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format( config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) if file.endswith(".caffemodel"): basename = os.path.splitext(file)[0] iter = int( basename.split("{}_iter_".format( config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) # Create job file. with open(config_param.job_file, 'w') as f: #f.write('cd {}\n'.format(config_param.caffe_root)) f.write('{} {} \\\n'.format(config_param.caffe_root, config_param.caffe_cmd)) if (config_param.caffe_cmd == 'test'): f.write('--model="{}" \\\n'.format(config_param.test_net_file)) f.write('--iterations="{}" \\\n'.format( solver_param['test_iter'][0])) if config_param.display_sparsity: f.write('--display_sparsity=1 \\\n') else: f.write('--solver="{}" \\\n'.format(config_param.solver_file)) if train_src_param != None: f.write(train_src_param) if solver_param['solver_mode'] == P.Solver.GPU: f.write('--gpu "{}" 2>&1 | tee {}\n'.format( config_param.gpus, config_param.log_file)) else: f.write('2>&1 | tee {}\n'.format(config_param.log_file)) # Copy the python script to job_dir. py_file = os.path.abspath(__file__) shutil.copy(py_file, config_param.job_dir) # Run the job. os.chmod(config_param.job_file, stat.S_IRWXU) if config_param.run_soon: subprocess.call(config_param.job_file, shell=True)
def main(): args = get_arguments() if args.solver_param != None: args.solver_param = ast.literal_eval(args.solver_param) if args.config_param != None: args.config_param = ast.literal_eval(args.config_param) #Start populating config_param config_param = OrderedDict() #Names config_param.config_name = 'image_classification' config_param.model_name = "jacintonet11" config_param.dataset = "nodataset" config_param.pretrain_model = None ### Modify the following parameters accordingly ### # The directory which contains the caffe code. # We assume you are running the script at the CAFFE_ROOT. config_param.caffe_root = os.environ['CAFFE_ROOT'] if 'CAFFE_ROOT' in os.environ else None if config_param.caffe_root == None: config_param.caffe_root = os.environ['CAFFE_HOME'] if 'CAFFE_HOME' in os.environ else None if config_param.caffe_root != None: config_param.caffe_root = config_param.caffe_root + '/build/tools/caffe.bin' config_param.caffe_cmd = 'train' # Set true if you want to start training right after generating all files. config_param.run_soon = False # Set true if you want to load from most recently saved snapshot. # Otherwise, we will load from the pretrain_model defined below. config_param.resume_training = True # If true, Remove old model files. config_param.remove_old_models = False config_param.display_sparsity = False config_param.crop_size = 224 config_param.image_width = 224 config_param.image_height = 224 config_param.train_data = "/data/hdd/datasets/object-detect/other/ilsvrc/2012/lmdb/size256/ilsvrc12_train_lmdb" config_param.test_data = "/data/hdd/datasets/object-detect/other/ilsvrc/2012/lmdb/size256/ilsvrc12_val_lmdb" config_param.stride_list = [2,2,2,2,2] config_param.dilation_list = [1,1,1,1,1] config_param.mean_value = 128 #used in a bias layer in the net. # Setup Default values # If true, use batch norm for all newly added layers. # Currently only the non batch norm version has been tested. config_param.use_batchnorm = True # Stores LabelMapItem. config_param.label_map_file = "" # Defining which GPUs to use. config_param.gpus = "0,1" #gpus = "0" config_param.num_output = 1000 config_param.batch_size = 128 config_param.accum_batch_size = 256 # Which layers to freeze (no backward) during training. config_param.freeze_layers = [] # Evaluate on whole test set. config_param.num_test_image = 50000 config_param.test_batch_size = 50 config_param.test_batch_size_in_proto = config_param.test_batch_size crop_size_to_use = args.config_param['crop_size'] if 'crop_size' in args.config_param else config_param.crop_size config_param.train_transform_param = { 'mirror': True, 'mean_value': [0, 0, 0], 'crop_size': crop_size_to_use } config_param.test_transform_param = { 'mirror': False, 'mean_value': [0, 0, 0], 'crop_size': crop_size_to_use } #Update from params given from outside #if args.config_param != None: # config_param.update(args.config_param) if args.config_param != None: for k in args.config_param.keys(): config_param.__setattr__(k,args.config_param[k]) config_param.__setitem__(k,args.config_param[k]) # Modify the job name if you want. config_param.base_name = config_param.config_name config_param.job_name = config_param.base_name # Base dir config_param.base_dir = config_param.job_name # Directory which stores the model .prototxt file. config_param.save_dir = config_param.job_name # Directory which stores the snapshot of models. config_param.snapshot_dir = config_param.job_name # Directory which stores the job script and log file. config_param.job_dir = config_param.job_name # Directory which stores the detection results. config_param.output_result_dir = "training/{}".format(config_param.job_name) # model definition files. config_param.train_net_file = "{}/train.prototxt".format(config_param.save_dir) config_param.test_net_file = "{}/test.prototxt".format(config_param.save_dir) config_param.deploy_net_file = "{}/deploy.prototxt".format(config_param.save_dir) config_param.solver_file = "{}/solver.prototxt".format(config_param.save_dir) # snapshot prefix. config_param.snapshot_prefix = "{}/{}_{}".format(config_param.snapshot_dir, config_param.dataset, config_param.model_name) # job script path. job_file_base_name = 'run' config_param.job_file_base = "{}/{}".format(config_param.job_dir, job_file_base_name) config_param.log_file = "{}.log".format(config_param.job_file_base) config_param.job_file = "{}.sh".format(config_param.job_file_base) # Stores the test image names and sizes. Created by data/VOC0712/create_list.sh config_param.name_size_file = "" # Solver parameters. config_param.gpulist = config_param.gpus.split(",") config_param.num_gpus = len(config_param.gpulist) # Divide the mini-batch to different GPUs. # In BVLC caffe, this has to be divided by num GPUs - not required in NVIDIA/caffe config_param.train_batch_size_in_proto = config_param.batch_size #Solver params solver_param = { # Train parameters 'type': "SGD", 'base_lr': 1e-1, 'max_iter': 320000, 'weight_decay': 0.0001, 'lr_policy': "poly", 'power': 1, 'gamma': 0.1, 'momentum': 0.9, 'iter_size': int(math.ceil(config_param.accum_batch_size/config_param.batch_size)), 'snapshot': 10000, 'display': 100, #'average_loss': 10, 'solver_mode': P.Solver.GPU if (config_param.num_gpus > 0) else P.Solver.CPU, 'device_id': int(config_param.gpulist[0]) if (config_param.num_gpus > 0) else 0, 'debug_info': False, 'snapshot_after_train': True, # Test parameters 'test_iter': [int(math.ceil(config_param.num_test_image/config_param.test_batch_size))], 'test_interval': 2000, 'test_initialization': True, 'random_seed': 33, } #if args.solver_param != None: # solver_param.update(args.solver_param) if args.solver_param != None: for k in args.solver_param.keys(): solver_param.__setitem__(k,args.solver_param[k]) #solver_param.__setattr__(k,args.solver_param[k]) ### Hopefully you don't need to change the following ### # Check file. check_if_exist(config_param.train_data) check_if_exist(config_param.test_data) check_if_exist(config_param.label_map_file) if config_param.pretrain_model != None: check_if_exist(config_param.pretrain_model) make_if_not_exist(config_param.base_dir) make_if_not_exist(config_param.save_dir) make_if_not_exist(config_param.job_dir) make_if_not_exist(config_param.snapshot_dir) #---------------------- #Net definition def define_net(phase): # Create train net. net = caffe.NetSpec() #if you want the train and test in same proto, #get the proto string for the data layer in train phase seperately and return it #set threads and parser_threads to 1 for the time being until an occassional random crash in NVIDIAcaffe:caffe-0.16 is fixed train_proto_str = [] threads = 1 if phase=='train': data_kwargs = {'source':config_param.train_data, 'name':'data', 'batch_size':config_param.train_batch_size_in_proto, 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'),'ntop':2,'threads':threads, 'parser_threads':threads} net['data'], net['label'] = L.Data(transform_param=config_param.train_transform_param, **data_kwargs) out_layer = 'data' elif phase=='test': data_kwargs = {'source':config_param.test_data, 'name':'data', 'batch_size':config_param.test_batch_size_in_proto, 'backend':caffe_pb2.DataParameter.DB.Value('LMDB'), 'ntop':2, 'threads':threads, 'parser_threads':threads} net['data'], net['label'] = L.Data(transform_param=config_param.test_transform_param,**data_kwargs) out_layer = 'data' elif phase=='deploy': net['data'] = L.Input(shape=[dict(dim=[1, 3, config_param.image_height, config_param.image_width])]) out_layer = 'data' bias_kwargs = { #fixed value with lr_mult=0 'param': [dict(lr_mult=0, decay_mult=0)], 'filler': dict(type='constant', value=(-config_param.mean_value)), } net['data/bias'] = L.Bias(net[out_layer], in_place=False, **bias_kwargs) out_layer = 'data/bias' if config_param.model_name == 'jacintonet11v2': out_layer = models.jacintonet_v2.jacintonet11(net, from_layer=out_layer,\ num_output=config_param.num_output,stride_list=config_param.stride_list,dilation_list=config_param.dilation_list,\ freeze_layers=config_param.freeze_layers) elif 'mobilenetv2' in config_param.model_name: expansion_t = float(config_param.model_name.split('netv2t')[1].split('-')[0]) if 'v2t' in config_param.model_name else 6 wide_factor = float(config_param.model_name.split('-')[1]) if '-' in config_param.model_name else 1.0 out_layer = models.mobilenetv2.mobilenetv2(net, from_layer=out_layer, wide_factor=wide_factor, expansion_t=expansion_t) elif 'mobilenet' in config_param.model_name: wide_factor = float(config_param.model_name.split('-')[1]) out_layer = models.mobilenet.mobilenet(net, from_layer=out_layer, wide_factor=wide_factor) else: ValueError("Invalid model name") if phase=='train' or phase=='test': net["loss"] = L.SoftmaxWithLoss(net[out_layer], net['label'], propagate_down=[True, False]) net["accuracy/top1"] = L.Accuracy(net[out_layer], net['label'], include=dict(phase=caffe_pb2.Phase.Value('TEST'))) accuracy_param_top5 = { 'top_k': 5 } net["accuracy/top5"] = L.Accuracy(net[out_layer], net['label'], accuracy_param=accuracy_param_top5, include=dict(phase=caffe_pb2.Phase.Value('TEST'))) elif phase=='deploy': net['prob'] = L.Softmax(net[out_layer]) return net #---------------------- net = define_net(phase='train') with open(config_param.train_net_file, 'w') as f: print('name: "{}_train"'.format(config_param.model_name), file=f) #if you want the train and test in same proto, #get the proto string for the data layer, train phase. #print(train_proto_str, file=f) print(net.to_proto(verbose=False), file=f) if config_param.save_dir!=config_param.job_dir: shutil.copy(config_param.train_net_file, config_param.job_dir) # Create test net. net = define_net(phase='test') with open(config_param.test_net_file, 'w') as f: print('name: "{}_test"'.format(config_param.model_name), file=f) print(net.to_proto(verbose=False), file=f) if config_param.save_dir!=config_param.job_dir: shutil.copy(config_param.test_net_file, config_param.job_dir) # Create deploy net. deploy_net = define_net(phase='deploy') with open(config_param.deploy_net_file, 'w') as f: net_param = deploy_net.to_proto(verbose=False) # Remove the few layers first del net_param.layer[0] #del net_param.layer[-1] #del net_param.layer[-1] #del net_param.layer[-1] net_param.name = '{}_deploy'.format(config_param.model_name) net_param.input.extend(['data']) net_param.input_shape.extend([ caffe_pb2.BlobShape(dim=[1, 3, config_param.image_height, config_param.image_width])]) print(net_param, file=f) if config_param.save_dir!=config_param.job_dir: shutil.copy(config_param.deploy_net_file, config_param.job_dir) # Create solver. solver = caffe_pb2.SolverParameter( train_net=config_param.train_net_file, test_net=[config_param.test_net_file], snapshot_prefix=config_param.snapshot_prefix, **solver_param) with open(config_param.solver_file, 'w') as f: print(solver, file=f) if config_param.save_dir!=config_param.job_dir: shutil.copy(solver_file, job_dir) max_iter = 0 # Find most recent snapshot. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int(basename.split("{}_iter_".format(config_param.model_name))[1]) if iter > max_iter: max_iter = iter train_src_param = None if config_param.pretrain_model != None: train_src_param = '--weights="{}" \\\n'.format(config_param.pretrain_model) if config_param.resume_training: if max_iter > 0: train_src_param = '--snapshot="{}_iter_{}.solverstate" \\\n'.format(config_param.snapshot_prefix, max_iter) if config_param.remove_old_models: # Remove any snapshots smaller than max_iter. for file in os.listdir(config_param.snapshot_dir): if file.endswith(".solverstate"): basename = os.path.splitext(file)[0] iter = int(basename.split("{}_iter_".format(config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) if file.endswith(".caffemodel"): basename = os.path.splitext(file)[0] iter = int(basename.split("{}_iter_".format(config_param.model_name))[1]) if max_iter > iter: os.remove("{}/{}".format(config_param.snapshot_dir, file)) # Create job file. with open(config_param.job_file, 'w') as f: #f.write('cd {}\n'.format(config_param.caffe_root)) f.write('{} {} \\\n'.format(config_param.caffe_root, config_param.caffe_cmd)) if(config_param.caffe_cmd == 'test'): f.write('--model="{}" \\\n'.format(config_param.test_net_file)) f.write('--iterations="{}" \\\n'.format(solver_param['test_iter'][0])) if config_param.display_sparsity: f.write('--display_sparsity=1 \\\n') else: f.write('--solver="{}" \\\n'.format(config_param.solver_file)) if train_src_param != None: f.write(train_src_param) if solver_param['solver_mode'] == P.Solver.GPU: f.write('--gpu "{}" 2>&1 | tee {}\n'.format(config_param.gpus, config_param.log_file)) else: f.write('2>&1 | tee {}\n'.format(config_param.log_file)) # Copy the python script to job_dir. py_file = os.path.abspath(__file__) shutil.copy(py_file, config_param.job_dir) # Run the job. os.chmod(config_param.job_file, stat.S_IRWXU) if config_param.run_soon: subprocess.call(config_param.job_file, shell=True)
def __setitem__(self, key, val): if hasattr(self, '_sync') and self._sync: OrderedDict.__setattr__(self, key, val) OrderedDict.__setitem__(self, key, val)
def __setattr__(self, name, value): """Allow elements in uppercase to be added to the OrderedDict.""" if name.isupper(): self[name] = value else: return OrderedDict.__setattr__(self, name, value)
def __setattr__(self, key, value): if "__" in key: OrderedDict.__setattr__(self, key, value) else: self.__setitem__(key, value)
def __setattr__(self, name, value): if name.startswith('_OrderedDict'): return OrderedDict.__setattr__(self, name, value) self.__setitem__(name, value)
def __setattr__(self,key,value): if key.startswith('_'): return OrderedDict.__setattr__(self,key,value) return self.__setitem__(key,value)
def __setattr__(self, name, value): if hasattr(self, '_sync') and self._sync: OrderedDict.__setitem__(self, name, value) OrderedDict.__setattr__(self, name, value)