1515
1616from timm .data import IMAGENET_DEFAULT_MEAN , IMAGENET_DEFAULT_STD
1717from .helpers import build_model_with_cfg
18- from .layers import ClassifierHead , create_act_layer , ConvBnAct
18+ from .layers import ClassifierHead , create_act_layer , ConvBnAct , DropPath
1919from .registry import register_model
2020
2121
@@ -56,10 +56,10 @@ def make_divisible(v, divisor=8, min_value=None):
5656
5757class SEWithNorm (nn .Module ):
5858
59- def __init__ (self , channels , reduction = 16 , act_layer = nn .ReLU , divisor = 1 , reduction_channels = None ,
59+ def __init__ (self , channels , se_ratio = 1 / 12. , act_layer = nn .ReLU , divisor = 1 , reduction_channels = None ,
6060 gate_layer = 'sigmoid' ):
6161 super (SEWithNorm , self ).__init__ ()
62- reduction_channels = reduction_channels or make_divisible (channels // reduction , divisor = divisor )
62+ reduction_channels = reduction_channels or make_divisible (int ( channels * se_ratio ) , divisor = divisor )
6363 self .fc1 = nn .Conv2d (channels , reduction_channels , kernel_size = 1 , bias = True )
6464 self .bn = nn .BatchNorm2d (reduction_channels )
6565 self .act = act_layer (inplace = True )
@@ -76,7 +76,7 @@ def forward(self, x):
7676
7777
7878class LinearBottleneck (nn .Module ):
79- def __init__ (self , in_chs , out_chs , stride , exp_ratio = 1.0 , use_se = True , se_rd = 12 , ch_div = 1 ):
79+ def __init__ (self , in_chs , out_chs , stride , exp_ratio = 1.0 , se_ratio = 0. , ch_div = 1 , drop_path = None ):
8080 super (LinearBottleneck , self ).__init__ ()
8181 self .use_shortcut = stride == 1 and in_chs <= out_chs
8282 self .in_channels = in_chs
@@ -90,10 +90,11 @@ def __init__(self, in_chs, out_chs, stride, exp_ratio=1.0, use_se=True, se_rd=12
9090 self .conv_exp = None
9191
9292 self .conv_dw = ConvBnAct (dw_chs , dw_chs , 3 , stride = stride , groups = dw_chs , apply_act = False )
93- self .se = SEWithNorm (dw_chs , reduction = se_rd , divisor = ch_div ) if use_se else None
93+ self .se = SEWithNorm (dw_chs , se_ratio = se_ratio , divisor = ch_div ) if se_ratio > 0. else None
9494 self .act_dw = nn .ReLU6 ()
9595
9696 self .conv_pwl = ConvBnAct (dw_chs , out_chs , 1 , apply_act = False )
97+ self .drop_path = drop_path
9798
9899 def feat_channels (self , exp = False ):
99100 return self .conv_dw .out_channels if exp else self .out_channels
@@ -107,12 +108,14 @@ def forward(self, x):
107108 x = self .se (x )
108109 x = self .act_dw (x )
109110 x = self .conv_pwl (x )
111+ if self .drop_path is not None :
112+ x = self .drop_path (x )
110113 if self .use_shortcut :
111114 x [:, 0 :self .in_channels ] += shortcut
112115 return x
113116
114117
115- def _block_cfg (width_mult = 1.0 , depth_mult = 1.0 , initial_chs = 16 , final_chs = 180 , use_se = True , ch_div = 1 ):
118+ def _block_cfg (width_mult = 1.0 , depth_mult = 1.0 , initial_chs = 16 , final_chs = 180 , se_ratio = 0. , ch_div = 1 ):
116119 layers = [1 , 2 , 2 , 3 , 3 , 5 ]
117120 strides = [1 , 2 , 2 , 2 , 1 , 2 ]
118121 layers = [ceil (element * depth_mult ) for element in layers ]
@@ -127,29 +130,31 @@ def _block_cfg(width_mult=1.0, depth_mult=1.0, initial_chs=16, final_chs=180, us
127130 out_chs_list .append (make_divisible (round (base_chs * width_mult ), divisor = ch_div ))
128131 base_chs += final_chs / (depth // 3 * 1.0 )
129132
130- if use_se :
131- use_ses = [False ] * (layers [0 ] + layers [1 ]) + [True ] * sum (layers [2 :])
132- else :
133- use_ses = [False ] * sum (layers [:])
133+ se_ratios = [0. ] * (layers [0 ] + layers [1 ]) + [se_ratio ] * sum (layers [2 :])
134134
135- return zip (out_chs_list , exp_ratios , strides , use_ses )
135+ return list ( zip (out_chs_list , exp_ratios , strides , se_ratios ) )
136136
137137
138- def _build_blocks (block_cfg , prev_chs , width_mult , se_rd = 12 , ch_div = 1 , feature_location = 'bottleneck' ):
138+ def _build_blocks (
139+ block_cfg , prev_chs , width_mult , ch_div = 1 , drop_path_rate = 0. , feature_location = 'bottleneck' ):
139140 feat_exp = feature_location == 'expansion'
140141 feat_chs = [prev_chs ]
141142 feature_info = []
142143 curr_stride = 2
143144 features = []
144- for block_idx , (chs , exp_ratio , stride , se ) in enumerate (block_cfg ):
145+ num_blocks = len (block_cfg )
146+ for block_idx , (chs , exp_ratio , stride , se_ratio ) in enumerate (block_cfg ):
145147 if stride > 1 :
146148 fname = 'stem' if block_idx == 0 else f'features.{ block_idx - 1 } '
147149 if block_idx > 0 and feat_exp :
148150 fname += '.act_dw'
149151 feature_info += [dict (num_chs = feat_chs [- 1 ], reduction = curr_stride , module = fname )]
150152 curr_stride *= stride
153+ block_dpr = drop_path_rate * block_idx / (num_blocks - 1 ) # stochastic depth linear decay rule
154+ drop_path = DropPath (block_dpr ) if block_dpr > 0. else None
151155 features .append (LinearBottleneck (
152- in_chs = prev_chs , out_chs = chs , exp_ratio = exp_ratio , stride = stride , use_se = se , se_rd = se_rd , ch_div = ch_div ))
156+ in_chs = prev_chs , out_chs = chs , exp_ratio = exp_ratio , stride = stride , se_ratio = se_ratio ,
157+ ch_div = ch_div , drop_path = drop_path ))
153158 prev_chs = chs
154159 feat_chs += [features [- 1 ].feat_channels (feat_exp )]
155160 pen_chs = make_divisible (1280 * width_mult , divisor = ch_div )
@@ -162,8 +167,8 @@ def _build_blocks(block_cfg, prev_chs, width_mult, se_rd=12, ch_div=1, feature_l
162167
163168class ReXNetV1 (nn .Module ):
164169 def __init__ (self , in_chans = 3 , num_classes = 1000 , global_pool = 'avg' , output_stride = 32 ,
165- initial_chs = 16 , final_chs = 180 , width_mult = 1.0 , depth_mult = 1.0 , use_se = True ,
166- se_rd = 12 , ch_div = 1 , drop_rate = 0.2 , feature_location = 'bottleneck' ):
170+ initial_chs = 16 , final_chs = 180 , width_mult = 1.0 , depth_mult = 1.0 , se_ratio = 1 / 12. ,
171+ ch_div = 1 , drop_rate = 0.2 , drop_path_rate = 0. , feature_location = 'bottleneck' ):
167172 super (ReXNetV1 , self ).__init__ ()
168173 self .drop_rate = drop_rate
169174 self .num_classes = num_classes
@@ -173,9 +178,9 @@ def __init__(self, in_chans=3, num_classes=1000, global_pool='avg', output_strid
173178 stem_chs = make_divisible (round (stem_base_chs * width_mult ), divisor = ch_div )
174179 self .stem = ConvBnAct (in_chans , stem_chs , 3 , stride = 2 , act_layer = 'swish' )
175180
176- block_cfg = _block_cfg (width_mult , depth_mult , initial_chs , final_chs , use_se , ch_div )
181+ block_cfg = _block_cfg (width_mult , depth_mult , initial_chs , final_chs , se_ratio , ch_div )
177182 features , self .feature_info = _build_blocks (
178- block_cfg , stem_chs , width_mult , se_rd , ch_div , feature_location )
183+ block_cfg , stem_chs , width_mult , ch_div , drop_path_rate , feature_location )
179184 self .num_features = features [- 1 ].out_channels
180185 self .features = nn .Sequential (* features )
181186
0 commit comments