def load_annotations(self, img_dir, img_suffix, ann_dir, seg_map_suffix, split): """Load annotation from directory. Args: img_dir (str): Path to image directory img_suffix (str): Suffix of images. ann_dir (str|None): Path to annotation directory. seg_map_suffix (str|None): Suffix of segmentation maps. split (str|None): Split txt file. If split is specified, only file with suffix in the splits will be loaded. Otherwise, all images in img_dir/ann_dir will be loaded. Default: None Returns: list[dict]: All image info of dataset. """ img_infos = [] with open(split) as f: for line in f: img_name = line.strip() img_info = dict(filename=img_name + img_suffix) if ann_dir is not None: seg_map = img_name.replace(*self.replace) + seg_map_suffix img_info['ann'] = dict(seg_map=seg_map) img_infos.append(img_info) print_log(f'Loaded {len(img_infos)} images', logger=get_root_logger()) return img_infos
def init_weights(self, pretrained=None): """Initialize the weights in backbone. Args: pretrained (str, optional): Path to pre-trained weights. Defaults to None. """ if isinstance(pretrained, str): logger = get_root_logger() load_checkpoint(self, pretrained, strict=False, logger=logger) elif pretrained is None: for m in self.modules(): if isinstance(m, nn.Conv2d): kaiming_init(m) elif isinstance(m, (_BatchNorm, nn.GroupNorm)): constant_init(m, 1) if self.zero_init_residual: for m in self.modules(): if isinstance(m, Bottleneck): constant_init(m.norm3, 0) elif isinstance(m, BasicBlock): constant_init(m.norm2, 0) else: raise TypeError('pretrained must be a str or None')
def init_weights(self, pretrained=None): logger = get_root_logger() if self.init_cfg is None and pretrained is None: logger.warn(f'No pre-trained weights for ' f'{self.__class__.__name__}, ' f'training start from scratch') pass else: assert 'checkpoint' in self.init_cfg, f'Only support ' \ f'specify `Pretrained` in ' \ f'`init_cfg` in ' \ f'{self.__class__.__name__} ' if self.init_cfg is not None: ckpt_path = self.init_cfg['checkpoint'] elif pretrained is not None: ckpt_path = pretrained ckpt = _load_checkpoint(ckpt_path, logger=logger, map_location='cpu') if 'state_dict' in ckpt: _state_dict = ckpt['state_dict'] elif 'model' in ckpt: _state_dict = ckpt['model'] else: _state_dict = ckpt state_dict = _state_dict missing_keys, unexpected_keys = \ self.load_state_dict(state_dict, False)
def main(args): config = Config.fromfile(args.config) if not os.path.exists(args.checkpoint_root): os.makedirs(args.checkpoint_root, 0o775) # test single model if args.model_name: if args.model_name in config: model_infos = config[args.model_name] if not isinstance(model_infos, list): model_infos = [model_infos] for model_info in model_infos: config_name = model_info['config'].strip() print(f'processing: {config_name}', flush=True) checkpoint = osp.join(args.checkpoint_root, model_info['checkpoint'].strip()) try: # build the model from a config file and a checkpoint file inference_model(config_name, checkpoint, args) except Exception: print(f'{config_name} test failed!') continue return else: raise RuntimeError('model name input error.') # test all model logger = get_root_logger( log_file='benchmark_inference_image.log', log_level=logging.ERROR) for model_name in config: model_infos = config[model_name] if not isinstance(model_infos, list): model_infos = [model_infos] for model_info in model_infos: print('processing: ', model_info['config'], flush=True) config_path = model_info['config'].strip() config_name = osp.splitext(osp.basename(config_path))[0] checkpoint_name = model_info['checkpoint'].strip() checkpoint = osp.join(args.checkpoint_root, checkpoint_name) # ensure checkpoint exists try: if not osp.exists(checkpoint): download_checkpoint(checkpoint_name, model_name, config_name.rstrip('.py'), args.checkpoint_root) except Exception: logger.error(f'{checkpoint_name} download error') continue # test model inference with checkpoint try: # build the model from a config file and a checkpoint file inference_model(config_path, checkpoint, args, logger) except Exception as e: logger.error(f'{config_path} " : {repr(e)}')
def init_weights(self, pretrained=None): if isinstance(pretrained, str): logger = get_root_logger() load_checkpoint(self, pretrained, map_location='cpu', strict=False, logger=logger)
def main(): args = parse_args() model_name = args.model_name # yml path generate. # If model_name is not set, script will check all of the models. if model_name is not None: yml_list = [(model_name, f'configs/{model_name}/{model_name}.yml')] else: # check all yml_list = [(x, f'configs/{x}/{x}.yml') for x in os.listdir('configs/') if x != '_base_'] logger = get_root_logger(log_file='url_check.log', log_level=logging.ERROR) for model_name, yml_path in yml_list: # Default yaml loader unsafe. model_infos = yml.load(open(yml_path, 'r'), Loader=yml.CLoader)['Models'] for model_info in model_infos: config_name = model_info['Name'] checkpoint_url = model_info['Weights'] # checkpoint url check status_code, flag = check_url(checkpoint_url) if flag: logger.info(f'checkpoint | {config_name} | {checkpoint_url} | ' f'{status_code} valid') else: logger.error( f'checkpoint | {config_name} | {checkpoint_url} | ' f'{status_code} | error') # log_json check checkpoint_name = checkpoint_url.split('/')[-1] model_time = '-'.join(checkpoint_name.split('-')[:-1]).replace( f'{config_name}_', '') # two style of log_json name # use '_' to link model_time (will be deprecated) log_json_url_1 = f'https://download.openmmlab.com/mmsegmentation/v0.5/{model_name}/{config_name}/{config_name}_{model_time}.log.json' # noqa status_code_1, flag_1 = check_url(log_json_url_1) # use '-' to link model_time log_json_url_2 = f'https://download.openmmlab.com/mmsegmentation/v0.5/{model_name}/{config_name}/{config_name}-{model_time}.log.json' # noqa status_code_2, flag_2 = check_url(log_json_url_2) if flag_1 or flag_2: if flag_1: logger.info( f'log.json | {config_name} | {log_json_url_1} | ' f'{status_code_1} | valid') else: logger.info( f'log.json | {config_name} | {log_json_url_2} | ' f'{status_code_2} | valid') else: logger.error( f'log.json | {config_name} | {log_json_url_1} & ' f'{log_json_url_2} | {status_code_1} & {status_code_2} | ' 'error')
def init_weights(self): if isinstance(self.pretrained, str): logger = get_root_logger() checkpoint = _load_checkpoint(self.pretrained, logger=logger, map_location='cpu') if 'state_dict' in checkpoint: state_dict = checkpoint['state_dict'] elif 'model' in checkpoint: state_dict = checkpoint['model'] else: state_dict = checkpoint if self.pretrain_style == 'timm': # Because the refactor of vit is blocked by mmcls, # so we firstly use timm pretrain weights to train # downstream model. state_dict = vit_convert(state_dict) if 'pos_embed' in state_dict.keys(): if self.pos_embed.shape != state_dict['pos_embed'].shape: logger.info(msg=f'Resize the pos_embed shape from ' f'{state_dict["pos_embed"].shape} to ' f'{self.pos_embed.shape}') h, w = self.img_size pos_size = int( math.sqrt(state_dict['pos_embed'].shape[1] - 1)) state_dict['pos_embed'] = self.resize_pos_embed( state_dict['pos_embed'], (h // self.patch_size, w // self.patch_size), (pos_size, pos_size), self.interpolate_mode) self.load_state_dict(state_dict, False) elif self.pretrained is None: super(VisionTransformer, self).init_weights() # We only implement the 'jax_impl' initialization implemented at # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py#L353 # noqa: E501 trunc_normal_init(self.pos_embed, std=.02) trunc_normal_init(self.cls_token, std=.02) for n, m in self.named_modules(): if isinstance(m, nn.Linear): trunc_normal_init(m.weight, std=.02) if m.bias is not None: if 'ffn' in n: normal_init(m.bias, std=1e-6) else: constant_init(m.bias, 0) elif isinstance(m, nn.Conv2d): kaiming_init(m.weight, mode='fan_in') if m.bias is not None: constant_init(m.bias, 0) elif isinstance(m, (_BatchNorm, nn.GroupNorm, nn.LayerNorm)): constant_init(m.bias, 0) constant_init(m.weight, 1.0)
def load_annotations(self, img_dir, img_suffix, ann_dir, seg_map_suffix, split): """Load annotation from directory. Args: img_dir (str): Path to image directory img_suffix (str): Suffix of images. ann_dir (str|None): Path to annotation directory. seg_map_suffix (str|None): Suffix of segmentation maps. split (str|None): Split txt file. If split is specified, only file with suffix in the splits will be loaded. Otherwise, all images in img_dir/ann_dir will be loaded. Default: None Returns: list[dict]: All image info of dataset. #TODO: currently, we need to ensure that the label files have exactly the same folder structures as the image files, which is not flexible. """ img_infos = [] if split is not None: with open(split) as f: for line in f: img_name = line.strip() img_info = dict(filename=img_name + img_suffix) if ann_dir is not None: # seg_map = osp.join(ann_dir, img_name + seg_map_suffix) # img_info['ann'] = dict(seg_map=seg_map, exist_label=osp.exists(seg_map)) seg_map = img_name + seg_map_suffix img_info['ann'] = dict(seg_map=seg_map, exist_label=osp.exists( osp.join(ann_dir, seg_map))) img_infos.append(img_info) else: for img in mmcv.scandir(img_dir, img_suffix, recursive=True): # img_info = dict(filename=osp.join(img_dir, img)) img_info = dict(filename=img) if ann_dir is not None: # seg_map = osp.join(ann_dir, # img.replace(img_suffix, seg_map_suffix)) # img_info['ann'] = dict(seg_map=seg_map, exist_label=osp.exists(seg_map)) seg_map = img.replace(img_suffix, seg_map_suffix) img_info['ann'] = dict(seg_map=seg_map, exist_label=osp.exists( osp.join(ann_dir, seg_map))) img_infos.append(img_info) print_log(f'Loaded {len(img_infos)} images', logger=get_root_logger()) return img_infos
def init_weights(self, pretrained=None): """Initialize the weights in backbone. Args: pretrained (str, optional): Path to pre-trained weights. Defaults to None. """ def _init_weights(m): if isinstance(m, nn.Linear): trunc_normal_(m.weight, std=.02) if isinstance(m, nn.Linear) and m.bias is not None: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.LayerNorm): nn.init.constant_(m.bias, 0) nn.init.constant_(m.weight, 1.0) if isinstance(pretrained, str): self.apply(_init_weights) logger = get_root_logger() checkpoint = torch.load(pretrained, map_location='cpu') for key in self.state_dict().keys(): if 'relative_position_bias_table' in key: if checkpoint['model'][key].shape[0] != self.state_dict( )[key].shape[0]: pos_bias_table = checkpoint['model'][key] old_window_size = int(pos_bias_table.shape[0]**.5) new_window_size = int( self.state_dict()[key].shape[0]**.5) num_head = pos_bias_table.shape[1] new_pos_bias_table = torch.nn.functional.interpolate( pos_bias_table.permute(1, 0).reshape( 1, num_head, old_window_size, old_window_size), size=(new_window_size, new_window_size), mode='bicubic', align_corners=False) checkpoint['model'][key] = new_pos_bias_table.reshape( num_head, -1).permute(1, 0) if 'relative_position_index' in key: checkpoint['model'][key] = self.state_dict()[key] msg = self.load_state_dict(checkpoint['model'], strict=False) logger.info(msg) # load_checkpoint(self, pretrained, strict=False, logger=logger) elif pretrained is None: self.apply(_init_weights) else: raise TypeError('pretrained must be a str or None')
def init_weights(self): """Use xavier initialization for all weight parameter and set classification head bias as a specific value when use focal loss.""" for p in self.parameters(): if p.dim() > 1: nn.init.xavier_uniform_(p) else: # adopt the default initialization for # the weight and bias of the layer norm pass if self.kernel_init: logger = get_root_logger() logger.info( 'mask kernel in mask head is normal initialized by std 0.01') nn.init.normal_(self.fc_mask.weight, mean=0, std=0.01)
def init_weights(self, pretrained=None): if isinstance(pretrained, str): logger = get_root_logger() checkpoint = _load_checkpoint(pretrained, logger=logger) if 'state_dict' in checkpoint: state_dict = checkpoint['state_dict'] elif 'model' in checkpoint: state_dict = checkpoint['model'] else: state_dict = checkpoint if 'pos_embed' in state_dict.keys(): if self.pos_embed.shape != state_dict['pos_embed'].shape: logger.info(msg=f'Resize the pos_embed shape from \ {state_dict["pos_embed"].shape} to {self.pos_embed.shape}') h, w = self.img_size pos_size = int( math.sqrt(state_dict['pos_embed'].shape[1] - 1)) state_dict['pos_embed'] = self.resize_pos_embed( state_dict['pos_embed'], (h, w), (pos_size, pos_size), self.patch_size, self.interpolate_mode) self.load_state_dict(state_dict, False) elif pretrained is None: # We only implement the 'jax_impl' initialization implemented at # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py#L353 # noqa: E501 trunc_normal_(self.pos_embed, std=.02) trunc_normal_(self.cls_token, std=.02) for n, m in self.named_modules(): if isinstance(m, Linear): trunc_normal_(m.weight, std=.02) if m.bias is not None: if 'mlp' in n: normal_init(m.bias, std=1e-6) else: constant_init(m.bias, 0) elif isinstance(m, Conv2d): kaiming_init(m.weight, mode='fan_in') if m.bias is not None: constant_init(m.bias, 0) elif isinstance(m, (_BatchNorm, nn.GroupNorm, nn.LayerNorm)): constant_init(m.bias, 0) constant_init(m.weight, 1.0) else: raise TypeError('pretrained must be a str or None')
def init_weights(self): if (isinstance(self.init_cfg, dict) and self.init_cfg.get('type') == 'Pretrained'): logger = get_root_logger() checkpoint = _load_checkpoint( self.init_cfg['checkpoint'], logger=logger, map_location='cpu') if 'state_dict' in checkpoint: state_dict = checkpoint['state_dict'] else: state_dict = checkpoint if 'pos_embed' in state_dict.keys(): if self.pos_embed.shape != state_dict['pos_embed'].shape: logger.info(msg=f'Resize the pos_embed shape from ' f'{state_dict["pos_embed"].shape} to ' f'{self.pos_embed.shape}') h, w = self.img_size pos_size = int( math.sqrt(state_dict['pos_embed'].shape[1] - 1)) state_dict['pos_embed'] = self.resize_pos_embed( state_dict['pos_embed'], (h // self.patch_size, w // self.patch_size), (pos_size, pos_size), self.interpolate_mode) self.load_state_dict(state_dict, False) elif self.init_cfg is not None: super(VisionTransformer, self).init_weights() else: # We only implement the 'jax_impl' initialization implemented at # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py#L353 # noqa: E501 trunc_normal_(self.pos_embed, std=.02) trunc_normal_(self.cls_token, std=.02) for n, m in self.named_modules(): if isinstance(m, nn.Linear): trunc_normal_(m.weight, std=.02) if m.bias is not None: if 'ffn' in n: nn.init.normal_(m.bias, mean=0., std=1e-6) else: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.Conv2d): kaiming_init(m, mode='fan_in', bias=0.) elif isinstance(m, (_BatchNorm, nn.GroupNorm, nn.LayerNorm)): constant_init(m, val=1.0, bias=0.)
def load_annotations(self, img_dir, img_suffix, ann_dir, seg_map_suffix, split): """Load annotation from directory. Args: img_dir (str): Path to image directory img_suffix (str): Suffix of images. ann_dir (str|None): Path to annotation directory. seg_map_suffix (str|None): Suffix of segmentation maps. split (str|None): Split txt file. If split is specified, only file with suffix in the splits will be loaded. Otherwise, all images in img_dir/ann_dir will be loaded. Default: None Returns: list[dict]: All image info of dataset. """ img_infos = [] if split is not None: lines = mmcv.list_from_file( split, file_client_args=self.file_client_args) for line in lines: img_name = line.strip() img_info = dict(filename=img_name + img_suffix) if ann_dir is not None: seg_map = img_name + seg_map_suffix img_info['ann'] = dict(seg_map=seg_map) img_infos.append(img_info) else: for img in self.file_client.list_dir_or_file( dir_path=img_dir, list_dir=False, suffix=img_suffix, recursive=True): img_info = dict(filename=img) if ann_dir is not None: seg_map = img.replace(img_suffix, seg_map_suffix) img_info['ann'] = dict(seg_map=seg_map) img_infos.append(img_info) img_infos = sorted(img_infos, key=lambda x: x['filename']) print_log(f'Loaded {len(img_infos)} images', logger=get_root_logger()) return img_infos
def init_weights(self): def _init_weights(m): if isinstance(m, nn.Linear): trunc_normal_(m.weight, std=.02) if isinstance(m, nn.Linear) and m.bias is not None: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.LayerNorm): nn.init.constant_(m.bias, 0) nn.init.constant_(m.weight, 1.0) self.apply(_init_weights) self.fix_init_weight() if (isinstance(self.init_cfg, dict) and self.init_cfg.get('type') == 'Pretrained'): logger = get_root_logger() checkpoint = _load_checkpoint( self.init_cfg['checkpoint'], logger=logger, map_location='cpu') state_dict = self.resize_rel_pos_embed(checkpoint) state_dict = self.resize_abs_pos_embed(state_dict) self.load_state_dict(state_dict, False) elif self.init_cfg is not None: super(MAE, self).init_weights() else: # We only implement the 'jax_impl' initialization implemented at # https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py#L353 # noqa: E501 # Copyright 2019 Ross Wightman # Licensed under the Apache License, Version 2.0 (the "License") trunc_normal_(self.cls_token, std=.02) for n, m in self.named_modules(): if isinstance(m, nn.Linear): trunc_normal_(m.weight, std=.02) if m.bias is not None: if 'ffn' in n: nn.init.normal_(m.bias, mean=0., std=1e-6) else: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.Conv2d): kaiming_init(m, mode='fan_in', bias=0.) elif isinstance(m, (_BatchNorm, nn.GroupNorm, nn.LayerNorm)): constant_init(m, val=1.0, bias=0.)
def init_weights(self, pretrained=None): """Initialize the weights in backbone. Args: pretrained (str, optional): Path to pre-trained weights. Defaults to None. """ def _init_weights(m): if isinstance(m, nn.Linear): trunc_normal_(m.weight, std=.02) if isinstance(m, nn.Linear) and m.bias is not None: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.LayerNorm): nn.init.constant_(m.bias, 0) nn.init.constant_(m.weight, 1.0) if isinstance(pretrained, str): self.apply(_init_weights) logger = get_root_logger() load_checkpoint(self, pretrained, strict=False, logger=logger) elif pretrained is None: self.apply(_init_weights) else: raise TypeError('pretrained must be a str or None')
def load_annotations(self, img_dir, img_suffix, ann_dir, seg_map_suffix, sequence_dir, sequence_suffix, split): """Load annotation from directory. Args: img_dir (str): Path to image directory img_suffix (str): Suffix of images. ann_dir (str|None): Path to annotation directory. seg_map_suffix (str|None): Suffix of segmentation maps. sequence_dir(str|None): Path to sequence directory. sequence_suffix(str|None): Suffix of sequence. split (str|None): Split txt file. If split is specified, only file with suffix in the splits will be loaded. Otherwise, all images in img_dir/ann_dir will be loaded. Default: None Returns: list[dict]: All image info of dataset. """ img_infos = [] if split is not None: with open(split) as f: for line in f: img_name = line.strip() img_info = dict(filename=img_name + img_suffix) if ann_dir is not None: seg_map = img_name + seg_map_suffix img_info['ann'] = dict(seg_map=seg_map) if sequence_dir is not None: frames = [] current_frame = img_name.split('_')[self.sequence_index] if self.random_select: frame_index = random.sample(range(1, self.sequence_range + 1), self.sequence_num) frame_index = sorted(frame_index, reverse=True) for index in frame_index: if 'f' in current_frame: frame = str(int(current_frame.replace('f', '')) - index).zfill( len(current_frame) - 1) frame_name = '_'.join(img_name.split('_')[ :self.sequence_index]) + f'_f{frame}' + sequence_suffix frames.append(frame_name) else: frame = str(int(current_frame) - index).zfill(len(current_frame)) frame_name = '_'.join(img_name.split('_')[ :self.sequence_index]) + f'_{frame}' + sequence_suffix frames.append(frame_name) else: for index in range(1, self.sequence_num + 1): if 'f' in current_frame: frame = str(int(current_frame.replace('f', '')) - index).zfill( len(current_frame) - 1) frame_name = '_'.join(img_name.split('_')[ :self.sequence_index]) + f'_f{frame}' + sequence_suffix frames.append(frame_name) else: frame = str(int(current_frame) - index).zfill(len(current_frame)) frame_name = '_'.join(img_name.split('_')[ :self.sequence_index]) + f'_{frame}' + sequence_suffix frames.append(frame_name) img_info['sequence'] = dict(frames=frames) img_infos.append(img_info) else: for img in mmcv.scandir(img_dir, img_suffix, recursive=True): img_info = dict(filename=img) if ann_dir is not None: seg_map = img.replace(img_suffix, seg_map_suffix) img_info['ann'] = dict(seg_map=seg_map) if sequence_dir is not None: #** I may need to change this here. frames = [] current_frame = img.split('_')[self.sequence_index] if self.random_select: frame_index = random.sample(range(1, self.sequence_range + 1), self.sequence_num) frame_index = sorted(frame_index, reverse=True) for index in frame_index: if 'f' in current_frame: frame = str(int(current_frame.replace('f', '')) - index).zfill(len(current_frame) - 1) frame_name = '_'.join(img.split('_')[ :self.sequence_index]) + f'_f{frame}' + sequence_suffix frames.append(frame_name) else: frame = str(int(current_frame) - index).zfill(len(current_frame)) frame_name = '_'.join(img.split('_')[ :self.sequence_index]) + f'_{frame}' + sequence_suffix frames.append(frame_name) else: #** We are working here. for index in range(1, self.sequence_num + 1): if 'f' in current_frame: frame = str(int(current_frame.replace('f', '')) - index).zfill(len(current_frame) - 1) frame_name = '_'.join(img.split('_')[ :self.sequence_index]) + f'_f{frame}' + sequence_suffix frames.append(frame_name) else: frame = str(int(current_frame) - index).zfill(len(current_frame)) frame_name = '_'.join(img.split('_')[ :self.sequence_index]) + f'_{frame}' + sequence_suffix frames.append(frame_name) img_info['sequence'] = dict(frames=frames) img_infos.append(img_info) print_log(f'Loaded {len(img_infos)} images', logger=get_root_logger()) return img_infos
def train_segmentor(model, dataset, cfg, distributed=False, validate=False, timestamp=None, meta=None): """Launch segmentor training.""" logger = get_root_logger(cfg.log_level) # prepare data loaders dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset] data_loaders = [ build_dataloader( ds, cfg.data.samples_per_gpu, cfg.data.workers_per_gpu, # cfg.gpus will be ignored if distributed len(cfg.gpu_ids), dist=distributed, seed=cfg.seed, drop_last=True) for ds in dataset ] # put model on gpus if distributed: find_unused_parameters = cfg.get('find_unused_parameters', True) # Sets the `find_unused_parameters` parameter in # torch.nn.parallel.DistributedDataParallel model = MMDistributedDataParallel( model.cuda(), device_ids=[torch.cuda.current_device()], broadcast_buffers=False, find_unused_parameters=find_unused_parameters) # model.ddp = model else: model = MMDataParallel(model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids) # print(model) # build runner optimizer = build_optimizer(model, cfg.optimizer) if cfg.get('runner') is None: cfg.runner = {'type': 'IterBasedRunner', 'max_iters': cfg.total_iters} warnings.warn( 'config is now expected to have a `runner` section, ' 'please set `runner` in your config.', UserWarning) runner = build_runner(cfg.runner, default_args=dict(model=model, batch_processor=None, optimizer=optimizer, work_dir=cfg.work_dir, logger=logger, meta=meta)) # print(cfg.optimizer) # print(cfg.optimizer_config) optimizer_config = OptimizerHookLW(**cfg.optimizer_config) # register hooks runner.register_training_hooks(cfg.lr_config, optimizer_config, cfg.checkpoint_config, cfg.log_config, cfg.get('momentum_config', None)) # an ugly walkaround to make the .log and .log.json filenames the same runner.timestamp = timestamp # register eval hooks if validate: val_dataset = build_dataset(cfg.data.val, dict(test_mode=True)) val_dataloader = build_dataloader( val_dataset, samples_per_gpu=1, workers_per_gpu=cfg.data.workers_per_gpu, dist=distributed, shuffle=False) eval_cfg = cfg.get('evaluation', {}) eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner' eval_hook = DistEvalHook if distributed else EvalHook runner.register_hook(eval_hook(val_dataloader, **eval_cfg)) if cfg.resume_from: runner.resume(cfg.resume_from) elif cfg.load_from: runner.load_checkpoint(cfg.load_from) runner.run(data_loaders, cfg.workflow)
def load_annotations(self, img_dir, img_suffix, ann_dir, seg_map_suffix, split, attack_info): """Load annotation from directory. Args: img_dir (str): Path to image directory img_suffix (str): Suffix of images. ann_dir (str|None): Path to annotation directory. seg_map_suffix (str|None): Suffix of segmentation maps. split (str|None): Split txt file. If split is specified, only file with suffix in the splits will be loaded. Otherwise, all images in img_dir/ann_dir will be loaded. Default: None Returns: list[dict]: All image info of dataset. """ img_infos = [] if split is not None: with open(split) as f: for line in f: img_name = line.strip() img_info = dict(filename=img_name + img_suffix) if ann_dir is not None: seg_map = img_name + seg_map_suffix img_info['ann'] = dict(seg_map=seg_map) img_infos.append(img_info) else: for img in mmcv.scandir(img_dir, img_suffix, recursive=True): img_info = dict(filename=img) if ann_dir is not None: seg_map = img.replace(img_suffix, seg_map_suffix) img_info['ann'] = dict(seg_map=seg_map) img_infos.append(img_info) print_log(f'Loaded {len(img_infos)} images', logger=get_root_logger()) if attack_info is None: # 如果attack_info=None,那么原封不动地返回original img_infos return img_infos # 否则,将img_infos打上'should_attack'标记 include_label = [] if attack_info['trigger_label'] is not None: include_label.append(attack_info['trigger_label']) if attack_info['from_label'] is not None: include_label.append(attack_info['from_label']) attacked_num = len(img_infos) if include_label: for i in range(len(img_infos)): seg_map_dir = osp.join(self.ann_dir, img_infos[i]['ann']['seg_map']) seg_map = mmcv.imread(seg_map_dir, flag='unchanged', backend='pillow') seg_map = np.unique(seg_map) img_infos[i]['should_attack'] = True for label in include_label: # 检验是不是每一个类别都在seg_map里面出现过? if label not in seg_map: # 如果这个类别在seg_map里面没有出现过,那么把该样本剔除 img_infos[i]['should_attack'] = False attacked_num -= 1 break else: for i in range(len(img_infos)): img_infos[i]['should_attack'] = True print_log(f'Attacked num: {attacked_num}', logger=get_root_logger()) return img_infos
def main(): args = parse_args() assert args.out or args.eval or args.format_only or args.show \ or args.show_dir, \ ('Please specify at least one operation (save/eval/format/show the ' 'results / save the results) with the argument "--out", "--eval"' ', "--format-only", "--show" or "--show-dir"') if args.eval and args.format_only: raise ValueError('--eval and --format_only cannot be both specified') if args.out is not None and not args.out.endswith(('.pkl', '.pickle')): raise ValueError('The output file must be a pkl file.') cfg = mmcv.Config.fromfile(args.config) # work_dir is determined in this priority: CLI > segment in file > filename if args.work_dir is not None: # update configs according to CLI args if args.work_dir is not None cfg.work_dir = args.work_dir elif cfg.get('work_dir', None) is None: # use config filename as default work_dir if cfg.work_dir is None cfg.work_dir = osp.join('./work_dirs', osp.splitext(osp.basename(args.config))[0]) if args.options is not None: cfg.merge_from_dict(args.options) # set cudnn_benchmark if cfg.get('cudnn_benchmark', False): torch.backends.cudnn.benchmark = True if args.aug_test: # hard code index cfg.data.test.pipeline[1].img_ratios = [ 0.5, 0.75, 1.0, 1.25, 1.5, 1.75 ] cfg.data.test.pipeline[1].flip = True cfg.model.pretrained = None cfg.data.test.test_mode = True # init distributed env first, since logger depends on the dist info. if args.launcher == 'none': distributed = False else: distributed = True init_dist(args.launcher, **cfg.dist_params) # init the logger before other steps logger = None if args.eval: timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) log_file = osp.join(cfg.work_dir, f'test_{timestamp}.log') logger = get_root_logger(log_file=log_file, log_level=cfg.log_level) # set random seeds if args.seed is not None: set_random_seed(args.seed, deterministic=args.deterministic) if logger is not None: logger.info(f'Set random seed to {args.seed}, deterministic: ' f'{args.deterministic}') else: print(f'Set random seed to {args.seed}, deterministic: ' f'{args.deterministic}') # build the dataloader # TODO: support multiple images per gpu (only minor changes are needed) dataset = build_dataset(cfg.data.val, dict(test_mode=True)) data_loader = build_dataloader( dataset, samples_per_gpu=1, workers_per_gpu=cfg.data.workers_per_gpu, dist=distributed, shuffle=False) # build the model and load checkpoint model = build_segmentor(cfg.model, train_cfg=None, test_cfg=cfg.test_cfg) checkpoint = load_checkpoint(model, args.checkpoint, map_location='cpu') model.CLASSES = checkpoint['meta']['CLASSES'] model.PALETTE = checkpoint['meta']['PALETTE'] if not distributed: model = MMDataParallel(model, device_ids=[0]) outputs = single_gpu_test(model, data_loader, args.show, args.show_dir) else: model = MMDistributedDataParallel( model.cuda(), device_ids=[torch.cuda.current_device()], broadcast_buffers=False) outputs = multi_gpu_test(model, data_loader, args.tmpdir, args.gpu_collect) rank, _ = get_dist_info() if rank == 0: if args.out: print(f'\nwriting results to {args.out}') mmcv.dump(outputs, args.out) kwargs = {} if args.eval_options is None else args.eval_options if args.format_only: dataset.format_results(outputs, **kwargs) if args.eval: dataset.evaluate(outputs, args.eval, logger, **kwargs)
def load_annotations(self): with open(self.ann_file) as f: anns = json.load(f) print_log('{} images loaded!'.format(len(anns)), logger=get_root_logger()) return anns
def main(): cfg, config_fn = get_cfg() _, config_name, _ = get_file_name_extension(config_fn) # dataset_name = "SV3_roads" dataset_name = "SN7_buildings" args_work_dir = path_join("C:/_koray/korhun/mmsegmentation/data/space", dataset_name + "_" + config_name) args_resume_from = path_join(args_work_dir, "latest.pth") if not os.path.isfile(args_resume_from): args_resume_from = None args_launcher = "none" args_seed = None args_deterministic = False args_no_validate = False if not os.path.isdir(args_work_dir): create_dir(args_work_dir) # cfg = Config.fromfile(args_config) # if args.options is not None: # cfg.merge_from_dict(args.options) # set cudnn_benchmark if cfg.get('cudnn_benchmark', False): torch.backends.cudnn.benchmark = True cfg.work_dir = args_work_dir # if args.load_from is not None: # cfg.load_from = args.load_from if args_resume_from is not None: cfg.resume_from = args_resume_from # if args.gpu_ids is not None: # cfg.gpu_ids = args.gpu_ids # else: # cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus) cfg.gpu_ids = range(0, 1) # init distributed env first, since logger depends on the dist info. if args_launcher == 'none': distributed = False else: distributed = True init_dist(args_launcher, **cfg.dist_params) # create work_dir mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) # dump config cfg.dump(osp.join(cfg.work_dir, config_name)) # init the logger before other steps timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) log_file = osp.join(cfg.work_dir, f'{timestamp}.log') logger = get_root_logger(log_file=log_file, log_level=cfg.log_level) # init the meta dict to record some important information such as # environment info and seed, which will be logged meta = dict() # log env info env_info_dict = collect_env() env_info = '\n'.join([f'{k}: {v}' for k, v in env_info_dict.items()]) dash_line = '-' * 60 + '\n' logger.info('Environment info:\n' + dash_line + env_info + '\n' + dash_line) meta['env_info'] = env_info # log some basic info logger.info(f'Distributed training: {distributed}') logger.info(f'Config:\n{cfg.pretty_text}') # set random seeds if args_seed is not None: logger.info(f'Set random seed to {args_seed}, deterministic: ' f'{args_deterministic}') set_random_seed(args_seed, deterministic=args_deterministic) cfg.seed = args_seed meta['seed'] = args_seed meta['exp_name'] = config_name model = build_segmentor( cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg')) logger.info(model) datasets = [build_dataset(cfg.data.train)] if len(cfg.workflow) == 2: val_dataset = copy.deepcopy(cfg.data.val) val_dataset.pipeline = cfg.data.train.pipeline datasets.append(build_dataset(val_dataset)) if cfg.checkpoint_config is not None: # save mmseg version, config file content and class names in # checkpoints as meta data cfg.checkpoint_config.meta = dict( mmseg_version=f'{__version__}+{get_git_hash()[:7]}', config=cfg.pretty_text, CLASSES=datasets[0].CLASSES, PALETTE=datasets[0].PALETTE) # add an attribute for visualization convenience model.CLASSES = datasets[0].CLASSES train_segmentor( model, datasets, cfg, distributed=distributed, validate=(not args_no_validate), timestamp=timestamp, meta=meta)
def forward(self, cls_score, label, weight=None, avg_factor=None, reduction_override=None, **kwargs): """Forward function belong cross region. Args: cls_score: label: weight: avg_factor: reduction_override: """ e = 30 self.temp = 10 count = 1 t1 = time() assert reduction_override in (None, 'none', 'mean', 'sum') reduction = (reduction_override if reduction_override else self.reduction) if self.class_weight is not None: class_weight = cls_score.new_tensor(self.class_weight) else: class_weight = None loss_cls = self.cls_criterion(cls_score, label, weight, class_weight=class_weight, reduction=reduction, avg_factor=avg_factor, **kwargs) b, c, _, _ = cls_score.shape # b_ft_cross_region1, b_tt_region1 = self.batch_cross_class(cls_score, label) b_ft_cross_region, b_tt_region_score, b_cross_class, b_tt_class = self.cross_class( cls_score, label, b) logits = [ torch.zeros(1, device=cls_score.device) for b_logits in range(b) ] for i in range(b): cross_class = b_cross_class[i] for j, key in enumerate(cross_class): class_key1, class_key2 = key.split('/', 1) tt_index1 = b_tt_class[i].index(int(class_key1)) tt_index2 = b_tt_class[i].index(int(class_key2)) phi1 = b_tt_region_score[i][:, :, :, tt_index1] phi2 = b_tt_region_score[i][:, :, :, tt_index2] phi1 = torch.reshape(phi1, (21, -1)) phi2 = torch.reshape(phi2, (21, -1)) phi1_light = phi1[:, phi1.sum( dim=0) != 0].detach() # [21, length1] phi2_light = phi2[:, phi2.sum( dim=0) != 0].detach() # [21, length2] cross_score = cls_score[ i, :, :, :] * b_ft_cross_region[i][:, :, j] cross_score = torch.reshape(cross_score, (21, -1)) cross_score_light = cross_score[:, cross_score.sum(dim=0) != 0] # [21, length] phi1_length = phi1_light.shape[1] phi2_length = phi2_light.shape[1] cross_score_length = cross_score_light.shape[1] if phi1_length <= cross_score_length: if phi1_length == 0: continue # neg_scores = F.kl_div(cross_score_light[:, 0:phi1_length], phi1_light, reduction='mean') neg_scores = torch.mean( F.cosine_similarity(cross_score_light[:, 0:phi1_length], phi1_light, dim=0)) else: neg_step = phi1_length // cross_score_length neg_scores = torch.zeros(cross_score_length, device=cross_score_light.device) for nk in range(neg_step): # neg_scores_step = F.kl_div(cross_score_light, # phi1_light[:, k * cross_score_length:(k + 1) * cross_score_length], # reduction='mean') neg_scores_step = F.cosine_similarity( cross_score_light, phi1_light[:, nk * cross_score_length:(nk + 1) * cross_score_length], dim=0) neg_scores += neg_scores_step neg_scores = torch.mean(neg_scores / neg_step) if phi2_length <= cross_score_length: if phi2_length == 0: continue # pos_scores = F.kl_div(cross_score_light[:, 0:phi2_length], phi2_light, reduction='mean') pos_scores = torch.mean( F.cosine_similarity(cross_score_light[:, 0:phi2_length], phi2_light, dim=0)) else: pos_step = phi2_length // cross_score_length pos_scores = torch.zeros(cross_score_length, device=cross_score_light.device) for pk in range(pos_step): # pos_scores_step = F.kl_div(cross_score_light, # phi2_light[:, k * cross_score_length:(k + 1) * cross_score_length], # reduction='mean') pos_scores_step = F.cosine_similarity( cross_score_light, phi2_light[:, pk * cross_score_length:(pk + 1) * cross_score_length], dim=0) pos_scores += pos_scores_step pos_scores = torch.mean(pos_scores / pos_step) logits[i] += ((neg_scores + 1) / (pos_scores + 1)) if cross_class: logits[i] = logits[i] / len(cross_class) logits = sum(logits) / b loss2 = self.loss_weight * logits + loss_cls print_log(f"seg_loss-{loss_cls},pwc_los-{logits}", logger=get_root_logger()) return loss2
def add_params(self, params, module, **kwargs): """Add all parameters of module to the params list. The parameters of the given module will be added to the list of param groups, with specific rules defined by paramwise_cfg. Args: params (list[dict]): A list of param groups, it will be modified in place. module (nn.Module): The module to be added. """ logger = get_root_logger() parameter_groups = {} logger.info(f'self.paramwise_cfg is {self.paramwise_cfg}') num_layers = self.paramwise_cfg.get('num_layers') + 2 decay_rate = self.paramwise_cfg.get('decay_rate') decay_type = self.paramwise_cfg.get('decay_type', 'layer_wise') logger.info('Build LearningRateDecayOptimizerConstructor ' f'{decay_type} {decay_rate} - {num_layers}') weight_decay = self.base_wd for name, param in module.named_parameters(): if not param.requires_grad: continue # frozen weights if len(param.shape) == 1 or name.endswith('.bias') or name in ( 'pos_embed', 'cls_token'): group_name = 'no_decay' this_weight_decay = 0. else: group_name = 'decay' this_weight_decay = weight_decay if 'layer_wise' in decay_type: if 'ConvNeXt' in module.backbone.__class__.__name__: layer_id = get_layer_id_for_convnext( name, self.paramwise_cfg.get('num_layers')) logger.info(f'set param {name} as id {layer_id}') elif 'BEiT' in module.backbone.__class__.__name__ or \ 'MAE' in module.backbone.__class__.__name__: layer_id = get_layer_id_for_vit(name, num_layers) logger.info(f'set param {name} as id {layer_id}') else: raise NotImplementedError() elif decay_type == 'stage_wise': if 'ConvNeXt' in module.backbone.__class__.__name__: layer_id = get_stage_id_for_convnext(name, num_layers) logger.info(f'set param {name} as id {layer_id}') else: raise NotImplementedError() group_name = f'layer_{layer_id}_{group_name}' if group_name not in parameter_groups: scale = decay_rate**(num_layers - layer_id - 1) parameter_groups[group_name] = { 'weight_decay': this_weight_decay, 'params': [], 'param_names': [], 'lr_scale': scale, 'group_name': group_name, 'lr': scale * self.base_lr, } parameter_groups[group_name]['params'].append(param) parameter_groups[group_name]['param_names'].append(name) rank, _ = get_dist_info() if rank == 0: to_display = {} for key in parameter_groups: to_display[key] = { 'param_names': parameter_groups[key]['param_names'], 'lr_scale': parameter_groups[key]['lr_scale'], 'lr': parameter_groups[key]['lr'], 'weight_decay': parameter_groups[key]['weight_decay'], } logger.info(f'Param groups = {json.dumps(to_display, indent=2)}') params.extend(parameter_groups.values())
def train_segmentor(model, dataset, cfg, distributed=False, validate=False, timestamp=None, meta=None): """Launch segmentor training.""" logger = get_root_logger(cfg.log_level) # prepare data loaders dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset] data_loaders = [ build_dataloader( ds, cfg.data.samples_per_gpu, cfg.data.workers_per_gpu, # cfg.gpus will be ignored if distributed len(cfg.gpu_ids), dist=distributed, seed=cfg.seed, drop_last=True) for ds in dataset ] # put model on gpus if distributed: find_unused_parameters = cfg.get('find_unused_parameters', False) # Sets the `find_unused_parameters` parameter in # torch.nn.parallel.DistributedDataParallel model = MMDistributedDataParallel( model.cuda(), device_ids=[torch.cuda.current_device()], broadcast_buffers=False, find_unused_parameters=find_unused_parameters) else: model = MMDataParallel(model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids) # build runner optimizer = build_optimizer(model, cfg.optimizer) if cfg.get('runner') is None: cfg.runner = {'type': 'IterBasedRunner', 'max_iters': cfg.total_iters} warnings.warn( 'config is now expected to have a `runner` section, ' 'please set `runner` in your config.', UserWarning) runner = build_runner(cfg.runner, default_args=dict(model=model, batch_processor=None, optimizer=optimizer, work_dir=cfg.work_dir, logger=logger, meta=meta)) # register hooks runner.register_training_hooks(cfg.lr_config, cfg.optimizer_config, cfg.checkpoint_config, cfg.log_config, cfg.get('momentum_config', None)) # an ugly walkaround to make the .log and .log.json filenames the same runner.timestamp = timestamp # register eval hooks if validate: val_dataset = build_dataset(cfg.data.val, dict(test_mode=True)) val_dataloader = build_dataloader( val_dataset, samples_per_gpu=1, workers_per_gpu=cfg.data.workers_per_gpu, dist=distributed, shuffle=False) eval_cfg = cfg.get('evaluation', {}) eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner' eval_hook = DistEvalHook if distributed else EvalHook # In this PR (https://github.com/open-mmlab/mmcv/pull/1193), the # priority of IterTimerHook has been modified from 'NORMAL' to 'LOW'. runner.register_hook(eval_hook(val_dataloader, **eval_cfg), priority='LOW') # user-defined hooks if cfg.get('custom_hooks', None): custom_hooks = cfg.custom_hooks assert isinstance(custom_hooks, list), \ f'custom_hooks expect list type, but got {type(custom_hooks)}' for hook_cfg in cfg.custom_hooks: assert isinstance(hook_cfg, dict), \ 'Each item in custom_hooks expects dict type, but got ' \ f'{type(hook_cfg)}' hook_cfg = hook_cfg.copy() priority = hook_cfg.pop('priority', 'NORMAL') hook = build_from_cfg(hook_cfg, HOOKS) runner.register_hook(hook, priority=priority) if cfg.resume_from: runner.resume(cfg.resume_from) elif cfg.load_from: runner.load_checkpoint(cfg.load_from) runner.run(data_loaders, cfg.workflow)
def main(): args = parse_args() cfg = Config.fromfile(args.config) if args.options is not None: cfg.merge_from_dict(args.options) # set cudnn_benchmark if cfg.get('cudnn_benchmark', False): torch.backends.cudnn.benchmark = True # work_dir is determined in this priority: CLI > segment in file > filename if args.work_dir is not None: # update configs according to CLI args if args.work_dir is not None cfg.work_dir = args.work_dir elif cfg.get('work_dir', None) is None: # use config filename as default work_dir if cfg.work_dir is None cfg.work_dir = osp.join('./work_dirs', osp.splitext(osp.basename(args.config))[0]) if args.load_from is not None: cfg.load_from = args.load_from if args.resume_from is not None: cfg.resume_from = args.resume_from if args.gpu_ids is not None: cfg.gpu_ids = args.gpu_ids else: cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus) # init distributed env first, since logger depends on the dist info. if args.launcher == 'none': distributed = False else: distributed = True init_dist(args.launcher, **cfg.dist_params) # create work_dir mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) # dump config cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config))) # init the logger before other steps timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) log_file = osp.join(cfg.work_dir, f'{timestamp}.log') logger = get_root_logger(log_file=log_file, log_level=cfg.log_level) # init the meta dict to record some important information such as # environment info and seed, which will be logged meta = dict() # log env info env_info_dict = collect_env() env_info = '\n'.join([f'{k}: {v}' for k, v in env_info_dict.items()]) dash_line = '-' * 60 + '\n' logger.info('Environment info:\n' + dash_line + env_info + '\n' + dash_line) meta['env_info'] = env_info # log some basic info logger.info(f'Distributed training: {distributed}') logger.info(f'Config:\n{cfg.pretty_text}') # set random seeds if args.seed is not None: logger.info(f'Set random seed to {args.seed}, deterministic: ' f'{args.deterministic}') set_random_seed(args.seed, deterministic=args.deterministic) cfg.seed = args.seed meta['seed'] = args.seed meta['exp_name'] = osp.basename(args.config) model = build_segmentor(cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg')) logger.info(model) datasets = [build_dataset(cfg.data.train)] if len(cfg.workflow) == 2: val_dataset = copy.deepcopy(cfg.data.val) val_dataset.pipeline = cfg.data.train.pipeline datasets.append(build_dataset(val_dataset)) if cfg.checkpoint_config is not None: # save mmseg version, config file content and class names in # checkpoints as meta data cfg.checkpoint_config.meta = dict( mmseg_version=f'{__version__}+{get_git_hash()[:7]}', config=cfg.pretty_text, CLASSES=datasets[0].CLASSES, PALETTE=datasets[0].PALETTE) # add an attribute for visualization convenience model.CLASSES = datasets[0].CLASSES train_segmentor(model, datasets, cfg, distributed=distributed, validate=(not args.no_validate), timestamp=timestamp, meta=meta)
def train_segmentor(model, dataset, cfg, distributed=False, validate=False, timestamp=None, meta=None): """Launch segmentor training.""" logger = get_root_logger(cfg.log_level) # prepare data loaders dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset] if not torch.cuda.is_available(): len_gpu_ids = 2 # need to be changed else: len_gpu_ids = len(cfg.gpu_ids) data_loaders = [ build_dataloader( ds, # A PyTorch dataset. cfg.data. samples_per_gpu, # Number of training samples on each GPU, i.e., batch size of each GPU. cfg.data. workers_per_gpu, # How many subprocesses to use for data loading for each GPU. # cfg.gpus will be ignored if distributed len_gpu_ids, # len(cfg.gpu_ids), # Number of GPUs. Only used in non-distributed training. dist=distributed, # Distributed training/test or not. Default: True. seed=cfg.seed, drop_last=True) for ds in dataset ] ''' About build_dataloader shuffle (bool): Whether to shuffle the data at every epoch. Default: True. seed (int | None): Seed to be used. Default: None. drop_last (bool): Whether to drop the last incomplete batch in epoch. Default: False pin_memory (bool): Whether to use pin_memory in DataLoader. Default: True dataloader_type (str): Type of dataloader. Default: 'PoolDataLoader' kwargs: any keyword argument to be used to initialize DataLoader''' # put model on gpus if distributed: find_unused_parameters = cfg.get('find_unused_parameters', False) # Sets the `find_unused_parameters` parameter in # torch.nn.parallel.DistributedDataParallel model = MMDistributedDataParallel( model.cuda(), device_ids=[torch.cuda.current_device()], broadcast_buffers=False, find_unused_parameters=find_unused_parameters) else: if torch.cuda.is_available(): model = MMDataParallel(model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids) else: model = MMDataParallel(model.to('cpu')) # build runner optimizer = build_optimizer(model, cfg.optimizer) if cfg.get('runner') is None: cfg.runner = {'type': 'IterBasedRunner', 'max_iters': cfg.total_iters} warnings.warn( 'config is now expected to have a `runner` section, ' 'please set `runner` in your config.', UserWarning) runner = build_runner(cfg.runner, default_args=dict(model=model, batch_processor=None, optimizer=optimizer, work_dir=cfg.work_dir, logger=logger, meta=meta)) # register hooks runner.register_training_hooks(cfg.lr_config, cfg.optimizer_config, cfg.checkpoint_config, cfg.log_config, cfg.get('momentum_config', None)) # an ugly walkaround to make the .log and .log.json filenames the same runner.timestamp = timestamp # register eval hooks if validate: val_dataset = build_dataset(cfg.data.val, dict(test_mode=True)) val_dataloader = build_dataloader( val_dataset, samples_per_gpu=len_gpu_ids, workers_per_gpu=cfg.data.workers_per_gpu, dist=distributed, shuffle=False) eval_cfg = cfg.get('evaluation', {}) eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner' eval_hook = DistEvalHook if distributed else EvalHook runner.register_hook(eval_hook(val_dataloader, **eval_cfg)) if cfg.resume_from: runner.resume(cfg.resume_from) elif cfg.load_from: runner.load_checkpoint(cfg.load_from) runner.run(data_loaders, cfg.workflow)
def forward(self, feats, pseudo_logits, cls_score, gt_semantic_seg, img_metas, weight=None, avg_factor=None, reduction_override=None, **kwargs): """Forward function.""" # calculate the negative logits of proposed loss function # feats1: features of the overlapping region in the first crop (NxC).... # feats2: features of the overlapping region in the second crop (NxC).... # neg_feats: all selected negative features (nxC).... # pseudo_labels1: pseudo labels for feats1 (N) # pseudo_logits1: confidence for feats1 (N).... # pseudo_logits2: confidence for feats2 (N).... # neg_pseudo_labels: pseudo labels for neg_feats (n) # gamma: the threshold value for positive filtering # temp: the temperature value # b: an integer to divide the loss computation into several parts # N: overlapping region; n: crop region b = 300 gamma = 0.75 n = img_metas[1]['img_shape'] n = n[0] * n[1] loss = [] pos_feats, pos_pseudo_labels = self.feature_prepare( feats, pseudo_logits, img_metas) for j in range(len(pos_feats)): feats1 = torch.reshape(pos_feats[j][0], (128, -1)) feats2 = torch.reshape(pos_feats[j][1], (128, -1)) neg_feats = torch.reshape(feats[0][j, :, :, :], (128, -1)) # change dim pseudo_logits1 = pos_pseudo_labels[j][0] pseudo_logits2 = pos_pseudo_labels[j][1] pseudo_labels1 = torch.reshape(torch.argmax(pseudo_logits1, dim=0), (1, -1)) # pseudo_logits-->[B,C,H,W] pos_pseudo_labels1-->[1,H,W] neg_pseudo_labels1 = torch.argmax(torch.squeeze( pseudo_logits[0][j], dim=0), dim=0) neg_pseudo_labels1 = torch.reshape(neg_pseudo_labels1, (1, -1)) # print_log(f'input{j}{[feats1.size(), feats2.size()]}', logger=get_root_logger()) pos1 = (feats1 * feats2.detach()).sum(0) / self.temp # positive scores (N) # try: # pos1 = (feats1 * feats2.detach()).sum(0) / temp # positive scores (N) # except: # import ipdb # ipdb.set_trace() neg_logits = torch.zeros( pos1.size(0), device=pos1.device) # initialize negative scores (n)N # divide the negative logits computation into several parts # in each part, only b negative samples are considered for i in range((n - 1) // b + 1): neg_feats_i = neg_feats[:, i * b:(i + 1) * b] neg_pseudo_labels_i = neg_pseudo_labels1[:, i * b:(i + 1) * b] neg_logits_i = torch.utils.checkpoint.checkpoint( self.calc_neg_logits, feats1, # [128,h*w] pseudo_labels1, # [1,h*w] neg_feats_i, # [128,b] neg_pseudo_labels_i) # [1,b] neg_logits += neg_logits_i # compute the loss for the first crop logits1 = torch.exp(pos1) / (torch.exp(pos1) + neg_logits + 1e-8) lossn = -torch.log(logits1 + 1e-8) # (N) dir_mask1 = (pseudo_logits1 < pseudo_logits2 ) # directional mask (N) pos_mask1 = (pseudo_logits2 > gamma) # positive filtering mask (N) mask1 = torch.reshape( torch.argmax((dir_mask1 * pos_mask1).float(), dim=0), (1, -1)).squeeze(0) # final loss for the first crop loss.append((mask1 * lossn).sum() / (mask1.sum() + 1e-8)) assert reduction_override in (None, 'none', 'mean', 'sum') reduction = (reduction_override if reduction_override else self.reduction) if self.class_weight is not None: class_weight = cls_score.new_tensor(self.class_weight) else: class_weight = None loss_cls = self.cls_criterion(cls_score, gt_semantic_seg, weight, class_weight=class_weight, reduction=reduction, avg_factor=avg_factor, **kwargs) loss1 = sum(loss) / len(pos_feats) loss2 = self.loss_weight * loss1 + loss_cls print_log(f"seg_loss-{loss2},con_los-{loss1}", logger=get_root_logger()) return loss2
def train_segmentor(model, dataset, cfg, distributed=False, validate=False, timestamp=None, meta=None): """Launch segmentor training.""" logger = get_root_logger(cfg.log_level) # prepare data loaders # print('----------------------------') # print(type(dataset),len(dataset)) # <class 'list'> 1 # print(type(dataset[0])) # <class 'mmseg.datasets.cityscapes.CityscapesDataset'> # print(len(dataset[0])) # 2975 # print(dataset[0][0]['img'].size()) dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset] data_loaders = [ build_dataloader( ds, cfg.data.samples_per_gpu, cfg.data.workers_per_gpu, # cfg.gpus will be ignored if distributed len(cfg.gpu_ids), dist=distributed, seed=cfg.seed, drop_last=True) for ds in dataset ] print('---------------------------') # print(data_loaders[0].next) print('before') print(cfg.gpu_ids) print(next(model.parameters()).device) # print(next(model.teacher.parameters()).device) # put model on gpus if distributed: find_unused_parameters = cfg.get('find_unused_parameters', False) find_unused_parameters = True # Sets the `find_unused_parameters` parameter in # torch.nn.parallel.DistributedDataParallel model = MMDistributedDataParallel( model.cuda(), device_ids=[torch.cuda.current_device()], broadcast_buffers=False, find_unused_parameters=find_unused_parameters) else: model = MMDataParallel(model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids) print('after') print(next(model.parameters()).device) # print(next(model.teacher.parameters()).device) # build runner optimizer = build_optimizer(model, cfg.optimizer) runner = IterBasedRunner(model=model, batch_processor=None, optimizer=optimizer, work_dir=cfg.work_dir, logger=logger, meta=meta) # register hooks runner.register_training_hooks(cfg.lr_config, cfg.optimizer_config, cfg.checkpoint_config, cfg.log_config, cfg.get('momentum_config', None)) # an ugly walkaround to make the .log and .log.json filenames the same runner.timestamp = timestamp # register eval hooks if validate: val_dataset = build_dataset(cfg.data.val, dict(test_mode=True)) val_dataloader = build_dataloader( val_dataset, samples_per_gpu=1, workers_per_gpu=cfg.data.workers_per_gpu, dist=distributed, shuffle=False) eval_cfg = cfg.get('evaluation', {}) eval_hook = DistEvalHook if distributed else EvalHook runner.register_hook(eval_hook(val_dataloader, **eval_cfg)) if cfg.resume_from: runner.resume(cfg.resume_from) elif cfg.load_from: runner.load_checkpoint(cfg.load_from) runner.run(data_loaders, cfg.workflow, cfg.total_iters)
def main(): args = parse_args() cfg = Config.fromfile(args.config) if args.cfg_options is not None: cfg.merge_from_dict(args.cfg_options) # set cudnn_benchmark if cfg.get('cudnn_benchmark', False): torch.backends.cudnn.benchmark = True # work_dir is determined in this priority: CLI > segment in file > filename if args.work_dir is not None: # update configs according to CLI args if args.work_dir is not None cfg.work_dir = args.work_dir elif cfg.get('work_dir', None) is None: # use config filename as default work_dir if cfg.work_dir is None cfg.work_dir = osp.join('./work_dirs', osp.splitext(osp.basename(args.config))[0]) if args.load_from is not None: cfg.load_from = args.load_from if args.resume_from is not None: cfg.resume_from = args.resume_from if args.gpus is not None: cfg.gpu_ids = range(1) warnings.warn('`--gpus` is deprecated because we only support ' 'single GPU mode in non-distributed training. ' 'Use `gpus=1` now.') if args.gpu_ids is not None: cfg.gpu_ids = args.gpu_ids[0:1] warnings.warn('`--gpu-ids` is deprecated, please use `--gpu-id`. ' 'Because we only support single GPU mode in ' 'non-distributed training. Use the first GPU ' 'in `gpu_ids` now.') if args.gpus is None and args.gpu_ids is None: cfg.gpu_ids = [args.gpu_id] cfg.auto_resume = args.auto_resume # init distributed env first, since logger depends on the dist info. if args.launcher == 'none': distributed = False else: distributed = True init_dist(args.launcher, **cfg.dist_params) # gpu_ids is used to calculate iter when resuming checkpoint _, world_size = get_dist_info() cfg.gpu_ids = range(world_size) # create work_dir mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) # dump config cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config))) # init the logger before other steps timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) log_file = osp.join(cfg.work_dir, f'{timestamp}.log') logger = get_root_logger(log_file=log_file, log_level=cfg.log_level) # set multi-process settings setup_multi_processes(cfg) # init the meta dict to record some important information such as # environment info and seed, which will be logged meta = dict() # log env info env_info_dict = collect_env() env_info = '\n'.join([f'{k}: {v}' for k, v in env_info_dict.items()]) dash_line = '-' * 60 + '\n' logger.info('Environment info:\n' + dash_line + env_info + '\n' + dash_line) meta['env_info'] = env_info # log some basic info logger.info(f'Distributed training: {distributed}') logger.info(f'Config:\n{cfg.pretty_text}') # set random seeds seed = init_random_seed(args.seed) seed = seed + dist.get_rank() if args.diff_seed else seed logger.info(f'Set random seed to {seed}, ' f'deterministic: {args.deterministic}') set_random_seed(seed, deterministic=args.deterministic) cfg.seed = seed meta['seed'] = seed meta['exp_name'] = osp.basename(args.config) model = build_segmentor( cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg')) model.init_weights() # SyncBN is not support for DP if not distributed: warnings.warn( 'SyncBN is only supported with DDP. To be compatible with DP, ' 'we convert SyncBN to BN. Please use dist_train.sh which can ' 'avoid this error.') model = revert_sync_batchnorm(model) logger.info(model) datasets = [build_dataset(cfg.data.train)] if len(cfg.workflow) == 2: val_dataset = copy.deepcopy(cfg.data.val) val_dataset.pipeline = cfg.data.train.pipeline datasets.append(build_dataset(val_dataset)) if cfg.checkpoint_config is not None: # save mmseg version, config file content and class names in # checkpoints as meta data cfg.checkpoint_config.meta = dict( mmseg_version=f'{__version__}+{get_git_hash()[:7]}', config=cfg.pretty_text, CLASSES=datasets[0].CLASSES, PALETTE=datasets[0].PALETTE) # add an attribute for visualization convenience model.CLASSES = datasets[0].CLASSES # passing checkpoint meta for saving best checkpoint meta.update(cfg.checkpoint_config.meta) train_segmentor( model, datasets, cfg, distributed=distributed, validate=(not args.no_validate), timestamp=timestamp, meta=meta)
# dist=False, # seed=cfg.seed, # drop_last=True) for ds in dataset # ] # # iter_loaders = [IterLoader(x) for x in data_loaders] # # print(len(iter_loaders)) # create work_dir mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) # dump config # cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config))) # init the logger before other steps timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) log_file = osp.join(cfg.work_dir, f'{timestamp}.log') logger = get_root_logger(log_file=log_file, log_level=cfg.log_level) # init the meta dict to record some important information such as # environment info and seed, which will be logged meta = dict() # log env info env_info_dict = collect_env() env_info = '\n'.join([f'{k}: {v}' for k, v in env_info_dict.items()]) dash_line = '-' * 60 + '\n' logger.info('Environment info:\n' + dash_line + env_info + '\n' + dash_line) meta['env_info'] = env_info # log some basic info distributed = False logger.info(f'Distributed training: {distributed}') logger.info(f'Config:\n{cfg.pretty_text}')