arghyaiitb commited on
Commit
a2b32c9
·
1 Parent(s): 63106a4

fixed the model code

Browse files
Files changed (2) hide show
  1. app.py +1 -114
  2. models.py +134 -0
app.py CHANGED
@@ -1,12 +1,12 @@
1
  import gradio as gr
2
  import torch
3
- import torch.nn as nn
4
  import torch.nn.functional as F
5
  from torchvision import transforms
6
  import numpy as np
7
  from PIL import Image
8
  import json
9
  import os
 
10
 
11
  # ImageNet-1k class names from HuggingFace
12
  # Source: https://huggingface.co/datasets/huggingface/label-files/blob/main/imagenet-1k-id2label.json
@@ -24,119 +24,6 @@ else:
24
  json.dump(IMAGENET_CLASSES, f, indent=2)
25
  print("ImageNet class labels downloaded successfully!")
26
 
27
- # Model definition - ResNet-50 for ImageNet
28
- class Bottleneck(nn.Module):
29
- """Bottleneck block for ResNet-50/101/152"""
30
- expansion = 4
31
-
32
- def __init__(self, in_channels, out_channels, stride=1, downsample=None):
33
- super(Bottleneck, self).__init__()
34
- self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
35
- self.bn1 = nn.BatchNorm2d(out_channels)
36
- self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3,
37
- stride=stride, padding=1, bias=False)
38
- self.bn2 = nn.BatchNorm2d(out_channels)
39
- self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion,
40
- kernel_size=1, bias=False)
41
- self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)
42
- self.downsample = downsample
43
-
44
- def forward(self, x):
45
- identity = x
46
-
47
- out = self.conv1(x)
48
- out = self.bn1(out)
49
- out = F.relu(out)
50
-
51
- out = self.conv2(out)
52
- out = self.bn2(out)
53
- out = F.relu(out)
54
-
55
- out = self.conv3(out)
56
- out = self.bn3(out)
57
-
58
- if self.downsample is not None:
59
- identity = self.downsample(x)
60
-
61
- out += identity
62
- out = F.relu(out)
63
-
64
- return out
65
-
66
-
67
- class ResNet50(nn.Module):
68
- """ResNet-50 model for ImageNet"""
69
-
70
- def __init__(self, num_classes=1000):
71
- super(ResNet50, self).__init__()
72
- self.in_channels = 64
73
-
74
- # Initial convolution layer
75
- self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
76
- self.bn1 = nn.BatchNorm2d(64)
77
- self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
78
-
79
- # ResNet-50 architecture: [3, 4, 6, 3] blocks
80
- self.layer1 = self._make_layer(64, 3, stride=1)
81
- self.layer2 = self._make_layer(128, 4, stride=2)
82
- self.layer3 = self._make_layer(256, 6, stride=2)
83
- self.layer4 = self._make_layer(512, 3, stride=2)
84
-
85
- # Final layers
86
- self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
87
- self.fc = nn.Linear(512 * Bottleneck.expansion, num_classes)
88
-
89
- # Initialize weights
90
- self._initialize_weights()
91
-
92
- def _make_layer(self, out_channels, blocks, stride):
93
- """Create a residual layer with specified number of blocks"""
94
- downsample = None
95
- if stride != 1 or self.in_channels != out_channels * Bottleneck.expansion:
96
- downsample = nn.Sequential(
97
- nn.Conv2d(self.in_channels, out_channels * Bottleneck.expansion,
98
- kernel_size=1, stride=stride, bias=False),
99
- nn.BatchNorm2d(out_channels * Bottleneck.expansion),
100
- )
101
-
102
- layers = []
103
- layers.append(Bottleneck(self.in_channels, out_channels, stride, downsample))
104
- self.in_channels = out_channels * Bottleneck.expansion
105
-
106
- for _ in range(1, blocks):
107
- layers.append(Bottleneck(self.in_channels, out_channels))
108
-
109
- return nn.Sequential(*layers)
110
-
111
- def _initialize_weights(self):
112
- """Initialize weights using He initialization"""
113
- for m in self.modules():
114
- if isinstance(m, nn.Conv2d):
115
- nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
116
- elif isinstance(m, nn.BatchNorm2d):
117
- nn.init.constant_(m.weight, 1)
118
- nn.init.constant_(m.bias, 0)
119
-
120
- def forward(self, x):
121
- # Initial layers
122
- x = self.conv1(x)
123
- x = self.bn1(x)
124
- x = F.relu(x)
125
- x = self.maxpool(x)
126
-
127
- # Residual layers
128
- x = self.layer1(x)
129
- x = self.layer2(x)
130
- x = self.layer3(x)
131
- x = self.layer4(x)
132
-
133
- # Final layers
134
- x = self.avgpool(x)
135
- x = torch.flatten(x, 1)
136
- x = self.fc(x)
137
-
138
- return x
139
-
140
 
141
  # Load model
142
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
1
  import gradio as gr
2
  import torch
 
3
  import torch.nn.functional as F
4
  from torchvision import transforms
5
  import numpy as np
6
  from PIL import Image
7
  import json
8
  import os
9
+ from models import ResNet50
10
 
11
  # ImageNet-1k class names from HuggingFace
12
  # Source: https://huggingface.co/datasets/huggingface/label-files/blob/main/imagenet-1k-id2label.json
 
