from collections import OrderedDict import torch.nn.functional as F from .BasicModules import * class DarknetLayer(nn.Module): def __init__(self,**kwargs): super().__init__() self.negative_slope = kwargs.get('negative_slop',0) self.norm_choice = kwargs.get('norm_choice','BN') self.kernel_size = kwargs.get('kernel_size',3) self.conv_choice = kwargs.get('conv_choice','basic') num_in_features = kwargs.get('num_in_features',1) self.num_in_features = num_in_features self.conv0 = ConvBlock(negative_slope=self.negative_slope,norm_choice=self.norm_choice,num_in_features=num_in_features, num_out_features=int(num_in_features/2),kernel_size=1) self.conv1 = ConvBlock(negative_slope=self.negative_slope,norm_choice=self.norm_choice,num_in_features=int(num_in_features/2), num_out_features=num_in_features,kernel_size=self.kernel_size) self.shortcut = DarkNetShortCut() def forward(self,x): x0 = self.conv0(x) x0 = self.conv1(x0) x = self.shortcut(x0,x) return x class Darknet(nn.Module): def __init__(self,**kwargs): super().__init__() self.block_inplanes = kwargs.get('block_inplanes') self.negative_slope = kwargs.get('negative_slop',0) self.norm_choice = kwargs.get('norm_choice','BN') self.kernel_size = kwargs.get('kernel_size',3) self.num_stages = kwargs.get('num_stages',4) self.pooling_ratios = kwargs.get('pooling_ratios') self.repeat_time_list = kwargs.get('repeat_time_list') self.dropout_rate = kwargs.get('dropout_rate',0) self.num_class = kwargs.get('num_class',1) self.conv_choice = kwargs.get('conv_choice','basic') n_input_channel = kwargs.get('n_input_channel',1) n_in_features = int(self.block_inplanes[0]/2) layer_map_dict = {} layer_map_dict['conv_0'] = ConvBlock(negative_slope=self.negative_slope,norm_choice=self.norm_choice,num_in_features=n_input_channel, num_out_features=n_in_features,kernel_size=3) num_in_features = n_in_features final_feature_num = num_in_features for stage_idx in range(self.num_stages): output_features = self.block_inplanes[stage_idx] layer_map_dict['Stage%02d_PreConv'%(stage_idx+1)] = ConvBlock(negative_slope=self.negative_slope,norm_choice=self.norm_choice,num_in_features=num_in_features, num_out_features=output_features,kernel_size=3) for repeat_idx in range(self.repeat_time_list[stage_idx]): layer_map_dict['Stage%02d_InnerConvBlock%02d'%(stage_idx+1,repeat_idx+1)] = self._make_layer(output_features) if self.dropout_rate>0: layer_map_dict['Stage%02d_Dropout'%(stage_idx+1)] = nn.Dropout3d(p=self.dropout_rate) if self.pooling_ratios[stage_idx]>1: layer_map_dict['Stage%02d_MP'%(stage_idx+1)] = nn.MaxPool3d(kernel_size=self.pooling_ratios[stage_idx]) final_feature_num = output_features num_in_features = output_features self.dark_layer_func = nn.Sequential(OrderedDict([(key,layer_map_dict[key]) for key in layer_map_dict.keys()])) self.avgpool = nn.AdaptiveAvgPool3d((1, 1, 1)) self.fc0 = nn.Linear(final_feature_num,int(final_feature_num/4)) self.dp0 = nn.Dropout3d(p=0.5) self.fc = nn.Linear(int(final_feature_num/4),self.num_class) def _make_layer(self,num_in_features): ''' Generate structures like input-conv1*1-conv3*3-shortcut ''' func = DarknetLayer(negative_slope = self.negative_slope,norm_choice = self.norm_choice,kernel_size=self.kernel_size, conv_choice = self.conv_choice,num_in_features = num_in_features) return func def forward(self,x): x = self.dark_layer_func(x) x = self.avgpool(x) x = x.view(x.size(0), -1) x = self.fc0(x) x = self.dp0(x) x = self.fc(x) return x