Source code for holocron.models.classification.darknetv4
# Copyright (C) 2020-2022, François-Guillaume Fernandez.# This program is licensed under the Apache License 2.0.# See LICENSE or go to <https://www.apache.org/licenses/LICENSE-2.0> for full license details.fromcollectionsimportOrderedDictfromtypingimportAny,Callable,Dict,List,Optional,Tuple,Unionimporttorchimporttorch.nnasnnfromholocron.nnimportDropBlock2d,GlobalAvgPool2dfromholocron.nn.initimportinit_modulefrom..presetsimportIMAGENETTEfrom..utilsimportconv_sequence,load_pretrained_paramsfrom.darknetv3importResBlock__all__=["DarknetV4","cspdarknet53","cspdarknet53_mish"]default_cfgs:Dict[str,Dict[str,Any]]={"cspdarknet53":{**IMAGENETTE,"input_shape":(3,224,224),"url":"https://github.com/frgfm/Holocron/releases/download/v0.1.3/cspdarknet53_224-d2a17b18.pt",},"cspdarknet53_mish":{**IMAGENETTE,"input_shape":(3,224,224),"url":"https://github.com/frgfm/Holocron/releases/download/v0.1.3/cspdarknet53_mish_256-32d8ec68.pt",},}classCSPStage(nn.Module):def__init__(self,in_channels:int,out_channels:int,num_blocks:int=1,act_layer:Optional[nn.Module]=None,norm_layer:Optional[Callable[[int],nn.Module]]=None,drop_layer:Optional[Callable[...,nn.Module]]=None,conv_layer:Optional[Callable[...,nn.Module]]=None,)->None:super().__init__()compression=2ifnum_blocks>1else1self.base_layer=nn.Sequential(*conv_sequence(in_channels,out_channels,act_layer,norm_layer,drop_layer,conv_layer,kernel_size=3,padding=1,stride=2,bias=(norm_layerisNone),),# Share the conv*conv_sequence(out_channels,2*out_channels//compression,act_layer,norm_layer,drop_layer,conv_layer,kernel_size=1,bias=(norm_layerisNone),),)self.main=nn.Sequential(*[ResBlock(out_channels//compression,out_channels//compressionifnum_blocks>1elsein_channels,act_layer,norm_layer,drop_layer,conv_layer,)for_inrange(num_blocks)],*conv_sequence(out_channels//compression,out_channels//compression,act_layer,norm_layer,drop_layer,conv_layer,kernel_size=1,bias=(norm_layerisNone),),)self.transition=nn.Sequential(*conv_sequence(2*out_channels//compression,out_channels,act_layer,norm_layer,drop_layer,conv_layer,kernel_size=1,bias=(norm_layerisNone),))defforward(self,x:torch.Tensor)->torch.Tensor:x=self.base_layer(x)x1,x2=x.chunk(2,dim=1)returnself.transition(torch.cat([x1,self.main(x2)],dim=1))classDarknetBodyV4(nn.Sequential):def__init__(self,layout:List[Tuple[int,int]],in_channels:int=3,stem_channels:int=32,num_features:int=1,act_layer:Optional[nn.Module]=None,norm_layer:Optional[Callable[[int],nn.Module]]=None,drop_layer:Optional[Callable[...,nn.Module]]=None,conv_layer:Optional[Callable[...,nn.Module]]=None,)->None:super().__init__()ifact_layerisNone:act_layer=nn.LeakyReLU(inplace=True)ifnorm_layerisNone:norm_layer=nn.BatchNorm2din_chans=[stem_channels]+[_layout[0]for_layoutinlayout[:-1]]super().__init__(OrderedDict([("stem",nn.Sequential(*conv_sequence(in_channels,stem_channels,act_layer,norm_layer,drop_layer,conv_layer,kernel_size=3,padding=1,bias=(norm_layerisNone),)),),("stages",nn.Sequential(*[CSPStage(_in_chans,out_chans,num_blocks,act_layer,norm_layer,drop_layer,conv_layer)for_in_chans,(out_chans,num_blocks)inzip(in_chans,layout)]),),]))self.num_features=num_featuresdefforward(self,x:torch.Tensor)->Union[torch.Tensor,List[torch.Tensor]]:ifself.num_features==1:returnsuper().forward(x)self.stem:nn.Sequentialself.stages:nn.Sequentialx=self.stem(x)features=[]foridx,stageinenumerate(self.stages):x=stage(x)ifidx>=(len(self.stages)-self.num_features):features.append(x)returnfeaturesclassDarknetV4(nn.Sequential):def__init__(self,layout:List[Tuple[int,int]],num_classes:int=10,in_channels:int=3,stem_channels:int=32,num_features:int=1,act_layer:Optional[nn.Module]=None,norm_layer:Optional[Callable[[int],nn.Module]]=None,drop_layer:Optional[Callable[...,nn.Module]]=None,conv_layer:Optional[Callable[...,nn.Module]]=None,)->None:super().__init__(OrderedDict([("features",DarknetBodyV4(layout,in_channels,stem_channels,num_features,act_layer,norm_layer,drop_layer,conv_layer,),),("pool",GlobalAvgPool2d(flatten=True)),("classifier",nn.Linear(layout[-1][0],num_classes)),]))init_module(self,"leaky_relu")def_darknet(arch:str,pretrained:bool,progress:bool,layout:List[Tuple[int,int]],**kwargs:Any)->DarknetV4:# Build the modelmodel=DarknetV4(layout,**kwargs)model.default_cfg=default_cfgs[arch]# type: ignore[assignment]# Load pretrained parametersifpretrained:load_pretrained_params(model,default_cfgs[arch]["url"],progress)returnmodel
[docs]defcspdarknet53(pretrained:bool=False,progress:bool=True,**kwargs:Any)->DarknetV4:"""CSP-Darknet-53 from `"CSPNet: A New Backbone that can Enhance Learning Capability of CNN" <https://arxiv.org/pdf/1911.11929.pdf>`_ Args: pretrained (bool): If True, returns a model pre-trained on ImageNet progress (bool): If True, displays a progress bar of the download to stderr Returns: torch.nn.Module: classification model """return_darknet("cspdarknet53",pretrained,progress,[(64,1),(128,2),(256,8),(512,8),(1024,4)],**kwargs)
[docs]defcspdarknet53_mish(pretrained:bool=False,progress:bool=True,**kwargs:Any)->DarknetV4:"""Modified version of CSP-Darknet-53 from `"CSPNet: A New Backbone that can Enhance Learning Capability of CNN" <https://arxiv.org/pdf/1911.11929.pdf>`_ with Mish as activation layer and DropBlock as regularization layer. Args: pretrained (bool): If True, returns a model pre-trained on ImageNet progress (bool): If True, displays a progress bar of the download to stderr Returns: torch.nn.Module: classification model """kwargs["act_layer"]=nn.Mish(inplace=True)kwargs["drop_layer"]=DropBlock2dreturn_darknet("cspdarknet53_mish",pretrained,progress,[(64,1),(128,2),(256,8),(512,8),(1024,4)],**kwargs)