24
  json.dump(IMAGENET_CLASSES, f, indent=2)
25
  print("ImageNet class labels downloaded successfully!")
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  # Load model
29
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
models.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+
6
+ class Bottleneck(nn.Module):
7
+ """Bottleneck residual block for ResNet-50/101/152"""
8
+ expansion = 4
9
+
10
+ def __init__(self, in_channels, out_channels, stride=1, downsample=None, dropout=0.0):
11
+ super(Bottleneck, self).__init__()
12
+ self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
13
+ self.bn1 = nn.BatchNorm2d(out_channels)
14
+ self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
15
+ self.bn2 = nn.BatchNorm2d(out_channels)
16
+ self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=1, bias=False)
17
+ self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)
18
+ self.downsample = downsample
19
+ self.dropout = nn.Dropout2d(dropout) if dropout > 0 else None
20
+
21
+ def forward(self, x):
22
+ identity = x
23
+
24
+ out = self.conv1(x)
25
+ out = self.bn1(out)
26
+ out = F.relu(out)
27
+
28
+ out = self.conv2(out)
29
+ out = self.bn2(out)
30
+ out = F.relu(out)
31
+
32
+ if self.dropout is not None:
33
+ out = self.dropout(out)
34
+
35
+ out = self.conv3(out)
36
+ out = self.bn3(out)
37
+
38
+ if self.downsample is not None:
39
+ identity = self.downsample(x)
40
+
41
+ out += identity
42
+ out = F.relu(out)
43
+
44
+ return out
45
+
46
+
47
+ class ResNet50(nn.Module):
48
+ """ResNet-50 model for ImageNet-1K dataset"""
49
+
50
+ def __init__(self, num_classes=1000, dropout=0.0):
51
+ super(ResNet50, self).__init__()
52
+ self.in_channels = 64
53
+
54
+ # Initial convolution layer for ImageNet (224x224 input)
55
+ self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
56
+ self.bn1 = nn.BatchNorm2d(64)
57
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
58
+
59
+ # ResNet-50 architecture: [3, 4, 6, 3] blocks per layer group
60
+ self.layer1 = self._make_layer(64, 3, stride=1, dropout=dropout)
61
+ self.layer2 = self._make_layer(128, 4, stride=2, dropout=dropout)
62
+ self.layer3 = self._make_layer(256, 6, stride=2, dropout=dropout)
63
+ self.layer4 = self._make_layer(512, 3, stride=2, dropout=dropout)
64
+
65
+ # Final layers for ImageNet
66
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
67
+ self.dropout = nn.Dropout(0.5) # Standard dropout for ImageNet
68
+ self.fc = nn.Linear(512 * Bottleneck.expansion, num_classes)
69
+
70
+ # Initialize weights
71
+ self._initialize_weights()
72
+
73
+ def _make_layer(self, out_channels, blocks, stride, dropout=0.0):
74
+ """Create a residual layer with specified number of blocks"""
75
+ downsample = None
76
+ if stride != 1 or self.in_channels != out_channels * Bottleneck.expansion:
77
+ downsample = nn.Sequential(
78
+ nn.Conv2d(self.in_channels, out_channels * Bottleneck.expansion,
79
+ kernel_size=1, stride=stride, bias=False),
80
+ nn.BatchNorm2d(out_channels * Bottleneck.expansion),
81
+ )
82
+
83
+ layers = []
84
+ layers.append(Bottleneck(self.in_channels, out_channels, stride, downsample, dropout))
85
+ self.in_channels = out_channels * Bottleneck.expansion
86
+
87
+ for _ in range(1, blocks):
88
+ layers.append(Bottleneck(self.in_channels, out_channels, dropout=dropout))
89
+
90
+ return nn.Sequential(*layers)
91
+
92
+ def _initialize_weights(self):
93
+ """Initialize weights using He initialization"""
94
+ for m in self.modules():
95
+ if isinstance(m, nn.Conv2d):
96
+ nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
97
+ elif isinstance(m, nn.BatchNorm2d):
98
+ nn.init.constant_(m.weight, 1)
99
+ nn.init.constant_(m.bias, 0)
100
+
101
+ def forward(self, x):
102
+ # Initial layers
103
+ x = self.conv1(x)
104
+ x = self.bn1(x)
105
+ x = F.relu(x)
106
+ x = self.maxpool(x)
107
+
108
+ # Residual layers
109
+ x = self.layer1(x)
110
+ x = self.layer2(x)
111
+ x = self.layer3(x)
112
+ x = self.layer4(x)
113
+
114
+ # Final layers
115
+ x = self.avgpool(x)
116
+ x = torch.flatten(x, 1)
117
+ x = self.dropout(x)
118
+ x = self.fc(x)
119
+
120
+ return x
121
+
122
+
123
+ if __name__ == "__main__":
124
+ # Test the model
125
+ model = ResNet50(num_classes=1000)
126
+ print(f"Model parameters: {sum(p.numel() for p in model.parameters()):,}")
127
+ print(f"Model trainable parameters: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")
128
+
129
+ # Test forward pass
130
+ x = torch.randn(1, 3, 224, 224) # ImageNet size (224x224)
131
+ y = model(x)
132
+ print(f"Input shape: {x.shape}")
133
+ print(f"Output shape: {y.shape}")
134
+ print(f"Expected output classes: {y.shape[1]}")