sidharthg commited on
Commit
a91f34b
·
verified ·
1 Parent(s): 97fe418

Upload 7 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ examples/1.jpg filter=lfs diff=lfs merge=lfs -text
37
+ examples/2.jpg filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torchvision.transforms as T
4
+ from PIL import Image
5
+ from model import resnet18 # Ensure this matches your model definition file
6
+
7
+ # Load CIFAR-100 class names
8
+ with open("cifar100_classes.txt") as f:
9
+ CIFAR100_CLASSES = [line.strip() for line in f.readlines()]
10
+
11
+ # Load trained model
12
+ DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
+ model = resnet18(num_classes=100)
14
+ checkpoint=torch.load("resnet18_cifar100_best.pth", map_location=DEVICE)
15
+ model.load_state_dict(checkpoint["model_state_dict"])
16
+
17
+ model.eval()
18
+ model.to(DEVICE)
19
+
20
+ # Define preprocessing
21
+ transform = T.Compose([
22
+ T.Resize((32, 32)),
23
+ T.ToTensor(),
24
+ T.Normalize((0.5071, 0.4867, 0.4408), (0.2675, 0.2565, 0.2761)),
25
+ ])
26
+
27
+ def predict(image):
28
+ img = Image.fromarray(image).convert("RGB")
29
+ img = transform(img).unsqueeze(0).to(DEVICE)
30
+ with torch.no_grad():
31
+ outputs = model(img)
32
+ probs = torch.softmax(outputs, dim=1)
33
+ conf, pred = torch.max(probs, dim=1)
34
+ class_name = CIFAR100_CLASSES[pred.item()]
35
+ confidence = conf.item() # Normalize to 0-100%
36
+ return {f"{class_name}": round(confidence, 2)}
37
+
38
+ # Gradio UI
39
+ title = "CIFAR-100 Image Classifier"
40
+ description = "Upload an image (32x32 or larger). The model will predict the top class with confidence score."
41
+
42
+ demo = gr.Interface(
43
+ fn=predict,
44
+ inputs=gr.Image(type="numpy", label="Upload Image"),
45
+ outputs=gr.Label(num_top_classes=1, label="Prediction"),
46
+ title=title,
47
+ description=description,
48
+ examples=[["examples/1.jpg"], ["examples/2.jpg"]],
49
+ allow_flagging="never"
50
+ )
51
+
52
+ if __name__ == "__main__":
53
+ demo.launch()
cifar100_classes.txt ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ apple
2
+ aquarium_fish
3
+ baby
4
+ bear
5
+ beaver
6
+ bed
7
+ bee
8
+ beetle
9
+ bicycle
10
+ bottle
11
+ bowl
12
+ boy
13
+ bridge
14
+ bus
15
+ butterfly
16
+ camel
17
+ can
18
+ castle
19
+ caterpillar
20
+ cattle
21
+ chair
22
+ chimpanzee
23
+ clock
24
+ cloud
25
+ cockroach
26
+ couch
27
+ crab
28
+ crocodile
29
+ cup
30
+ dinosaur
31
+ dolphin
32
+ elephant
33
+ flatfish
34
+ forest
35
+ fox
36
+ girl
37
+ hamster
38
+ house
39
+ kangaroo
40
+ keyboard
41
+ lamp
42
+ lawn_mower
43
+ leopard
44
+ lion
45
+ lizard
46
+ lobster
47
+ man
48
+ maple_tree
49
+ motorcycle
50
+ mountain
51
+ mouse
52
+ mushroom
53
+ oak_tree
54
+ orange
55
+ orchid
56
+ otter
57
+ palm_tree
58
+ pear
59
+ pickup_truck
60
+ pine_tree
61
+ plain
62
+ plate
63
+ poppy
64
+ porcupine
65
+ possum
66
+ rabbit
67
+ raccoon
68
+ ray
69
+ road
70
+ rocket
71
+ rose
72
+ sea
73
+ seal
74
+ shark
75
+ shrew
76
+ skunk
77
+ skyscraper
78
+ snail
79
+ snake
80
+ spider
81
+ squirrel
82
+ streetcar
83
+ sunflower
84
+ sweet_pepper
85
+ table
86
+ tank
87
+ telephone
88
+ television
89
+ tiger
90
+ tractor
91
+ train
92
+ trout
93
+ tulip
94
+ turtle
95
+ wardrobe
96
+ whale
97
+ willow_tree
98
+ wolf
99
+ woman
100
+ worm
examples/1.jpg ADDED

Git LFS Details

  • SHA256: ff848c3d749932be6bebc66a3777f270573586dc470fa3de9356b0896036fb34
  • Pointer size: 132 Bytes
  • Size of remote file: 1.02 MB
examples/2.jpg ADDED

Git LFS Details

  • SHA256: c13bc7c7b4a9f681d0aec4b3194fec110060e8482c7e9e92f08367d13338a0d3
  • Pointer size: 131 Bytes
  • Size of remote file: 541 kB
