15
15
16
16
from timm .data import IMAGENET_DEFAULT_MEAN , IMAGENET_DEFAULT_STD
17
17
from .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
19
19
from .registry import register_model
20
20
21
21
@@ -56,10 +56,10 @@ def make_divisible(v, divisor=8, min_value=None):
56
56
57
57
class SEWithNorm (nn .Module ):
58
58
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 ,
60
60
gate_layer = 'sigmoid' ):
61
61
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 )
63
63
self .fc1 = nn .Conv2d (channels , reduction_channels , kernel_size = 1 , bias = True )
64
64
self .bn = nn .BatchNorm2d (reduction_channels )
65
65
self .act = act_layer (inplace = True )
@@ -76,7 +76,7 @@ def forward(self, x):
76
76
77
77
78
78
class 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 ):
80
80
super (LinearBottleneck , self ).__init__ ()
81
81
self .use_shortcut = stride == 1 and in_chs <= out_chs
82
82
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
90
90
self .conv_exp = None
91
91
92
92
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
94
94
self .act_dw = nn .ReLU6 ()
95
95
96
96
self .conv_pwl = ConvBnAct (dw_chs , out_chs , 1 , apply_act = False )
97
+ self .drop_path = drop_path
97
98
98
99
def feat_channels (self , exp = False ):
99
100
return self .conv_dw .out_channels if exp else self .out_channels
@@ -107,12 +108,14 @@ def forward(self, x):
107
108
x = self .se (x )
108
109
x = self .act_dw (x )
109
110
x = self .conv_pwl (x )
111
+ if self .drop_path is not None :
112
+ x = self .drop_path (x )
110
113
if self .use_shortcut :
111
114
x [:, 0 :self .in_channels ] += shortcut
112
115
return x
113
116
114
117
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 ):
116
119
layers = [1 , 2 , 2 , 3 , 3 , 5 ]
117
120
strides = [1 , 2 , 2 , 2 , 1 , 2 ]
118
121
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
127
130
out_chs_list .append (make_divisible (round (base_chs * width_mult ), divisor = ch_div ))
128
131
base_chs += final_chs / (depth // 3 * 1.0 )
129
132
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 :])
134
134
135
- return zip (out_chs_list , exp_ratios , strides , use_ses )
135
+ return list ( zip (out_chs_list , exp_ratios , strides , se_ratios ) )
136
136
137
137
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' ):
139
140
feat_exp = feature_location == 'expansion'
140
141
feat_chs = [prev_chs ]
141
142
feature_info = []
142
143
curr_stride = 2
143
144
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 ):
145
147
if stride > 1 :
146
148
fname = 'stem' if block_idx == 0 else f'features.{ block_idx - 1 } '
147
149
if block_idx > 0 and feat_exp :
148
150
fname += '.act_dw'
149
151
feature_info += [dict (num_chs = feat_chs [- 1 ], reduction = curr_stride , module = fname )]
150
152
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
151
155
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 ))
153
158
prev_chs = chs
154
159
feat_chs += [features [- 1 ].feat_channels (feat_exp )]
155
160
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
162
167
163
168
class ReXNetV1 (nn .Module ):
164
169
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' ):
167
172
super (ReXNetV1 , self ).__init__ ()
168
173
self .drop_rate = drop_rate
169
174
self .num_classes = num_classes
@@ -173,9 +178,9 @@ def __init__(self, in_chans=3, num_classes=1000, global_pool='avg', output_strid
173
178
stem_chs = make_divisible (round (stem_base_chs * width_mult ), divisor = ch_div )
174
179
self .stem = ConvBnAct (in_chans , stem_chs , 3 , stride = 2 , act_layer = 'swish' )
175
180
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 )
177
182
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 )
179
184
self .num_features = features [- 1 ].out_channels
180
185
self .features = nn .Sequential (* features )
181
186
0 commit comments