resnetv2.py 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. """Pre-Activation ResNet v2 with GroupNorm and Weight Standardization.
  2. A PyTorch implementation of ResNetV2 adapted from the Google Big-Transfer (BiT) source code
  3. at https://github.com/google-research/big_transfer to match timm interfaces. The BiT weights have
  4. been included here as pretrained models from their original .NPZ checkpoints.
  5. Additionally, supports non pre-activation bottleneck for use as a backbone for Vision Transformers (ViT) and
  6. extra padding support to allow porting of official Hybrid ResNet pretrained weights from
  7. https://github.com/google-research/vision_transformer
  8. Thanks to the Google team for the above two repositories and associated papers:
  9. * Big Transfer (BiT): General Visual Representation Learning - https://arxiv.org/abs/1912.11370
  10. * An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale - https://arxiv.org/abs/2010.11929
  11. * Knowledge distillation: A good teacher is patient and consistent - https://arxiv.org/abs/2106.05237
  12. Original copyright of Google code below, modifications by Ross Wightman, Copyright 2020.
  13. """
  14. # Copyright 2020 Google LLC
  15. #
  16. # Licensed under the Apache License, Version 2.0 (the "License");
  17. # you may not use this file except in compliance with the License.
  18. # You may obtain a copy of the License at
  19. #
  20. # http://www.apache.org/licenses/LICENSE-2.0
  21. #
  22. # Unless required by applicable law or agreed to in writing, software
  23. # distributed under the License is distributed on an "AS IS" BASIS,
  24. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. # See the License for the specific language governing permissions and
  26. # limitations under the License.
  27. from collections import OrderedDict # pylint: disable=g-importing-member
  28. from functools import partial
  29. from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  30. import torch
  31. import torch.nn as nn
  32. from timm.data import IMAGENET_INCEPTION_MEAN, IMAGENET_INCEPTION_STD
  33. from timm.layers import GroupNormAct, BatchNormAct2d, EvoNorm2dS0, FilterResponseNormTlu2d, ClassifierHead, \
  34. DropPath, calculate_drop_path_rates, AvgPool2dSame, create_pool2d, StdConv2d, create_conv2d, get_act_layer, get_norm_act_layer, make_divisible
  35. from ._builder import build_model_with_cfg
  36. from ._features import feature_take_indices
  37. from ._manipulate import checkpoint_seq, named_apply, adapt_input_conv
  38. from ._registry import generate_default_cfgs, register_model, register_model_deprecations
  39. __all__ = ['ResNetV2'] # model_registry will add each entrypoint fn to this
  40. class PreActBasic(nn.Module):
  41. """Pre-activation basic block (not in typical 'v2' implementations)."""
  42. def __init__(
  43. self,
  44. in_chs: int,
  45. out_chs: Optional[int] = None,
  46. bottle_ratio: float = 1.0,
  47. stride: int = 1,
  48. dilation: int = 1,
  49. first_dilation: Optional[int] = None,
  50. groups: int = 1,
  51. act_layer: Optional[Callable] = None,
  52. conv_layer: Optional[Callable] = None,
  53. norm_layer: Optional[Callable] = None,
  54. proj_layer: Optional[Callable] = None,
  55. drop_path_rate: float = 0.,
  56. device=None,
  57. dtype=None,
  58. ):
  59. """Initialize PreActBasic block.
  60. Args:
  61. in_chs: Input channels.
  62. out_chs: Output channels.
  63. bottle_ratio: Bottleneck ratio (not used in basic block).
  64. stride: Stride for convolution.
  65. dilation: Dilation rate.
  66. first_dilation: First dilation rate.
  67. groups: Group convolution size.
  68. act_layer: Activation layer type.
  69. conv_layer: Convolution layer type.
  70. norm_layer: Normalization layer type.
  71. proj_layer: Projection/downsampling layer type.
  72. drop_path_rate: Stochastic depth drop rate.
  73. """
  74. dd = {'device': device, 'dtype': dtype}
  75. super().__init__()
  76. first_dilation = first_dilation or dilation
  77. conv_layer = conv_layer or StdConv2d
  78. norm_layer = norm_layer or partial(GroupNormAct, num_groups=32)
  79. out_chs = out_chs or in_chs
  80. mid_chs = make_divisible(out_chs * bottle_ratio)
  81. if proj_layer is not None and (stride != 1 or first_dilation != dilation or in_chs != out_chs):
  82. self.downsample = proj_layer(
  83. in_chs,
  84. out_chs,
  85. stride=stride,
  86. dilation=dilation,
  87. first_dilation=first_dilation,
  88. preact=True,
  89. conv_layer=conv_layer,
  90. norm_layer=norm_layer,
  91. **dd,
  92. )
  93. else:
  94. self.downsample = None
  95. self.norm1 = norm_layer(in_chs, **dd)
  96. self.conv1 = conv_layer(in_chs, mid_chs, 3, stride=stride, dilation=first_dilation, groups=groups, **dd)
  97. self.norm2 = norm_layer(mid_chs, **dd)
  98. self.conv2 = conv_layer(mid_chs, out_chs, 3, dilation=dilation, groups=groups, **dd)
  99. self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
  100. def zero_init_last(self) -> None:
  101. """Zero-initialize the last convolution weight (not applicable to basic block)."""
  102. nn.init.zeros_(self.conv2.weight)
  103. def forward(self, x: torch.Tensor) -> torch.Tensor:
  104. """Forward pass.
  105. Args:
  106. x: Input tensor.
  107. Returns:
  108. Output tensor.
  109. """
  110. x_preact = self.norm1(x)
  111. # shortcut branch
  112. shortcut = x
  113. if self.downsample is not None:
  114. shortcut = self.downsample(x_preact)
  115. # residual branch
  116. x = self.conv1(x_preact)
  117. x = self.conv2(self.norm2(x))
  118. x = self.drop_path(x)
  119. return x + shortcut
  120. class PreActBottleneck(nn.Module):
  121. """Pre-activation (v2) bottleneck block.
  122. Follows the implementation of "Identity Mappings in Deep Residual Networks":
  123. https://github.com/KaimingHe/resnet-1k-layers/blob/master/resnet-pre-act.lua
  124. Except it puts the stride on 3x3 conv when available.
  125. """
  126. def __init__(
  127. self,
  128. in_chs: int,
  129. out_chs: Optional[int] = None,
  130. bottle_ratio: float = 0.25,
  131. stride: int = 1,
  132. dilation: int = 1,
  133. first_dilation: Optional[int] = None,
  134. groups: int = 1,
  135. act_layer: Optional[Callable] = None,
  136. conv_layer: Optional[Callable] = None,
  137. norm_layer: Optional[Callable] = None,
  138. proj_layer: Optional[Callable] = None,
  139. drop_path_rate: float = 0.,
  140. device=None,
  141. dtype=None,
  142. ):
  143. """Initialize PreActBottleneck block.
  144. Args:
  145. in_chs: Input channels.
  146. out_chs: Output channels.
  147. bottle_ratio: Bottleneck ratio.
  148. stride: Stride for convolution.
  149. dilation: Dilation rate.
  150. first_dilation: First dilation rate.
  151. groups: Group convolution size.
  152. act_layer: Activation layer type.
  153. conv_layer: Convolution layer type.
  154. norm_layer: Normalization layer type.
  155. proj_layer: Projection/downsampling layer type.
  156. drop_path_rate: Stochastic depth drop rate.
  157. """
  158. dd = {'device': device, 'dtype': dtype}
  159. super().__init__()
  160. first_dilation = first_dilation or dilation
  161. conv_layer = conv_layer or StdConv2d
  162. norm_layer = norm_layer or partial(GroupNormAct, num_groups=32)
  163. out_chs = out_chs or in_chs
  164. mid_chs = make_divisible(out_chs * bottle_ratio)
  165. if proj_layer is not None:
  166. self.downsample = proj_layer(
  167. in_chs,
  168. out_chs,
  169. stride=stride,
  170. dilation=dilation,
  171. first_dilation=first_dilation,
  172. preact=True,
  173. conv_layer=conv_layer,
  174. norm_layer=norm_layer,
  175. **dd,
  176. )
  177. else:
  178. self.downsample = None
  179. self.norm1 = norm_layer(in_chs, **dd)
  180. self.conv1 = conv_layer(in_chs, mid_chs, 1, **dd)
  181. self.norm2 = norm_layer(mid_chs, **dd)
  182. self.conv2 = conv_layer(mid_chs, mid_chs, 3, stride=stride, dilation=first_dilation, groups=groups, **dd)
  183. self.norm3 = norm_layer(mid_chs, **dd)
  184. self.conv3 = conv_layer(mid_chs, out_chs, 1, **dd)
  185. self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
  186. def zero_init_last(self) -> None:
  187. """Zero-initialize the last convolution weight."""
  188. nn.init.zeros_(self.conv3.weight)
  189. def forward(self, x: torch.Tensor) -> torch.Tensor:
  190. """Forward pass.
  191. Args:
  192. x: Input tensor.
  193. Returns:
  194. Output tensor.
  195. """
  196. x_preact = self.norm1(x)
  197. # shortcut branch
  198. shortcut = x
  199. if self.downsample is not None:
  200. shortcut = self.downsample(x_preact)
  201. # residual branch
  202. x = self.conv1(x_preact)
  203. x = self.conv2(self.norm2(x))
  204. x = self.conv3(self.norm3(x))
  205. x = self.drop_path(x)
  206. return x + shortcut
  207. class Bottleneck(nn.Module):
  208. """Non Pre-activation bottleneck block, equiv to V1.5/V1b Bottleneck. Used for ViT.
  209. """
  210. def __init__(
  211. self,
  212. in_chs: int,
  213. out_chs: Optional[int] = None,
  214. bottle_ratio: float = 0.25,
  215. stride: int = 1,
  216. dilation: int = 1,
  217. first_dilation: Optional[int] = None,
  218. groups: int = 1,
  219. act_layer: Optional[Callable] = None,
  220. conv_layer: Optional[Callable] = None,
  221. norm_layer: Optional[Callable] = None,
  222. proj_layer: Optional[Callable] = None,
  223. drop_path_rate: float = 0.,
  224. device=None,
  225. dtype=None,
  226. ):
  227. dd = {'device': device, 'dtype': dtype}
  228. super().__init__()
  229. first_dilation = first_dilation or dilation
  230. act_layer = act_layer or nn.ReLU
  231. conv_layer = conv_layer or StdConv2d
  232. norm_layer = norm_layer or partial(GroupNormAct, num_groups=32)
  233. out_chs = out_chs or in_chs
  234. mid_chs = make_divisible(out_chs * bottle_ratio)
  235. if proj_layer is not None:
  236. self.downsample = proj_layer(
  237. in_chs,
  238. out_chs,
  239. stride=stride,
  240. dilation=dilation,
  241. preact=False,
  242. conv_layer=conv_layer,
  243. norm_layer=norm_layer,
  244. **dd,
  245. )
  246. else:
  247. self.downsample = None
  248. self.conv1 = conv_layer(in_chs, mid_chs, 1, **dd)
  249. self.norm1 = norm_layer(mid_chs, **dd)
  250. self.conv2 = conv_layer(mid_chs, mid_chs, 3, stride=stride, dilation=first_dilation, groups=groups, **dd)
  251. self.norm2 = norm_layer(mid_chs, **dd)
  252. self.conv3 = conv_layer(mid_chs, out_chs, 1, **dd)
  253. self.norm3 = norm_layer(out_chs, apply_act=False, **dd)
  254. self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0 else nn.Identity()
  255. self.act3 = act_layer(inplace=True)
  256. def zero_init_last(self) -> None:
  257. """Zero-initialize the last batch norm weight."""
  258. if getattr(self.norm3, 'weight', None) is not None:
  259. nn.init.zeros_(self.norm3.weight)
  260. def forward(self, x: torch.Tensor) -> torch.Tensor:
  261. """Forward pass.
  262. Args:
  263. x: Input tensor.
  264. Returns:
  265. Output tensor.
  266. """
  267. # shortcut branch
  268. shortcut = x
  269. if self.downsample is not None:
  270. shortcut = self.downsample(x)
  271. # residual
  272. x = self.conv1(x)
  273. x = self.norm1(x)
  274. x = self.conv2(x)
  275. x = self.norm2(x)
  276. x = self.conv3(x)
  277. x = self.norm3(x)
  278. x = self.drop_path(x)
  279. x = self.act3(x + shortcut)
  280. return x
  281. class DownsampleConv(nn.Module):
  282. """1x1 convolution downsampling module."""
  283. def __init__(
  284. self,
  285. in_chs: int,
  286. out_chs: int,
  287. stride: int = 1,
  288. dilation: int = 1,
  289. first_dilation: Optional[int] = None,
  290. preact: bool = True,
  291. conv_layer: Optional[Callable] = None,
  292. norm_layer: Optional[Callable] = None,
  293. device=None,
  294. dtype=None,
  295. ):
  296. dd = {'device': device, 'dtype': dtype}
  297. super().__init__()
  298. self.conv = conv_layer(in_chs, out_chs, 1, stride=stride, **dd)
  299. self.norm = nn.Identity() if preact else norm_layer(out_chs, apply_act=False, **dd)
  300. def forward(self, x: torch.Tensor) -> torch.Tensor:
  301. """Forward pass.
  302. Args:
  303. x: Input tensor.
  304. Returns:
  305. Downsampled tensor.
  306. """
  307. return self.norm(self.conv(x))
  308. class DownsampleAvg(nn.Module):
  309. """AvgPool downsampling as in 'D' ResNet variants."""
  310. def __init__(
  311. self,
  312. in_chs: int,
  313. out_chs: int,
  314. stride: int = 1,
  315. dilation: int = 1,
  316. first_dilation: Optional[int] = None,
  317. preact: bool = True,
  318. conv_layer: Optional[Callable] = None,
  319. norm_layer: Optional[Callable] = None,
  320. device=None,
  321. dtype=None,
  322. ):
  323. dd = {'device': device, 'dtype': dtype}
  324. super().__init__()
  325. avg_stride = stride if dilation == 1 else 1
  326. if stride > 1 or dilation > 1:
  327. avg_pool_fn = AvgPool2dSame if avg_stride == 1 and dilation > 1 else nn.AvgPool2d
  328. self.pool = avg_pool_fn(2, avg_stride, ceil_mode=True, count_include_pad=False)
  329. else:
  330. self.pool = nn.Identity()
  331. self.conv = conv_layer(in_chs, out_chs, 1, stride=1, **dd)
  332. self.norm = nn.Identity() if preact else norm_layer(out_chs, apply_act=False, **dd)
  333. def forward(self, x: torch.Tensor) -> torch.Tensor:
  334. """Forward pass.
  335. Args:
  336. x: Input tensor.
  337. Returns:
  338. Downsampled tensor.
  339. """
  340. return self.norm(self.conv(self.pool(x)))
  341. class ResNetStage(nn.Module):
  342. """ResNet Stage."""
  343. def __init__(
  344. self,
  345. in_chs: int,
  346. out_chs: int,
  347. stride: int,
  348. dilation: int,
  349. depth: int,
  350. bottle_ratio: float = 0.25,
  351. groups: int = 1,
  352. avg_down: bool = False,
  353. block_dpr: Optional[List[float]] = None,
  354. block_fn: Callable = PreActBottleneck,
  355. act_layer: Optional[Callable] = None,
  356. conv_layer: Optional[Callable] = None,
  357. norm_layer: Optional[Callable] = None,
  358. **block_kwargs: Any,
  359. ):
  360. super().__init__()
  361. self.grad_checkpointing = False
  362. first_dilation = 1 if dilation in (1, 2) else 2
  363. layer_kwargs = dict(act_layer=act_layer, conv_layer=conv_layer, norm_layer=norm_layer)
  364. proj_layer = DownsampleAvg if avg_down else DownsampleConv
  365. prev_chs = in_chs
  366. self.blocks = nn.Sequential()
  367. for block_idx in range(depth):
  368. drop_path_rate = block_dpr[block_idx] if block_dpr else 0.
  369. stride = stride if block_idx == 0 else 1
  370. self.blocks.add_module(str(block_idx), block_fn(
  371. prev_chs,
  372. out_chs,
  373. stride=stride,
  374. dilation=dilation,
  375. bottle_ratio=bottle_ratio,
  376. groups=groups,
  377. first_dilation=first_dilation,
  378. proj_layer=proj_layer,
  379. drop_path_rate=drop_path_rate,
  380. **layer_kwargs,
  381. **block_kwargs,
  382. ))
  383. prev_chs = out_chs
  384. first_dilation = dilation
  385. proj_layer = None
  386. def forward(self, x: torch.Tensor) -> torch.Tensor:
  387. """Forward pass through all blocks in the stage.
  388. Args:
  389. x: Input tensor.
  390. Returns:
  391. Output tensor.
  392. """
  393. if self.grad_checkpointing and not torch.jit.is_scripting():
  394. x = checkpoint_seq(self.blocks, x)
  395. else:
  396. x = self.blocks(x)
  397. return x
  398. def is_stem_deep(stem_type: str) -> bool:
  399. """Check if stem type is deep (has multiple convolutions).
  400. Args:
  401. stem_type: Type of stem to check.
  402. Returns:
  403. True if stem is deep, False otherwise.
  404. """
  405. return any([s in stem_type for s in ('deep', 'tiered')])
  406. def create_resnetv2_stem(
  407. in_chs: int,
  408. out_chs: int = 64,
  409. stem_type: str = '',
  410. preact: bool = True,
  411. conv_layer: Callable = StdConv2d,
  412. norm_layer: Callable = partial(GroupNormAct, num_groups=32),
  413. device=None,
  414. dtype=None,
  415. ) -> nn.Sequential:
  416. dd = {'device': device, 'dtype': dtype}
  417. stem = OrderedDict()
  418. assert stem_type in ('', 'fixed', 'same', 'deep', 'deep_fixed', 'deep_same', 'tiered')
  419. # NOTE conv padding mode can be changed by overriding the conv_layer def
  420. if is_stem_deep(stem_type):
  421. # A 3 deep 3x3 conv stack as in ResNet V1D models
  422. if 'tiered' in stem_type:
  423. stem_chs = (3 * out_chs // 8, out_chs // 2) # 'T' resnets in resnet.py
  424. else:
  425. stem_chs = (out_chs // 2, out_chs // 2) # 'D' ResNets
  426. stem['conv1'] = conv_layer(in_chs, stem_chs[0], kernel_size=3, stride=2, **dd)
  427. stem['norm1'] = norm_layer(stem_chs[0], **dd)
  428. stem['conv2'] = conv_layer(stem_chs[0], stem_chs[1], kernel_size=3, stride=1, **dd)
  429. stem['norm2'] = norm_layer(stem_chs[1], **dd)
  430. stem['conv3'] = conv_layer(stem_chs[1], out_chs, kernel_size=3, stride=1, **dd)
  431. if not preact:
  432. stem['norm3'] = norm_layer(out_chs, **dd)
  433. else:
  434. # The usual 7x7 stem conv
  435. stem['conv'] = conv_layer(in_chs, out_chs, kernel_size=7, stride=2, **dd)
  436. if not preact:
  437. stem['norm'] = norm_layer(out_chs, **dd)
  438. if 'fixed' in stem_type:
  439. # 'fixed' SAME padding approximation that is used in BiT models
  440. stem['pad'] = nn.ConstantPad2d(1, 0.)
  441. stem['pool'] = nn.MaxPool2d(kernel_size=3, stride=2, padding=0)
  442. elif 'same' in stem_type:
  443. # full, input size based 'SAME' padding, used in ViT Hybrid model
  444. stem['pool'] = create_pool2d('max', kernel_size=3, stride=2, padding='same')
  445. else:
  446. # the usual PyTorch symmetric padding
  447. stem['pool'] = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
  448. return nn.Sequential(stem)
  449. class ResNetV2(nn.Module):
  450. """Implementation of Pre-activation (v2) ResNet mode.
  451. """
  452. def __init__(
  453. self,
  454. layers: List[int],
  455. channels: Tuple[int, ...] = (256, 512, 1024, 2048),
  456. num_classes: int = 1000,
  457. in_chans: int = 3,
  458. global_pool: str = 'avg',
  459. output_stride: int = 32,
  460. width_factor: int = 1,
  461. stem_chs: int = 64,
  462. stem_type: str = '',
  463. avg_down: bool = False,
  464. preact: bool = True,
  465. basic: bool = False,
  466. bottle_ratio: float = 0.25,
  467. act_layer: Callable = nn.ReLU,
  468. norm_layer: Callable = partial(GroupNormAct, num_groups=32),
  469. conv_layer: Callable = StdConv2d,
  470. drop_rate: float = 0.,
  471. drop_path_rate: float = 0.,
  472. zero_init_last: bool = False,
  473. device=None,
  474. dtype=None,
  475. ):
  476. """
  477. Args:
  478. layers (List[int]) : number of layers in each block
  479. channels (List[int]) : number of channels in each block:
  480. num_classes (int): number of classification classes (default 1000)
  481. in_chans (int): number of input (color) channels. (default 3)
  482. global_pool (str): Global pooling type. One of 'avg', 'max', 'avgmax', 'catavgmax' (default 'avg')
  483. output_stride (int): output stride of the network, 32, 16, or 8. (default 32)
  484. width_factor (int): channel (width) multiplication factor
  485. stem_chs (int): stem width (default: 64)
  486. stem_type (str): stem type (default: '' == 7x7)
  487. avg_down (bool): average pooling in residual downsampling (default: False)
  488. preact (bool): pre-activation (default: True)
  489. act_layer (Union[str, nn.Module]): activation layer
  490. norm_layer (Union[str, nn.Module]): normalization layer
  491. conv_layer (nn.Module): convolution module
  492. drop_rate: classifier dropout rate (default: 0.)
  493. drop_path_rate: stochastic depth rate (default: 0.)
  494. zero_init_last: zero-init last weight in residual path (default: False)
  495. """
  496. super().__init__()
  497. dd = {'device': device, 'dtype': dtype}
  498. self.num_classes = num_classes
  499. self.in_chans = in_chans
  500. self.drop_rate = drop_rate
  501. wf = width_factor
  502. norm_layer = get_norm_act_layer(norm_layer, act_layer=act_layer)
  503. act_layer = get_act_layer(act_layer)
  504. self.feature_info = []
  505. stem_chs = make_divisible(stem_chs * wf)
  506. self.stem = create_resnetv2_stem(
  507. in_chans,
  508. stem_chs,
  509. stem_type,
  510. preact,
  511. conv_layer=conv_layer,
  512. norm_layer=norm_layer,
  513. **dd,
  514. )
  515. stem_feat = ('stem.conv3' if is_stem_deep(stem_type) else 'stem.conv') if preact else 'stem.norm'
  516. self.feature_info.append(dict(num_chs=stem_chs, reduction=2, module=stem_feat))
  517. prev_chs = stem_chs
  518. curr_stride = 4
  519. dilation = 1
  520. block_dprs = calculate_drop_path_rates(drop_path_rate, layers, stagewise=True)
  521. if preact:
  522. block_fn = PreActBasic if basic else PreActBottleneck
  523. else:
  524. assert not basic
  525. block_fn = Bottleneck
  526. self.stages = nn.Sequential()
  527. for stage_idx, (d, c, bdpr) in enumerate(zip(layers, channels, block_dprs)):
  528. out_chs = make_divisible(c * wf)
  529. stride = 1 if stage_idx == 0 else 2
  530. if curr_stride >= output_stride:
  531. dilation *= stride
  532. stride = 1
  533. stage = ResNetStage(
  534. prev_chs,
  535. out_chs,
  536. stride=stride,
  537. dilation=dilation,
  538. depth=d,
  539. bottle_ratio=bottle_ratio,
  540. avg_down=avg_down,
  541. act_layer=act_layer,
  542. conv_layer=conv_layer,
  543. norm_layer=norm_layer,
  544. block_dpr=bdpr,
  545. block_fn=block_fn,
  546. **dd,
  547. )
  548. prev_chs = out_chs
  549. curr_stride *= stride
  550. self.feature_info += [dict(num_chs=prev_chs, reduction=curr_stride, module=f'stages.{stage_idx}')]
  551. self.stages.add_module(str(stage_idx), stage)
  552. self.num_features = self.head_hidden_size = prev_chs
  553. self.norm = norm_layer(self.num_features, **dd) if preact else nn.Identity()
  554. self.head = ClassifierHead(
  555. self.num_features,
  556. num_classes,
  557. pool_type=global_pool,
  558. drop_rate=self.drop_rate,
  559. use_conv=True,
  560. **dd,
  561. )
  562. self.init_weights(zero_init_last=zero_init_last)
  563. @torch.jit.ignore
  564. def init_weights(self, zero_init_last: bool = True) -> None:
  565. """Initialize model weights."""
  566. named_apply(partial(_init_weights, zero_init_last=zero_init_last), self)
  567. @torch.jit.ignore()
  568. def load_pretrained(self, checkpoint_path: str, prefix: str = 'resnet/') -> None:
  569. """Load pretrained weights."""
  570. _load_weights(self, checkpoint_path, prefix)
  571. @torch.jit.ignore
  572. def group_matcher(self, coarse: bool = False) -> Dict[str, Any]:
  573. """Group parameters for optimization."""
  574. matcher = dict(
  575. stem=r'^stem',
  576. blocks=r'^stages\.(\d+)' if coarse else [
  577. (r'^stages\.(\d+)\.blocks\.(\d+)', None),
  578. (r'^norm', (99999,))
  579. ]
  580. )
  581. return matcher
  582. @torch.jit.ignore
  583. def set_grad_checkpointing(self, enable: bool = True) -> None:
  584. """Enable or disable gradient checkpointing."""
  585. for s in self.stages:
  586. s.grad_checkpointing = enable
  587. @torch.jit.ignore
  588. def get_classifier(self) -> nn.Module:
  589. """Get the classifier head."""
  590. return self.head.fc
  591. def reset_classifier(self, num_classes: int, global_pool: Optional[str] = None) -> None:
  592. """Reset the classifier head.
  593. Args:
  594. num_classes: Number of classes for new classifier.
  595. global_pool: Global pooling type.
  596. """
  597. self.num_classes = num_classes
  598. self.head.reset(num_classes, global_pool)
  599. def forward_intermediates(
  600. self,
  601. x: torch.Tensor,
  602. indices: Optional[Union[int, List[int]]] = None,
  603. norm: bool = False,
  604. stop_early: bool = False,
  605. output_fmt: str = 'NCHW',
  606. intermediates_only: bool = False,
  607. ) -> Union[List[torch.Tensor], Tuple[torch.Tensor, List[torch.Tensor]]]:
  608. """ Forward features that returns intermediates.
  609. Args:
  610. x: Input image tensor
  611. indices: Take last n blocks if int, all if None, select matching indices if sequence
  612. norm: Apply norm layer to compatible intermediates
  613. stop_early: Stop iterating over blocks when last desired intermediate hit
  614. output_fmt: Shape of intermediate feature outputs
  615. intermediates_only: Only return intermediate features
  616. Returns:
  617. """
  618. assert output_fmt in ('NCHW',), 'Output shape must be NCHW.'
  619. intermediates = []
  620. take_indices, max_index = feature_take_indices(5, indices)
  621. # forward pass
  622. feat_idx = 0
  623. H, W = x.shape[-2:]
  624. for stem in self.stem:
  625. x = stem(x)
  626. if x.shape[-2:] == (H //2, W //2):
  627. x_down = x
  628. if feat_idx in take_indices:
  629. intermediates.append(x_down)
  630. last_idx = len(self.stages)
  631. if torch.jit.is_scripting() or not stop_early: # can't slice blocks in torchscript
  632. stages = self.stages
  633. else:
  634. stages = self.stages[:max_index]
  635. for feat_idx, stage in enumerate(stages, start=1):
  636. x = stage(x)
  637. if feat_idx in take_indices:
  638. if feat_idx == last_idx:
  639. x_inter = self.norm(x) if norm else x
  640. intermediates.append(x_inter)
  641. else:
  642. intermediates.append(x)
  643. if intermediates_only:
  644. return intermediates
  645. if feat_idx == last_idx:
  646. x = self.norm(x)
  647. return x, intermediates
  648. def prune_intermediate_layers(
  649. self,
  650. indices: Union[int, List[int]] = 1,
  651. prune_norm: bool = False,
  652. prune_head: bool = True,
  653. ):
  654. """ Prune layers not required for specified intermediates.
  655. """
  656. take_indices, max_index = feature_take_indices(5, indices)
  657. self.stages = self.stages[:max_index] # truncate blocks w/ stem as idx 0
  658. if prune_norm:
  659. self.norm = nn.Identity()
  660. if prune_head:
  661. self.reset_classifier(0, '')
  662. return take_indices
  663. def forward_features(self, x: torch.Tensor) -> torch.Tensor:
  664. """Forward pass through feature extraction layers.
  665. Args:
  666. x: Input tensor.
  667. Returns:
  668. Feature tensor.
  669. """
  670. x = self.stem(x)
  671. x = self.stages(x)
  672. x = self.norm(x)
  673. return x
  674. def forward_head(self, x: torch.Tensor, pre_logits: bool = False) -> torch.Tensor:
  675. """Forward pass through classifier head.
  676. Args:
  677. x: Input features.
  678. pre_logits: Return features before final linear layer.
  679. Returns:
  680. Classification logits or features.
  681. """
  682. return self.head(x, pre_logits=pre_logits) if pre_logits else self.head(x)
  683. def forward(self, x: torch.Tensor) -> torch.Tensor:
  684. """Forward pass.
  685. Args:
  686. x: Input tensor.
  687. Returns:
  688. Output logits.
  689. """
  690. x = self.forward_features(x)
  691. x = self.forward_head(x)
  692. return x
  693. def _init_weights(module: nn.Module, name: str = '', zero_init_last: bool = True) -> None:
  694. """Initialize module weights.
  695. Args:
  696. module: PyTorch module to initialize.
  697. name: Module name.
  698. zero_init_last: Zero-initialize last layer weights.
  699. """
  700. if isinstance(module, nn.Linear) or ('head.fc' in name and isinstance(module, nn.Conv2d)):
  701. nn.init.normal_(module.weight, mean=0.0, std=0.01)
  702. nn.init.zeros_(module.bias)
  703. elif isinstance(module, nn.Conv2d):
  704. nn.init.kaiming_normal_(module.weight, mode='fan_out', nonlinearity='relu')
  705. if module.bias is not None:
  706. nn.init.zeros_(module.bias)
  707. elif isinstance(module, (nn.BatchNorm2d, nn.LayerNorm, nn.GroupNorm)):
  708. nn.init.ones_(module.weight)
  709. nn.init.zeros_(module.bias)
  710. elif zero_init_last and hasattr(module, 'zero_init_last'):
  711. module.zero_init_last()
  712. @torch.no_grad()
  713. def _load_weights(model: nn.Module, checkpoint_path: str, prefix: str = 'resnet/'):
  714. import numpy as np
  715. def t2p(conv_weights):
  716. """Possibly convert HWIO to OIHW."""
  717. if conv_weights.ndim == 4:
  718. conv_weights = conv_weights.transpose([3, 2, 0, 1])
  719. return torch.from_numpy(conv_weights)
  720. weights = np.load(checkpoint_path)
  721. stem_conv_w = adapt_input_conv(
  722. model.stem.conv.weight.shape[1], t2p(weights[f'{prefix}root_block/standardized_conv2d/kernel']))
  723. model.stem.conv.weight.copy_(stem_conv_w)
  724. model.norm.weight.copy_(t2p(weights[f'{prefix}group_norm/gamma']))
  725. model.norm.bias.copy_(t2p(weights[f'{prefix}group_norm/beta']))
  726. if isinstance(getattr(model.head, 'fc', None), nn.Conv2d) and \
  727. model.head.fc.weight.shape[0] == weights[f'{prefix}head/conv2d/kernel'].shape[-1]:
  728. model.head.fc.weight.copy_(t2p(weights[f'{prefix}head/conv2d/kernel']))
  729. model.head.fc.bias.copy_(t2p(weights[f'{prefix}head/conv2d/bias']))
  730. for i, (sname, stage) in enumerate(model.stages.named_children()):
  731. for j, (bname, block) in enumerate(stage.blocks.named_children()):
  732. cname = 'standardized_conv2d'
  733. block_prefix = f'{prefix}block{i + 1}/unit{j + 1:02d}/'
  734. block.conv1.weight.copy_(t2p(weights[f'{block_prefix}a/{cname}/kernel']))
  735. block.conv2.weight.copy_(t2p(weights[f'{block_prefix}b/{cname}/kernel']))
  736. block.conv3.weight.copy_(t2p(weights[f'{block_prefix}c/{cname}/kernel']))
  737. block.norm1.weight.copy_(t2p(weights[f'{block_prefix}a/group_norm/gamma']))
  738. block.norm2.weight.copy_(t2p(weights[f'{block_prefix}b/group_norm/gamma']))
  739. block.norm3.weight.copy_(t2p(weights[f'{block_prefix}c/group_norm/gamma']))
  740. block.norm1.bias.copy_(t2p(weights[f'{block_prefix}a/group_norm/beta']))
  741. block.norm2.bias.copy_(t2p(weights[f'{block_prefix}b/group_norm/beta']))
  742. block.norm3.bias.copy_(t2p(weights[f'{block_prefix}c/group_norm/beta']))
  743. if block.downsample is not None:
  744. w = weights[f'{block_prefix}a/proj/{cname}/kernel']
  745. block.downsample.conv.weight.copy_(t2p(w))
  746. def _create_resnetv2(variant: str, pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  747. """Create a ResNetV2 model.
  748. Args:
  749. variant: Model variant name.
  750. pretrained: Load pretrained weights.
  751. **kwargs: Additional model arguments.
  752. Returns:
  753. ResNetV2 model instance.
  754. """
  755. feature_cfg = dict(flatten_sequential=True)
  756. return build_model_with_cfg(
  757. ResNetV2, variant, pretrained,
  758. feature_cfg=feature_cfg,
  759. **kwargs,
  760. )
  761. def _create_resnetv2_bit(variant: str, pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  762. """Create a ResNetV2 model with BiT weights.
  763. Args:
  764. variant: Model variant name.
  765. pretrained: Load pretrained weights.
  766. **kwargs: Additional model arguments.
  767. Returns:
  768. ResNetV2 model instance.
  769. """
  770. return _create_resnetv2(
  771. variant,
  772. pretrained=pretrained,
  773. stem_type='fixed',
  774. conv_layer=partial(StdConv2d, eps=1e-8),
  775. **kwargs,
  776. )
  777. def _cfg(url: str = '', **kwargs: Any) -> Dict[str, Any]:
  778. return {
  779. 'url': url,
  780. 'num_classes': 1000, 'input_size': (3, 224, 224), 'pool_size': (7, 7),
  781. 'crop_pct': 0.875, 'interpolation': 'bilinear',
  782. 'mean': IMAGENET_INCEPTION_MEAN, 'std': IMAGENET_INCEPTION_STD,
  783. 'first_conv': 'stem.conv', 'classifier': 'head.fc',
  784. 'license': 'apache-2.0',
  785. **kwargs
  786. }
  787. default_cfgs = generate_default_cfgs({
  788. # Paper: Knowledge distillation: A good teacher is patient and consistent - https://arxiv.org/abs/2106.05237
  789. 'resnetv2_50x1_bit.goog_distilled_in1k': _cfg(
  790. hf_hub_id='timm/',
  791. interpolation='bicubic', custom_load=True),
  792. 'resnetv2_152x2_bit.goog_teacher_in21k_ft_in1k': _cfg(
  793. hf_hub_id='timm/',
  794. interpolation='bicubic', custom_load=True),
  795. 'resnetv2_152x2_bit.goog_teacher_in21k_ft_in1k_384': _cfg(
  796. hf_hub_id='timm/',
  797. input_size=(3, 384, 384), pool_size=(12, 12), crop_pct=1.0, interpolation='bicubic', custom_load=True),
  798. # pretrained on imagenet21k, finetuned on imagenet1k
  799. 'resnetv2_50x1_bit.goog_in21k_ft_in1k': _cfg(
  800. hf_hub_id='timm/',
  801. input_size=(3, 448, 448), pool_size=(14, 14), crop_pct=1.0, custom_load=True),
  802. 'resnetv2_50x3_bit.goog_in21k_ft_in1k': _cfg(
  803. hf_hub_id='timm/',
  804. input_size=(3, 448, 448), pool_size=(14, 14), crop_pct=1.0, custom_load=True),
  805. 'resnetv2_101x1_bit.goog_in21k_ft_in1k': _cfg(
  806. hf_hub_id='timm/',
  807. input_size=(3, 448, 448), pool_size=(14, 14), crop_pct=1.0, custom_load=True),
  808. 'resnetv2_101x3_bit.goog_in21k_ft_in1k': _cfg(
  809. hf_hub_id='timm/',
  810. input_size=(3, 448, 448), pool_size=(14, 14), crop_pct=1.0, custom_load=True),
  811. 'resnetv2_152x2_bit.goog_in21k_ft_in1k': _cfg(
  812. hf_hub_id='timm/',
  813. input_size=(3, 448, 448), pool_size=(14, 14), crop_pct=1.0, custom_load=True),
  814. 'resnetv2_152x4_bit.goog_in21k_ft_in1k': _cfg(
  815. hf_hub_id='timm/',
  816. input_size=(3, 480, 480), pool_size=(15, 15), crop_pct=1.0, custom_load=True), # only one at 480x480?
  817. # trained on imagenet-21k
  818. 'resnetv2_50x1_bit.goog_in21k': _cfg(
  819. hf_hub_id='timm/',
  820. num_classes=21843, custom_load=True),
  821. 'resnetv2_50x3_bit.goog_in21k': _cfg(
  822. hf_hub_id='timm/',
  823. num_classes=21843, custom_load=True),
  824. 'resnetv2_101x1_bit.goog_in21k': _cfg(
  825. hf_hub_id='timm/',
  826. num_classes=21843, custom_load=True),
  827. 'resnetv2_101x3_bit.goog_in21k': _cfg(
  828. hf_hub_id='timm/',
  829. num_classes=21843, custom_load=True),
  830. 'resnetv2_152x2_bit.goog_in21k': _cfg(
  831. hf_hub_id='timm/',
  832. num_classes=21843, custom_load=True),
  833. 'resnetv2_152x4_bit.goog_in21k': _cfg(
  834. hf_hub_id='timm/',
  835. num_classes=21843, custom_load=True),
  836. 'resnetv2_18.ra4_e3600_r224_in1k': _cfg(
  837. hf_hub_id='timm/',
  838. interpolation='bicubic', crop_pct=0.9, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  839. 'resnetv2_18d.ra4_e3600_r224_in1k': _cfg(
  840. hf_hub_id='timm/',
  841. interpolation='bicubic', crop_pct=0.9, test_input_size=(3, 288, 288), test_crop_pct=1.0,
  842. first_conv='stem.conv1'),
  843. 'resnetv2_34.ra4_e3600_r224_in1k': _cfg(
  844. hf_hub_id='timm/',
  845. interpolation='bicubic', crop_pct=0.9, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  846. 'resnetv2_34d.ra4_e3600_r224_in1k': _cfg(
  847. hf_hub_id='timm/',
  848. interpolation='bicubic', crop_pct=0.9, test_input_size=(3, 288, 288), test_crop_pct=1.0,
  849. first_conv='stem.conv1'),
  850. 'resnetv2_34d.ra4_e3600_r384_in1k': _cfg(
  851. hf_hub_id='timm/',
  852. crop_pct=1.0, input_size=(3, 384, 384), pool_size=(12, 12), test_input_size=(3, 448, 448),
  853. interpolation='bicubic', first_conv='stem.conv1'),
  854. 'resnetv2_50.a1h_in1k': _cfg(
  855. hf_hub_id='timm/',
  856. interpolation='bicubic', crop_pct=0.95, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  857. 'resnetv2_50d.untrained': _cfg(
  858. interpolation='bicubic', first_conv='stem.conv1'),
  859. 'resnetv2_50t.untrained': _cfg(
  860. interpolation='bicubic', first_conv='stem.conv1'),
  861. 'resnetv2_101.a1h_in1k': _cfg(
  862. hf_hub_id='timm/',
  863. interpolation='bicubic', crop_pct=0.95, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  864. 'resnetv2_101d.untrained': _cfg(
  865. interpolation='bicubic', first_conv='stem.conv1'),
  866. 'resnetv2_152.untrained': _cfg(
  867. interpolation='bicubic'),
  868. 'resnetv2_152d.untrained': _cfg(
  869. interpolation='bicubic', first_conv='stem.conv1'),
  870. 'resnetv2_50d_gn.ah_in1k': _cfg(
  871. hf_hub_id='timm/',
  872. interpolation='bicubic', first_conv='stem.conv1',
  873. crop_pct=0.95, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  874. 'resnetv2_50d_evos.ah_in1k': _cfg(
  875. hf_hub_id='timm/',
  876. interpolation='bicubic', first_conv='stem.conv1',
  877. crop_pct=0.95, test_input_size=(3, 288, 288), test_crop_pct=1.0),
  878. 'resnetv2_50d_frn.untrained': _cfg(
  879. interpolation='bicubic', first_conv='stem.conv1'),
  880. })
  881. @register_model
  882. def resnetv2_50x1_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  883. """ResNetV2-50x1-BiT model."""
  884. return _create_resnetv2_bit(
  885. 'resnetv2_50x1_bit', pretrained=pretrained, layers=[3, 4, 6, 3], width_factor=1, **kwargs)
  886. @register_model
  887. def resnetv2_50x3_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  888. """ResNetV2-50x3-BiT model."""
  889. return _create_resnetv2_bit(
  890. 'resnetv2_50x3_bit', pretrained=pretrained, layers=[3, 4, 6, 3], width_factor=3, **kwargs)
  891. @register_model
  892. def resnetv2_101x1_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  893. """ResNetV2-101x1-BiT model."""
  894. return _create_resnetv2_bit(
  895. 'resnetv2_101x1_bit', pretrained=pretrained, layers=[3, 4, 23, 3], width_factor=1, **kwargs)
  896. @register_model
  897. def resnetv2_101x3_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  898. """ResNetV2-101x3-BiT model."""
  899. return _create_resnetv2_bit(
  900. 'resnetv2_101x3_bit', pretrained=pretrained, layers=[3, 4, 23, 3], width_factor=3, **kwargs)
  901. @register_model
  902. def resnetv2_152x2_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  903. """ResNetV2-152x2-BiT model."""
  904. return _create_resnetv2_bit(
  905. 'resnetv2_152x2_bit', pretrained=pretrained, layers=[3, 8, 36, 3], width_factor=2, **kwargs)
  906. @register_model
  907. def resnetv2_152x4_bit(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  908. """ResNetV2-152x4-BiT model."""
  909. return _create_resnetv2_bit(
  910. 'resnetv2_152x4_bit', pretrained=pretrained, layers=[3, 8, 36, 3], width_factor=4, **kwargs)
  911. @register_model
  912. def resnetv2_18(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  913. """ResNetV2-18 model."""
  914. model_args = dict(
  915. layers=[2, 2, 2, 2], channels=(64, 128, 256, 512), basic=True, bottle_ratio=1.0,
  916. conv_layer=create_conv2d, norm_layer=BatchNormAct2d
  917. )
  918. return _create_resnetv2('resnetv2_18', pretrained=pretrained, **dict(model_args, **kwargs))
  919. @register_model
  920. def resnetv2_18d(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  921. """ResNetV2-18d model (deep stem variant)."""
  922. model_args = dict(
  923. layers=[2, 2, 2, 2], channels=(64, 128, 256, 512), basic=True, bottle_ratio=1.0,
  924. conv_layer=create_conv2d, norm_layer=BatchNormAct2d, stem_type='deep', avg_down=True
  925. )
  926. return _create_resnetv2('resnetv2_18d', pretrained=pretrained, **dict(model_args, **kwargs))
  927. @register_model
  928. def resnetv2_34(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  929. """ResNetV2-34 model."""
  930. model_args = dict(
  931. layers=(3, 4, 6, 3), channels=(64, 128, 256, 512), basic=True, bottle_ratio=1.0,
  932. conv_layer=create_conv2d, norm_layer=BatchNormAct2d
  933. )
  934. return _create_resnetv2('resnetv2_34', pretrained=pretrained, **dict(model_args, **kwargs))
  935. @register_model
  936. def resnetv2_34d(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  937. """ResNetV2-34d model (deep stem variant)."""
  938. model_args = dict(
  939. layers=(3, 4, 6, 3), channels=(64, 128, 256, 512), basic=True, bottle_ratio=1.0,
  940. conv_layer=create_conv2d, norm_layer=BatchNormAct2d, stem_type='deep', avg_down=True
  941. )
  942. return _create_resnetv2('resnetv2_34d', pretrained=pretrained, **dict(model_args, **kwargs))
  943. @register_model
  944. def resnetv2_50(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  945. """ResNetV2-50 model."""
  946. model_args = dict(layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d)
  947. return _create_resnetv2('resnetv2_50', pretrained=pretrained, **dict(model_args, **kwargs))
  948. @register_model
  949. def resnetv2_50d(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  950. """ResNetV2-50d model (deep stem variant)."""
  951. model_args = dict(
  952. layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d,
  953. stem_type='deep', avg_down=True)
  954. return _create_resnetv2('resnetv2_50d', pretrained=pretrained, **dict(model_args, **kwargs))
  955. @register_model
  956. def resnetv2_50t(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  957. """ResNetV2-50t model (tiered stem variant)."""
  958. model_args = dict(
  959. layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d,
  960. stem_type='tiered', avg_down=True)
  961. return _create_resnetv2('resnetv2_50t', pretrained=pretrained, **dict(model_args, **kwargs))
  962. @register_model
  963. def resnetv2_101(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  964. """ResNetV2-101 model."""
  965. model_args = dict(layers=[3, 4, 23, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d)
  966. return _create_resnetv2('resnetv2_101', pretrained=pretrained, **dict(model_args, **kwargs))
  967. @register_model
  968. def resnetv2_101d(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  969. """ResNetV2-101d model (deep stem variant)."""
  970. model_args = dict(
  971. layers=[3, 4, 23, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d,
  972. stem_type='deep', avg_down=True)
  973. return _create_resnetv2('resnetv2_101d', pretrained=pretrained, **dict(model_args, **kwargs))
  974. @register_model
  975. def resnetv2_152(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  976. """ResNetV2-152 model."""
  977. model_args = dict(layers=[3, 8, 36, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d)
  978. return _create_resnetv2('resnetv2_152', pretrained=pretrained, **dict(model_args, **kwargs))
  979. @register_model
  980. def resnetv2_152d(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  981. """ResNetV2-152d model (deep stem variant)."""
  982. model_args = dict(
  983. layers=[3, 8, 36, 3], conv_layer=create_conv2d, norm_layer=BatchNormAct2d,
  984. stem_type='deep', avg_down=True)
  985. return _create_resnetv2('resnetv2_152d', pretrained=pretrained, **dict(model_args, **kwargs))
  986. # Experimental configs (may change / be removed)
  987. @register_model
  988. def resnetv2_50d_gn(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  989. """ResNetV2-50d model with Group Normalization."""
  990. model_args = dict(
  991. layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=GroupNormAct,
  992. stem_type='deep', avg_down=True)
  993. return _create_resnetv2('resnetv2_50d_gn', pretrained=pretrained, **dict(model_args, **kwargs))
  994. @register_model
  995. def resnetv2_50d_evos(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  996. """ResNetV2-50d model with EvoNorm."""
  997. model_args = dict(
  998. layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=EvoNorm2dS0,
  999. stem_type='deep', avg_down=True)
  1000. return _create_resnetv2('resnetv2_50d_evos', pretrained=pretrained, **dict(model_args, **kwargs))
  1001. @register_model
  1002. def resnetv2_50d_frn(pretrained: bool = False, **kwargs: Any) -> ResNetV2:
  1003. """ResNetV2-50d model with Filter Response Normalization."""
  1004. model_args = dict(
  1005. layers=[3, 4, 6, 3], conv_layer=create_conv2d, norm_layer=FilterResponseNormTlu2d,
  1006. stem_type='deep', avg_down=True)
  1007. return _create_resnetv2('resnetv2_50d_frn', pretrained=pretrained, **dict(model_args, **kwargs))
  1008. register_model_deprecations(__name__, {
  1009. 'resnetv2_50x1_bitm': 'resnetv2_50x1_bit.goog_in21k_ft_in1k',
  1010. 'resnetv2_50x3_bitm': 'resnetv2_50x3_bit.goog_in21k_ft_in1k',
  1011. 'resnetv2_101x1_bitm': 'resnetv2_101x1_bit.goog_in21k_ft_in1k',
  1012. 'resnetv2_101x3_bitm': 'resnetv2_101x3_bit.goog_in21k_ft_in1k',
  1013. 'resnetv2_152x2_bitm': 'resnetv2_152x2_bit.goog_in21k_ft_in1k',
  1014. 'resnetv2_152x4_bitm': 'resnetv2_152x4_bit.goog_in21k_ft_in1k',
  1015. 'resnetv2_50x1_bitm_in21k': 'resnetv2_50x1_bit.goog_in21k',
  1016. 'resnetv2_50x3_bitm_in21k': 'resnetv2_50x3_bit.goog_in21k',
  1017. 'resnetv2_101x1_bitm_in21k': 'resnetv2_101x1_bit.goog_in21k',
  1018. 'resnetv2_101x3_bitm_in21k': 'resnetv2_101x3_bit.goog_in21k',
  1019. 'resnetv2_152x2_bitm_in21k': 'resnetv2_152x2_bit.goog_in21k',
  1020. 'resnetv2_152x4_bitm_in21k': 'resnetv2_152x4_bit.goog_in21k',
  1021. 'resnetv2_50x1_bit_distilled': 'resnetv2_50x1_bit.goog_distilled_in1k',
  1022. 'resnetv2_152x2_bit_teacher': 'resnetv2_152x2_bit.goog_teacher_in21k_ft_in1k',
  1023. 'resnetv2_152x2_bit_teacher_384': 'resnetv2_152x2_bit.goog_teacher_in21k_ft_in1k_384',
  1024. })