1
1
"""PyTorch ResNet
2
-
3
2
This started as a copy of https://github.com/pytorch/vision 'resnet.py' (BSD-3-Clause) with
4
3
additional dropout and dynamic global avg/max pool.
5
-
6
4
ResNeXt, SE-ResNeXt, SENet, and MXNet Gluon stem/downsample variants, tiered stems added by Ross Wightman
7
5
Copyright 2020 Ross Wightman
8
6
"""
@@ -442,7 +440,7 @@ def drop_blocks(drop_block_rate=0.):
442
440
443
441
def make_blocks (
444
442
block_fn , channels , block_repeats , inplanes , reduce_first = 1 , output_stride = 32 ,
445
- down_kernel_size = 1 , avg_down = False , drop_block_rate = 0. , drop_path_rate = 0. , first_conv_stride = 1 , ** kwargs ):
443
+ down_kernel_size = 1 , avg_down = False , drop_block_rate = 0. , drop_path_rate = 0. , ** kwargs ):
446
444
stages = []
447
445
feature_info = []
448
446
net_num_blocks = sum (block_repeats )
@@ -451,7 +449,7 @@ def make_blocks(
451
449
dilation = prev_dilation = 1
452
450
for stage_idx , (planes , num_blocks , db ) in enumerate (zip (channels , block_repeats , drop_blocks (drop_block_rate ))):
453
451
stage_name = f'layer{ stage_idx + 1 } ' # never liked this name, but weight compat requires it
454
- stride = first_conv_stride if stage_idx == 0 else 2
452
+ stride = 1 if stage_idx == 0 else 2
455
453
if net_stride >= output_stride :
456
454
dilation *= stride
457
455
stride = 1
@@ -494,7 +492,7 @@ class ResNet(nn.Module):
494
492
This ResNet impl supports a number of stem and downsample options based on the v1c, v1d, v1e, and v1s
495
493
variants included in the MXNet Gluon ResNetV1b model. The C and D variants are also discussed in the
496
494
'Bag of Tricks' paper: https://arxiv.org/pdf/1812.01187. The B variant is equivalent to torchvision default.
497
-
495
+
498
496
ResNet variants (the same modifications can be used in SE/ResNeXt models as well):
499
497
* normal, b - 7x7 stem, stem_width = 64, same as torchvision ResNet, NVIDIA ResNet 'v1.5', Gluon v1b
500
498
* c - 3 layer deep 3x3 stem, stem_width = 32 (32, 32, 64)
@@ -503,18 +501,18 @@ class ResNet(nn.Module):
503
501
* s - 3 layer deep 3x3 stem, stem_width = 64 (64, 64, 128)
504
502
* t - 3 layer deep 3x3 stem, stem width = 32 (24, 48, 64), average pool in downsample
505
503
* tn - 3 layer deep 3x3 stem, stem width = 32 (24, 32, 64), average pool in downsample
506
-
504
+
507
505
ResNeXt
508
506
* normal - 7x7 stem, stem_width = 64, standard cardinality and base widths
509
507
* same c,d, e, s variants as ResNet can be enabled
510
-
508
+
511
509
SE-ResNeXt
512
510
* normal - 7x7 stem, stem_width = 64
513
511
* same c, d, e, s variants as ResNet can be enabled
514
-
512
+
515
513
SENet-154 - 3 layer deep 3x3 stem (same as v1c-v1s), stem_width = 64, cardinality=64,
516
514
reduction by 2 on width of first bottleneck convolution, 3x3 downsample convs after first block
517
-
515
+
518
516
Parameters
519
517
----------
520
518
block : Block
@@ -558,12 +556,12 @@ def __init__(self, block, layers, num_classes=1000, in_chans=3,
558
556
cardinality = 1 , base_width = 64 , stem_width = 64 , stem_type = '' ,
559
557
output_stride = 32 , block_reduce_first = 1 , down_kernel_size = 1 , avg_down = False ,
560
558
act_layer = nn .ReLU , norm_layer = nn .BatchNorm2d , aa_layer = None , drop_rate = 0.0 , drop_path_rate = 0. ,
561
- drop_block_rate = 0. , global_pool = 'avg' , zero_init_last_bn = True , block_args = None , skip_stem_max_pool = False ):
559
+ drop_block_rate = 0. , global_pool = 'avg' , zero_init_last_bn = True , block_args = None , replace_stem_max_pool = False ):
562
560
block_args = block_args or dict ()
563
561
assert output_stride in (8 , 16 , 32 )
564
562
self .num_classes = num_classes
565
563
self .drop_rate = drop_rate
566
- self .skip_stem_max_pool = skip_stem_max_pool
564
+ self .replace_stem_max_pool = replace_stem_max_pool
567
565
super (ResNet , self ).__init__ ()
568
566
569
567
# Stem
@@ -588,25 +586,27 @@ def __init__(self, block, layers, num_classes=1000, in_chans=3,
588
586
self .feature_info = [dict (num_chs = inplanes , reduction = 2 , module = 'act1' )]
589
587
590
588
# Stem Pooling
591
- if not self .skip_stem_max_pool :
592
- first_conv_stride = 1
589
+ if not self .replace_stem_max_pool :
593
590
if aa_layer is not None :
594
591
self .maxpool = nn .Sequential (* [
595
592
nn .MaxPool2d (kernel_size = 3 , stride = 1 , padding = 1 ),
596
593
aa_layer (channels = inplanes , stride = 2 )])
597
594
else :
598
595
self .maxpool = nn .MaxPool2d (kernel_size = 3 , stride = 2 , padding = 1 )
599
596
else :
600
- self .maxpool = nn .Identity ()
601
- first_conv_stride = 2
597
+ self .maxpool = nn .Sequential (* [
598
+ nn .Conv2d (inplanes , inplanes , 3 , stride = 2 , padding = 1 ),
599
+ nn .BatchNorm2d (inplanes ),
600
+ nn .ReLU ()
601
+ ])
602
602
603
603
# Feature Blocks
604
604
channels = [64 , 128 , 256 , 512 ]
605
605
stage_modules , stage_feature_info = make_blocks (
606
606
block , channels , layers , inplanes , cardinality = cardinality , base_width = base_width ,
607
607
output_stride = output_stride , reduce_first = block_reduce_first , avg_down = avg_down ,
608
608
down_kernel_size = down_kernel_size , act_layer = act_layer , norm_layer = norm_layer , aa_layer = aa_layer ,
609
- drop_block_rate = drop_block_rate , drop_path_rate = drop_path_rate , first_conv_stride = first_conv_stride , ** block_args )
609
+ drop_block_rate = drop_block_rate , drop_path_rate = drop_path_rate , ** block_args )
610
610
for stage in stage_modules :
611
611
self .add_module (* stage ) # layer1, layer2, etc
612
612
self .feature_info .extend (stage_feature_info )
@@ -1078,39 +1078,39 @@ def ecaresnet50d(pretrained=False, **kwargs):
1078
1078
@register_model
1079
1079
def resnetrs50 (pretrained = False , ** kwargs ):
1080
1080
model_args = dict (
1081
- block = Bottleneck , layers = [3 , 4 , 6 , 3 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1081
+ block = Bottleneck , layers = [3 , 4 , 6 , 3 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1082
1082
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1083
1083
return _create_resnet ('resnetrs50' , pretrained , ** model_args )
1084
1084
1085
1085
1086
1086
@register_model
1087
1087
def resnetrs101 (pretrained = False , ** kwargs ):
1088
1088
model_args = dict (
1089
- block = Bottleneck , layers = [3 , 4 , 23 , 3 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1089
+ block = Bottleneck , layers = [3 , 4 , 23 , 3 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1090
1090
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1091
1091
return _create_resnet ('resnetrs101' , pretrained , ** model_args )
1092
1092
1093
1093
1094
1094
@register_model
1095
1095
def resnetrs152 (pretrained = False , ** kwargs ):
1096
1096
model_args = dict (
1097
- block = Bottleneck , layers = [3 , 8 , 36 , 3 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1097
+ block = Bottleneck , layers = [3 , 8 , 36 , 3 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1098
1098
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1099
1099
return _create_resnet ('resnetrs152' , pretrained , ** model_args )
1100
1100
1101
1101
1102
1102
@register_model
1103
1103
def resnetrs200 (pretrained = False , ** kwargs ):
1104
1104
model_args = dict (
1105
- block = Bottleneck , layers = [3 , 24 , 36 , 3 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1105
+ block = Bottleneck , layers = [3 , 24 , 36 , 3 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1106
1106
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1107
1107
return _create_resnet ('resnetrs200' , pretrained , ** model_args )
1108
1108
1109
1109
1110
1110
@register_model
1111
1111
def resnetrs270 (pretrained = False , ** kwargs ):
1112
1112
model_args = dict (
1113
- block = Bottleneck , layers = [4 , 29 , 53 , 4 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1113
+ block = Bottleneck , layers = [4 , 29 , 53 , 4 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1114
1114
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1115
1115
return _create_resnet ('resnetrs270' , pretrained , ** model_args )
1116
1116
@@ -1119,15 +1119,15 @@ def resnetrs270(pretrained=False, **kwargs):
1119
1119
@register_model
1120
1120
def resnetrs350 (pretrained = False , ** kwargs ):
1121
1121
model_args = dict (
1122
- block = Bottleneck , layers = [4 , 36 , 72 , 4 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1122
+ block = Bottleneck , layers = [4 , 36 , 72 , 4 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1123
1123
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1124
1124
return _create_resnet ('resnetrs350' , pretrained , ** model_args )
1125
1125
1126
1126
1127
1127
@register_model
1128
1128
def resnetrs420 (pretrained = False , ** kwargs ):
1129
1129
model_args = dict (
1130
- block = Bottleneck , layers = [4 , 44 , 87 , 4 ], stem_width = 32 , stem_type = 'deep' , skip_stem_max_pool = True ,
1130
+ block = Bottleneck , layers = [4 , 44 , 87 , 4 ], stem_width = 32 , stem_type = 'deep' , replace_stem_max_pool = True ,
1131
1131
avg_down = True , block_args = dict (attn_layer = 'se' ), ** kwargs )
1132
1132
return _create_resnet ('resnetrs420' , pretrained , ** model_args )
1133
1133
@@ -1373,4 +1373,4 @@ def senet154(pretrained=False, **kwargs):
1373
1373
model_args = dict (
1374
1374
block = Bottleneck , layers = [3 , 8 , 36 , 3 ], cardinality = 64 , base_width = 4 , stem_type = 'deep' ,
1375
1375
down_kernel_size = 3 , block_reduce_first = 2 , block_args = dict (attn_layer = 'se' ), ** kwargs )
1376
- return _create_resnet ('senet154' , pretrained , ** model_args )
1376
+ return _create_resnet ('senet154' , pretrained , ** model_args )
0 commit comments