model.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ from typing import Type, Union, List, Optional
4
+
5
+
6
+ class BasicBlock(nn.Module):
7
+ expansion: int = 1
8
+
9
+ def __init__(
10
+ self,
11
+ in_channels: int,
12
+ out_channels: int,
13
+ stride: int = 1,
14
+ downsample: Optional[nn.Module] = None,
15
+ ) -> None:
16
+ super().__init__()
17
+ self.conv1 = nn.Conv2d(
18
+ in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
19
+ self.bn1 = nn.BatchNorm2d(out_channels)
20
+ self.relu = nn.ReLU(inplace=True)
21
+ self.conv2 = nn.Conv2d(out_channels, out_channels,
22
+ kernel_size=3, stride=1, padding=1, bias=False)
23
+ self.bn2 = nn.BatchNorm2d(out_channels)
24
+ self.downsample = downsample
25
+ self.stride = stride
26
+
27
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
28
+ identity = x
29
+ out = self.conv1(x)
30
+ out = self.bn1(out)
31
+ out = self.relu(out)
32
+ out = self.conv2(out)
33
+ out = self.bn2(out)
34
+ if self.downsample is not None:
35
+ identity = self.downsample(x)
36
+ out += identity
37
+ out = self.relu(out)
38
+ return out
39
+
40
+
41
+ class Bottleneck(nn.Module):
42
+ expansion: int = 4
43
+
44
+ def __init__(
45
+ self,
46
+ in_channels: int,
47
+ out_channels: int,
48
+ stride: int = 1,
49
+ downsample: Optional[nn.Module] = None,
50
+ ) -> None:
51
+ super().__init__()
52
+ width = out_channels
53
+ self.conv1 = nn.Conv2d(
54
+ in_channels, width, kernel_size=1, stride=1, bias=False)
55
+ self.bn1 = nn.BatchNorm2d(width)
56
+ self.conv2 = nn.Conv2d(width, width, kernel_size=3,
57
+ stride=stride, padding=1, bias=False)
58
+ self.bn2 = nn.BatchNorm2d(width)
59
+ self.conv3 = nn.Conv2d(
60
+ width, out_channels * self.expansion, kernel_size=1, stride=1, bias=False)
61
+ self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)
62
+ self.relu = nn.ReLU(inplace=True)
63
+ self.downsample = downsample
64
+ self.stride = stride
65
+
66
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
67
+ identity = x
68
+ out = self.conv1(x)
69
+ out = self.bn1(out)
70
+ out = self.relu(out)
71
+ out = self.conv2(out)
72
+ out = self.bn2(out)
73
+ out = self.relu(out)
74
+ out = self.conv3(out)
75
+ out = self.bn3(out)
76
+ if self.downsample is not None:
77
+ identity = self.downsample(x)
78
+ out += identity
79
+ out = self.relu(out)
80
+ return out
81
+
82
+
83
+ class ResNet(nn.Module):
84
+ def __init__(
85
+ self,
86
+ block: Type[Union[BasicBlock, Bottleneck]],
87
+ layers: List[int],
88
+ num_classes: int = 100,
89
+ ) -> None:
90
+ super().__init__()
91
+ self.in_channels = 64
92
+ # Modified for CIFAR-100 (32x32 images)
93
+ self.conv1 = nn.Conv2d(3, 64, kernel_size=3,
94
+ stride=1, padding=1, bias=False)
95
+ self.bn1 = nn.BatchNorm2d(64)
96
+ self.relu = nn.ReLU(inplace=True)
97
+ self.layer1 = self._make_layer(block, 64, layers[0])
98
+ self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
99
+ self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
100
+ self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
101
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
102
+ self.fc = nn.Linear(512 * block.expansion, num_classes)
103
+
104
+ def _make_layer(
105
+ self,
106
+ block: Type[Union[BasicBlock, Bottleneck]],
107
+ out_channels: int,
108
+ blocks: int,
109
+ stride: int = 1,
110
+ ) -> nn.Sequential:
111
+ downsample = None
112
+ if stride != 1 or self.in_channels != out_channels * block.expansion:
113
+ downsample = nn.Sequential(
114
+ nn.Conv2d(self.in_channels, out_channels * block.expansion,
115
+ kernel_size=1, stride=stride, bias=False),
116
+ nn.BatchNorm2d(out_channels * block.expansion),
117
+ )
118
+
119
+ layers = []
120
+ layers.append(
121
+ block(self.in_channels, out_channels, stride, downsample))
122
+ self.in_channels = out_channels * block.expansion
123
+ for _ in range(1, blocks):
124
+ layers.append(block(self.in_channels, out_channels))
125
+
126
+ return nn.Sequential(*layers)
127
+
128
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
129
+ x = self.conv1(x)
130
+ x = self.bn1(x)
131
+ x = self.relu(x)
132
+ x = self.layer1(x)
133
+ x = self.layer2(x)
134
+ x = self.layer3(x)
135
+ x = self.layer4(x)
136
+ x = self.avgpool(x)
137
+ x = torch.flatten(x, 1)
138
+ x = self.fc(x)
139
+ return x
140
+
141
+
142
+ def resnet18(num_classes: int = 100) -> ResNet:
143
+ return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes)
144
+
145
+
146
+ def resnet34(num_classes: int = 100) -> ResNet:
147
+ return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes)
148
+
149
+
150
+ def resnet50(num_classes: int = 100) -> ResNet:
151
+ return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio
2
+ torch
3
+ torchvision
4
+ Pillow
resnet18_cifar100_best.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23c3eac02b21c620cdfeeafff569534c716f9c9c7c61984ec5220c81475f4edd
3
+ size 89862129