def test_backbone(module, feature): avail_model = getattr(backbones, module).supported_models for name in avail_model: if name in exclude_test: continue print(name, feature) pretrained = False if name not in no_pretrained and feature == "classifier": pretrained = True elif name != 'darknet53' and feature == 'tri_stage_fpn': network = backbones.get_backbone(name, pretrained=pretrained, feature_type=feature, n_classes=2, norm_layer=EvoNormBatch2d, norm_kwargs={'eps': 1e-3}) assert all(not isinstance(m, torch.nn.BatchNorm2d) for m in network.modules()) network = backbones.get_backbone(name, pretrained=pretrained, feature_type=feature, n_classes=2) x = torch.rand(2, 3, 224, 224) x = network(x) if feature == "tri_stage_fpn": out_run = [o.size(1) for o in x] out_def = list(network.out_channels)[2:] assert out_run == out_def, "channel size defined in '{}' model ({}) " \ "is not equal to output in runtime ({}).".format(name, out_def, out_run) elif feature == "classifier": assert x.size(1) == network.out_channels, "channel size defined in '{}' model ({}) is " \ "not equal to output in runtime ({}).".format(name, network.out_channels, x.size()) del network, x
def test_backbone_fail(module, feature): avail_model = getattr(backbones, module).supported_models for name in avail_model: if name in exclude_test: continue print(name, feature) pretrained = False if name not in no_pretrained and feature == "classifier": pretrained = True network = backbones.get_backbone(name, pretrained=pretrained, feature_type=feature, n_classes=2) channel = 2 with pytest.raises(RuntimeError): x = torch.rand(1, channel, 224, 224) x = network(x) if feature == "tri_stage_fpn": out_run = [o.size(1) for o in x] out_def = list(network.out_channels)[2:] assert out_run != out_def, "channel size defined in '{}' model ({}) " \ "is not equal to output in runtime ({}).".format(name, out_def, out_run) elif feature == "classifier": assert x.size(1) != network.out_channels, "channel size defined in '{}' model ({}) is " \ "not equal to output in runtime ({}).".format(name, network.out_channels, x.size()) del network, x
def __init__(self, backbone: str, feature_type='tri_stage_fpn', pretrained_backbone=False, freeze_backbone=False, *args, **kwargs): super(BackbonePoolConnector, self).__init__() if not isinstance(backbone, str): raise RuntimeError( "expects backbone to be 'str' instance, got %s" % (type(backbone))) if not feature_type in supported_feature_type: raise RuntimeError("feature type of '%s' is not supported, "\ "supported: %s" % (feature_type, supported_feature_type)) if isinstance(backbone, str): if feature_type == "classifier" and "n_classes" not in kwargs: ## number of classes in backbone only required for classifier feature type raise RuntimeError("'n_classes' argument in model for classifier feature "\ "is not defined, make sure you have define it properly.") backbone = get_backbone(backbone, pretrained=pretrained_backbone, feature_type=feature_type, *args, **kwargs) self.backbone = backbone if freeze_backbone: self.backbone.requires_grad_(False)
def calculate_models_params_and_flops(): backbone='darknet53' network = backbones.get_backbone(backbone, pretrained=False, feature_type='tri_stage_fpn', n_classes=1000) input = torch.randn(1, 3, 448, 448) bb_macs, _ = profile(network, inputs=(input, ),verbose=False) bb_params = summary(network,(3,448,448),device='cpu')[0].item() model_df = pd.DataFrame(columns=['model_name', 'params', 'mac/flops']) for key in model_argmap: model_cfg= create_model_cfg(key, model_argmap) model_components = create_model_components(model_cfg['name'], preprocess_args=model_cfg['preprocess_args'], network_args=model_cfg['network_args'], loss_args=model_cfg['loss_args'], postprocess_args=model_cfg['postprocess_args'], stage='validate') network=model_components.network model_macs, model_params = profile(network, inputs=(input, ),verbose=False) if 'backbone' in model_cfg.network_args: model_macs-=bb_macs model_params-=bb_params key+='_head' model_macs_in_g=model_macs/(10**9) model_params_in_m=model_params/(10**6) print(key,model_params_in_m,model_macs_in_g) model_df = model_df.append({'model_name': key, 'params': model_params_in_m, 'mac/flops': model_macs_in_g}, ignore_index=True) model_df.to_csv('models_summary.txt',index=False)
def test_backbone(module): default_cfgs = getattr(backbones, module).default_cfgs for name, cfg in default_cfgs.items(): if name in exclude_test: continue print(name) pretrained = False if name not in no_pretrained: pretrained = True network = backbones.get_backbone(name, pretrained=False, n_classes=2, norm_layer=EvoNormBatch2d, norm_kwargs={'eps': 1e-3}) assert all(not isinstance(m, nn.BatchNorm2d) for m in network.modules()) assert isinstance(network, backbones.BackboneBase) assert network.default_config == cfg assert network.name == name network = backbones.get_backbone(name, pretrained=pretrained, n_classes=2) stages = network.get_stages() assert len(stages) == 5 assert isinstance(stages, (nn.Sequential, nn.ModuleList)) classifier = network.get_classifier() assert isinstance(classifier, nn.Module) x = torch.rand(2, 3, 224, 224) out_run = [] with torch.no_grad(): for stage in stages: x = stage(x) out_run.append(x.size(1)) x = classifier(x) out_def = network.stages_channel assert isinstance(out_def, tuple) assert tuple(out_run) == out_def, "channel size defined in '{}' model ({}) " \ "is not equal to output in runtime ({}).".format(name, out_def, out_run) assert x.size(1) == network.num_classes, "channel size defined in '{}' model ({}) is " \ "not equal to output in runtime ({}).".format(name, network.num_classes, x.size()) del network, x
def calculate_backbone_params_and_flops(): all_supported_backbones=backbones.all_models backbone_df = pd.DataFrame(columns=['backbone_name', 'params', 'mac/flops']) for backbone in all_supported_backbones: network = backbones.get_backbone(backbone, pretrained=False, feature_type='tri_stage_fpn', n_classes=1000) input = torch.randn(1, 3, 224, 224) macs, _ = profile(network, inputs=(input, ),verbose=False) params = summary(network,(3,224,224),device='cpu')[0].item() macs_in_g=macs/(10**9) params_in_m=params/(10**6) print(backbone,params_in_m,macs_in_g) backbone_df = backbone_df.append({'backbone_name': backbone, 'params': params_in_m, 'mac/flops': macs_in_g}, ignore_index=True) backbone_df.to_csv('backbones_summary.txt',index=False)
def test_backbone_fail(module): avail_model = getattr(backbones, module).supported_models for name in avail_model: if name in exclude_test: continue print(name) pretrained = False if name not in no_pretrained: pretrained = True network = backbones.get_backbone(name, pretrained=pretrained, n_classes=2) assert isinstance(network, backbones.BackboneBase) channel = 2 with pytest.raises(RuntimeError): x = torch.rand(1, channel, 224, 224) x = network(x)
def test_reset_classifier(module): avail_model = getattr(backbones, module).supported_models backbone = backbones.get_backbone(avail_model[0]) assert isinstance(backbone, backbones.BackboneBase) backbone.requires_grad_(False) backbone = backbone.eval() num_feature = backbone.num_classifer_feature num_classes = 9 x = torch.randn(1, 3, 224, 224) ## change num_classes with default layer bb1 = deepcopy(backbone) bb1.reset_classifier(num_classes) bb1_out = bb1(x.clone()) assert bb1.num_classes == num_classes assert bb1_out.size(1) == num_classes ## custom layer classifier = nn.Sequential( nn.Linear(num_feature, 512), nn.Dropout2d(0.2), nn.Linear(512, num_classes) ) bb2 = deepcopy(backbone) bb2.reset_classifier(num_classes, classifier) bb2_out = bb2(x.clone()) assert bb1.num_classes == num_classes assert bb2_out.size(1) == num_classes ## num_classes is negative bb3 = deepcopy(backbone) bb3.reset_classifier(-1) bb3_out = bb3(x.clone()) assert bb3_out.size(1) == bb3.num_classifer_feature ## unknown type with pytest.raises(TypeError): backbone.reset_classifier(8, 'dummy')
def __init__(self, module: Union[str, BackboneBase, nn.Sequential, nn.ModuleList, Sequence], stages_output: Union[str, int, Sequence] = [2, 3, 4], stages_channel: Union[Sequence] = None, freeze: bool = False, name: str = None, **kwargs): super().__init__() stages = None reduce_stages_channel = False if isinstance(module, str): module = get_backbone(module, **kwargs) if isinstance(module, BackboneBase): name = module.name stages = module.get_stages() stages.add_module("classifier", module.get_classifier()) if stages_channel is None: reduce_stages_channel = True stages_channel = list( module.stages_channel) + [module.num_classes] elif isinstance(module, (nn.Sequential, nn.ModuleList)): stages = module elif isinstance(module, Sequence): stages = nn.Sequential(*module) else: raise TypeError( "'module' argument is expected to have 'str', 'BackboneBase', " "'nn.Sequential', 'nn.ModuleList', or list of 'nn.Module' type, got {}" .format(type(module))) self.stages_output = self._validate_stages_output( stages_output, len(stages), self._stages_output_str_map) max_stages = max(self.stages_output) for idx, (n, module) in enumerate(stages.named_children()): if idx > max_stages: break self.add_module(n, module) assert len( self ) == max_stages + 1, "This should not happened, please report as bug." if freeze: self.requires_grad_(False) self.freeze = freeze self._name = name if name else "backbone" self.hooks_handle = [ ModuleIOHook(m) for n, m in enumerate(self) if n in self.stages_output ] if stages_channel is None: module_out = self.forward(torch.randn(2, 3, 224, 224)) stages_channel = [o.size(1) for o in module_out] if reduce_stages_channel: stages_channel = [ x for n, x in enumerate(stages_channel) if n in self.stages_output ] if len(stages_channel) != len(self.stages_output): raise RuntimeError( "length of 'stages_channel' ({}) and number of 'stages_output' ({}) " "is expected to be equal.".format(len(stages_channel), len(self.stages_output))) self._stages_channel = tuple(stages_channel)
def test_backbone_class(): x = torch.randn(2, 3, 224, 224) ## normal model = Backbone("resnet18", stages_output="tri_stage", norm_layer=EvoNormBatch2d) with torch.no_grad(): y = model(x) assert model.name == "resnet18" assert model.stages_output == (2, 3, 4) assert model.stages_channel == (128, 256, 512) assert len(model.hooks_handle) == len(model.stages_output) assert len(model) == 5 assert all(not isinstance(m, torch.nn.BatchNorm2d) for m in model.modules()) assert tuple(o.size(1) for o in y) == model.stages_channel model = Backbone("resnet18", stages_output="classifier") with torch.no_grad(): y = model(x) assert model.name == "resnet18" assert model.stages_output == (5,) assert model.stages_channel == (1000,) assert len(model.hooks_handle) == len(model.stages_output) assert len(model) == 6 ## 5 stages with classifier assert tuple(o.size(1) for o in y) == model.stages_channel module = backbones.get_backbone("resnet18") model = Backbone(module, stages_output="tri_stage") assert model.name == "resnet18" assert model.stages_output == (2, 3, 4) assert model.stages_channel == (128, 256, 512) model = Backbone(module, stages_output="classifier") assert model.name == "resnet18" assert model.stages_output == (5,) assert model.stages_channel == (1000,) stages_channel = [128, 256, 512] num_classes = 10 stages = [ nn.Sequential( nn.Conv2d(3, 128, 3, padding=1), nn.ReLU(), nn.BatchNorm2d(128) ), nn.Sequential( nn.Conv2d(128, 256, 3, stride=2, padding=1), nn.ReLU(), nn.BatchNorm2d(256) ), nn.Sequential( nn.Conv2d(256, 512, 3, stride=2, padding=1), nn.ReLU(), nn.BatchNorm2d(512) ), ] classifier = nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Flatten(1), nn.Linear(512, num_classes) ) ## defined module model = Backbone(stages, stages_output=[0,1,2], stages_channel=stages_channel, name="dummy") assert model.name == "dummy" assert model.stages_output == (0,1,2) assert model.stages_channel == tuple(stages_channel) model = Backbone(nn.Sequential(*stages), stages_output=[0,1,2], stages_channel=stages_channel, name="dummy") assert model.name == "dummy" assert model.stages_output == (0,1,2) assert model.stages_channel == tuple(stages_channel) with pytest.raises(RuntimeError): Backbone(stages, stages_output=[0,1], stages_channel=stages_channel, name="dummy") ## infer channel output model = Backbone(stages, stages_output=[0,1,2]) assert model.stages_output == (0,1,2) assert model.stages_channel == tuple(stages_channel) ## defined module with classifier module = stages + [classifier] model = Backbone(module, stages_output="classifier", stages_channel=[num_classes], name="dummy") assert model.name == "dummy" assert model.stages_output == (3,) assert model.stages_channel == (num_classes,) model = Backbone(nn.Sequential(*module), stages_output="classifier", stages_channel=[num_classes], name="dummy") assert model.name == "dummy" assert model.stages_output == (3,) assert model.stages_channel == (num_classes,) ## infer channel output model = Backbone(module, stages_output=-1) assert model.stages_output == (3,) assert model.stages_channel == (num_classes,) model = Backbone("resnet18", stages_output="classifier", freeze=True) assert all(not p.requires_grad for p in model.parameters()) ## invalid module with pytest.raises(TypeError): Backbone({"invalid": stages}, stages_output=[0,1,2], stages_channel=stages_channel)