S-Rajesh commited on
Commit
a252a3e
·
verified ·
1 Parent(s): 880e6b5

Upload convnext_original.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. convnext_original.py +156 -0
convnext_original.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ # All rights reserved.
4
+
5
+ # This source code is licensed under the license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ from timm.models.layers import trunc_normal_, DropPath
13
+ # from timm.models.registry import register_model
14
+
15
+ class Block(nn.Module):
16
+ r""" ConvNeXt Block. There are two equivalent implementations:
17
+ (1) DwConv -> LayerNorm (channels_first) -> 1x1 Conv -> GELU -> 1x1 Conv; all in (N, C, H, W)
18
+ (2) DwConv -> Permute to (N, H, W, C); LayerNorm (channels_last) -> Linear -> GELU -> Linear; Permute back
19
+ We use (2) as we find it slightly faster in PyTorch
20
+
21
+ Args:
22
+ dim (int): Number of input channels.
23
+ drop_path (float): Stochastic depth rate. Default: 0.0
24
+ layer_scale_init_value (float): Init value for Layer Scale. Default: 1e-6.
25
+ """
26
+ def __init__(self, dim, drop_path=0., layer_scale_init_value=1e-6):
27
+ super().__init__()
28
+ self.dwconv = nn.Conv2d(dim, dim, kernel_size=7, padding=3, groups=dim) # depthwise conv
29
+ self.norm = LayerNorm(dim, eps=1e-6)
30
+ self.pwconv1 = nn.Linear(dim, 4 * dim) # pointwise/1x1 convs, implemented with linear layers
31
+ self.act = nn.GELU()
32
+ self.pwconv2 = nn.Linear(4 * dim, dim)
33
+ self.gamma = nn.Parameter(layer_scale_init_value * torch.ones((dim)),
34
+ requires_grad=True) if layer_scale_init_value > 0 else None
35
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
36
+
37
+ def forward(self, x):
38
+ input = x
39
+ x = self.dwconv(x)
40
+ x = x.permute(0, 2, 3, 1) # (N, C, H, W) -> (N, H, W, C)
41
+ x = self.norm(x)
42
+ x = self.pwconv1(x)
43
+ x = self.act(x)
44
+ x = self.pwconv2(x)
45
+ if self.gamma is not None:
46
+ x = self.gamma * x
47
+ x = x.permute(0, 3, 1, 2) # (N, H, W, C) -> (N, C, H, W)
48
+
49
+ x = input + self.drop_path(x)
50
+ return x
51
+
52
+ class ConvNeXt(nn.Module):
53
+ r""" ConvNeXt
54
+ A PyTorch impl of : `A ConvNet for the 2020s` -
55
+ https://arxiv.org/pdf/2201.03545.pdf
56
+
57
+ Args:
58
+ in_chans (int): Number of input image channels. Default: 3
59
+ num_classes (int): Number of classes for classification head. Default: 1000
60
+ depths (tuple(int)): Number of blocks at each stage. Default: [3, 3, 9, 3]
61
+ dims (int): Feature dimension at each stage. Default: [96, 192, 384, 768]
62
+ drop_path_rate (float): Stochastic depth rate. Default: 0.
63
+ layer_scale_init_value (float): Init value for Layer Scale. Default: 1e-6.
64
+ head_init_scale (float): Init scaling value for classifier weights and biases. Default: 1.
65
+ """
66
+ def __init__(self, in_chans=3, num_classes=1000,
67
+ depths=[3, 3, 9, 3], dims=[96, 192, 384, 768], drop_path_rate=0.,
68
+ layer_scale_init_value=1e-6, head_init_scale=1.,
69
+ ):
70
+ super().__init__()
71
+
72
+ self.downsample_layers = nn.ModuleList() # stem and 3 intermediate downsampling conv layers
73
+ stem = nn.Sequential(
74
+ nn.Conv2d(in_chans, dims[0], kernel_size=4, stride=4),
75
+ LayerNorm(dims[0], eps=1e-6, data_format="channels_first")
76
+ )
77
+ self.downsample_layers.append(stem)
78
+ for i in range(3):
79
+ downsample_layer = nn.Sequential(
80
+ LayerNorm(dims[i], eps=1e-6, data_format="channels_first"),
81
+ nn.Conv2d(dims[i], dims[i+1], kernel_size=2, stride=2),
82
+ )
83
+ self.downsample_layers.append(downsample_layer)
84
+
85
+ self.stages = nn.ModuleList() # 4 feature resolution stages, each consisting of multiple residual blocks
86
+ dp_rates=[x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]
87
+ cur = 0
88
+ for i in range(4):
89
+ stage = nn.Sequential(
90
+ *[Block(dim=dims[i], drop_path=dp_rates[cur + j],
91
+ layer_scale_init_value=layer_scale_init_value) for j in range(depths[i])]
92
+ )
93
+ self.stages.append(stage)
94
+ cur += depths[i]
95
+
96
+ self.norm = nn.LayerNorm(dims[-1], eps=1e-6) # final norm layer
97
+ self.head = nn.Linear(dims[-1], num_classes)
98
+
99
+ self.apply(self._init_weights)
100
+ self.head.weight.data.mul_(head_init_scale)
101
+ self.head.bias.data.mul_(head_init_scale)
102
+
103
+ def _init_weights(self, m):
104
+ if isinstance(m, (nn.Conv2d, nn.Linear)):
105
+ trunc_normal_(m.weight, std=.02)
106
+ nn.init.constant_(m.bias, 0)
107
+
108
+ def forward_features(self, x):
109
+ for i in range(4):
110
+ x = self.downsample_layers[i](x)
111
+ x = self.stages[i](x)
112
+ return self.norm(x.mean([-2, -1])) # global average pooling, (N, C, H, W) -> (N, C)
113
+
114
+ def forward(self, x):
115
+ x = self.forward_features(x)
116
+ x = self.head(x)
117
+ return x
118
+
119
+ class LayerNorm(nn.Module):
120
+ r""" LayerNorm that supports two data formats: channels_last (default) or channels_first.
121
+ The ordering of the dimensions in the inputs. channels_last corresponds to inputs with
122
+ shape (batch_size, height, width, channels) while channels_first corresponds to inputs
123
+ with shape (batch_size, channels, height, width).
124
+ """
125
+ def __init__(self, normalized_shape, eps=1e-6, data_format="channels_last"):
126
+ super().__init__()
127
+ self.weight = nn.Parameter(torch.ones(normalized_shape))
128
+ self.bias = nn.Parameter(torch.zeros(normalized_shape))
129
+ self.eps = eps
130
+ self.data_format = data_format
131
+ if self.data_format not in ["channels_last", "channels_first"]:
132
+ raise NotImplementedError
133
+ self.normalized_shape = (normalized_shape, )
134
+
135
+ def forward(self, x):
136
+ if self.data_format == "channels_last":
137
+ return F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps)
138
+ elif self.data_format == "channels_first":
139
+ u = x.mean(1, keepdim=True)
140
+ s = (x - u).pow(2).mean(1, keepdim=True)
141
+ x = (x - u) / torch.sqrt(s + self.eps)
142
+ x = self.weight[:, None, None] * x + self.bias[:, None, None]
143
+ return x
144
+
145
+
146
+ model_urls = {
147
+ "convnext_tiny_1k": "https://dl.fbaipublicfiles.com/convnext/convnext_tiny_1k_224_ema.pth",
148
+ "convnext_small_1k": "https://dl.fbaipublicfiles.com/convnext/convnext_small_1k_224_ema.pth",
149
+ "convnext_base_1k": "https://dl.fbaipublicfiles.com/convnext/convnext_base_1k_224_ema.pth",
150
+ "convnext_large_1k": "https://dl.fbaipublicfiles.com/convnext/convnext_large_1k_224_ema.pth",
151
+ "convnext_tiny_22k": "https://dl.fbaipublicfiles.com/convnext/convnext_tiny_22k_224.pth",
152
+ "convnext_small_22k": "https://dl.fbaipublicfiles.com/convnext/convnext_small_22k_224.pth",
153
+ "convnext_base_22k": "https://dl.fbaipublicfiles.com/convnext/convnext_base_22k_224.pth",
154
+ "convnext_large_22k": "https://dl.fbaipublicfiles.com/convnext/convnext_large_22k_224.pth",
155
+ "convnext_xlarge_22k": "https://dl.fbaipublicfiles.com/convnext/convnext_xlarge_22k_224.pth",
156
+ }