4@contact: sherlockliao01@gmail.com
17from .build
import BACKBONE_REGISTRY
19logger = logging.getLogger(__name__)
22 'https://drive.google.com/uc?id=1LaG1EJpHrxdAxKnSCJ_i0u-nbxSAeiFY',
24 'https://drive.google.com/uc?id=1uwA9fElHOk3ZogwbeY5GkLI6QPTX70Hq',
26 'https://drive.google.com/uc?id=16DGLbZukvVYgINws8u8deSaOqjybZ83i',
28 'https://drive.google.com/uc?id=1rb8UN5ZzPKRc_xvtHlyDh-cSz88YX9hs',
30 'https://drive.google.com/uc?id=1sr90V6irlYYDd4_4ISU2iruoRG8J__6l'
38 """Convolution layer (conv + bn + relu)."""
62 self.
bn = nn.InstanceNorm2d(out_channels, affine=
True)
64 self.
bn = get_norm(bn_norm, out_channels)
65 self.
relu = nn.ReLU(inplace=
True)
75 """1x1 convolution + bn + relu."""
77 def __init__(self, in_channels, out_channels, bn_norm, stride=1, groups=1):
88 self.
bn = get_norm(bn_norm, out_channels)
89 self.
relu = nn.ReLU(inplace=
True)
99 """1x1 convolution + bn (w/o non-linearity)."""
101 def __init__(self, in_channels, out_channels, bn_norm, stride=1):
102 super(Conv1x1Linear, self).
__init__()
104 in_channels, out_channels, 1, stride=stride, padding=0, bias=
False
106 self.
bn = get_norm(bn_norm, out_channels)
115 """3x3 convolution + bn + relu."""
117 def __init__(self, in_channels, out_channels, bn_norm, stride=1, groups=1):
128 self.
bn = get_norm(bn_norm, out_channels)
129 self.
relu = nn.ReLU(inplace=
True)
139 """Lightweight 3x3 convolution.
140 1x1 (linear) + dw 3x3 (nonlinear).
143 def __init__(self, in_channels, out_channels, bn_norm):
144 super(LightConv3x3, self).
__init__()
146 in_channels, out_channels, 1, stride=1, padding=0, bias=
False
157 self.
bn = get_norm(bn_norm, out_channels)
158 self.
relu = nn.ReLU(inplace=
True)
172 """A mini-network that generates channel-wise gates conditioned on input tensor."""
179 gate_activation='sigmoid',
184 if num_gates
is None: num_gates = in_channels
191 in_channels // reduction,
197 if layer_norm: self.
norm1 = nn.LayerNorm((in_channels // reduction, 1, 1))
198 self.
relu = nn.ReLU(inplace=
True)
200 in_channels // reduction,
206 if gate_activation ==
'sigmoid':
208 elif gate_activation ==
'relu':
210 elif gate_activation ==
'linear':
214 "Unknown gate activation: {}".format(gate_activation)
230 """Omni-scale feature learning block."""
238 bottleneck_reduction=4,
242 mid_channels = out_channels // bottleneck_reduction
263 if in_channels != out_channels:
266 if IN: self.
IN = nn.InstanceNorm2d(out_channels, affine=
True)
281 if self.
IN is not None:
283 return self.
relu(out)
290 """Omni-Scale Network.
293 - Zhou et al. Omni-Scale Feature Learning for Person Re-Identification. ICCV, 2019.
294 - Zhou et al. Learning Generalisable Omni-Scale Representations
295 for Person Re-Identification. arXiv preprint, 2019.
308 num_blocks = len(blocks)
309 assert num_blocks == len(layers)
310 assert num_blocks == len(channels) - 1
314 self.
maxpool = nn.MaxPool2d(3, stride=2, padding=1)
321 reduce_spatial_size=
True,
330 reduce_spatial_size=
True
338 reduce_spatial_size=
False
356 layers.append(block(in_channels, out_channels, bn_norm, IN=IN))
357 for i
in range(1, layer):
358 layers.append(block(out_channels, out_channels, bn_norm, IN=IN))
360 if reduce_spatial_size:
363 Conv1x1(out_channels, out_channels, bn_norm),
364 nn.AvgPool2d(2, stride=2),
368 return nn.Sequential(*layers)
371 for m
in self.modules():
372 if isinstance(m, nn.Conv2d):
373 nn.init.kaiming_normal_(
374 m.weight, mode=
'fan_out', nonlinearity=
'relu'
376 if m.bias
is not None:
377 nn.init.constant_(m.bias, 0)
379 elif isinstance(m, nn.BatchNorm2d):
380 nn.init.constant_(m.weight, 1)
381 nn.init.constant_(m.bias, 0)
383 elif isinstance(m, nn.BatchNorm1d):
384 nn.init.constant_(m.weight, 1)
385 nn.init.constant_(m.bias, 0)
387 elif isinstance(m, nn.Linear):
388 nn.init.normal_(m.weight, 0, 0.01)
389 if m.bias
is not None:
390 nn.init.constant_(m.bias, 0)
403 """Initializes model with pretrained weights.
405 Layers that don't match with pretrained layers in name or size are kept unchanged.
410 from collections
import OrderedDict
414 logger = logging.getLogger(__name__)
416 def _get_torch_home():
417 ENV_TORCH_HOME =
'TORCH_HOME'
418 ENV_XDG_CACHE_HOME =
'XDG_CACHE_HOME'
419 DEFAULT_CACHE_DIR =
'~/.cache'
420 torch_home = os.path.expanduser(
424 os.getenv(ENV_XDG_CACHE_HOME, DEFAULT_CACHE_DIR),
'torch'
430 torch_home = _get_torch_home()
431 model_dir = os.path.join(torch_home,
'checkpoints')
433 os.makedirs(model_dir)
435 if e.errno == errno.EEXIST:
441 filename = key +
'_imagenet.pth'
442 cached_file = os.path.join(model_dir, filename)
444 if not os.path.exists(cached_file):
445 if comm.is_main_process():
446 gdown.download(model_urls[key], cached_file, quiet=
False)
450 state_dict = torch.load(cached_file, map_location=torch.device(
'cpu'))
451 model_dict = model.state_dict()
452 new_state_dict = OrderedDict()
453 matched_layers, discarded_layers = [], []
455 for k, v
in state_dict.items():
456 if k.startswith(
'module.'):
459 if k
in model_dict
and model_dict[k].size() == v.size():
460 new_state_dict[k] = v
461 matched_layers.append(k)
463 discarded_layers.append(k)
465 model_dict.update(new_state_dict)
466 model.load_state_dict(model_dict)
468 if len(matched_layers) == 0:
470 'The pretrained weights from "{}" cannot be loaded, '
471 'please check the key names manually '
472 '(** ignored and continue **)'.format(cached_file)
476 'Successfully loaded imagenet pretrained weights from "{}"'.format(cached_file)
478 if len(discarded_layers) > 0:
480 '** The following layers are discarded '
481 'due to unmatched keys or layer size: {}'.format(discarded_layers)
485@BACKBONE_REGISTRY.register()
488 Create a OSNet instance from config.
490 OSNet: a :class:`OSNet` instance
494 pretrain = cfg.MODEL.BACKBONE.PRETRAIN
495 pretrain_path = cfg.MODEL.BACKBONE.PRETRAIN_PATH
496 with_ibn = cfg.MODEL.BACKBONE.WITH_IBN
497 bn_norm = cfg.MODEL.BACKBONE.NORM
498 depth = cfg.MODEL.BACKBONE.DEPTH
501 num_blocks_per_stage = [2, 2, 2]
502 num_channels_per_stage = {
503 "x1_0": [64, 256, 384, 512],
504 "x0_75": [48, 192, 288, 384],
505 "x0_5": [32, 128, 192, 256],
506 "x0_25": [16, 64, 96, 128]}[depth]
507 model =
OSNet([OSBlock, OSBlock, OSBlock], num_blocks_per_stage, num_channels_per_stage,
508 bn_norm, IN=with_ibn)
514 state_dict = torch.load(pretrain_path, map_location=torch.device(
'cpu'))
515 logger.info(f
"Loading pretrained model from {pretrain_path}")
516 model.load_state_dict(state_dict)
517 except FileNotFoundError
as e:
518 logger.info(f
'{pretrain_path} is not found! Please check this path.')
520 except KeyError
as e:
521 logger.info(
"State dict keys error! Please check the state dict.")
525 pretrain_key =
"osnet_ibn_" + depth
527 pretrain_key =
"osnet_" + depth
__init__(self, in_channels, num_gates=None, return_gates=False, gate_activation='sigmoid', reduction=16, layer_norm=False)
__init__(self, in_channels, out_channels, bn_norm, stride=1, groups=1)
__init__(self, in_channels, out_channels, bn_norm, stride=1)
__init__(self, in_channels, out_channels, bn_norm, stride=1, groups=1)
__init__(self, in_channels, out_channels, kernel_size, bn_norm, stride=1, padding=0, groups=1, IN=False)
__init__(self, in_channels, out_channels, bn_norm)
__init__(self, in_channels, out_channels, bn_norm, IN=False, bottleneck_reduction=4, **kwargs)
_make_layer(self, block, layer, in_channels, out_channels, bn_norm, reduce_spatial_size, IN=False)
__init__(self, blocks, layers, channels, bn_norm, IN=False, **kwargs)
init_pretrained_weights(model, key='')
build_osnet_backbone(cfg)