shyamgupta196 commited on
Commit
10367e5
1 Parent(s): 24014e2
Files changed (4) hide show
  1. CatVsDogTrain.py +398 -0
  2. CatVsDogsModel.pth +3 -0
  3. app.py +29 -0
  4. requirements.txt +2 -0
CatVsDogTrain.py ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ In this TorchDaily we will TRAIN
3
+ A MODEL USING TRANSFER LEARNING
4
+ Cats Vs Dogs Dataset
5
+
6
+ EARLIER ACC==14% OR LESS
7
+ NOW ITS 70% AND MORE
8
+ THE POWER OF ALEXNET (PRETRAINED MODELS IS VISIBLE)
9
+ DATE ==> 10-05-21
10
+ """
11
+ import torch
12
+ import torch.nn as nn
13
+ from torch.utils.data import DataLoader
14
+ import matplotlib.pyplot as plt
15
+ from torchvision import transforms, datasets, models
16
+ import torchvision
17
+ from tqdm import tqdm
18
+ import os
19
+ import PIL.Image as Image
20
+ import time
21
+
22
+ import torch, torchvision
23
+ from torchvision import datasets, models, transforms
24
+ import torch.nn as nn
25
+ import torch.optim as optim
26
+ from torch.utils.data import DataLoader
27
+ import time
28
+
29
+ # from torchsummary import summary
30
+
31
+ import numpy as np
32
+ import matplotlib.pyplot as plt
33
+ import os
34
+
35
+ from PIL import Image
36
+
37
+
38
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
39
+ print(device)
40
+ # prepare data
41
+ convert = transforms.Compose(
42
+ [
43
+ transforms.Resize((128, 128)),
44
+ transforms.RandomHorizontalFlip(0.2),
45
+ transforms.ToTensor(),
46
+ ]
47
+ )
48
+
49
+ # dataloader
50
+
51
+ data = datasets.ImageFolder(root="PetImages/", transform=convert)
52
+ Loader = DataLoader(data, batch_size=64, shuffle=True)
53
+
54
+ MAP = {0: "Cat", 1: "Dog"}
55
+
56
+ ##UNCOMMENT FOR SEEING THE DATA IMAGES
57
+ # fig, ax = plt.subplots(8, 8, figsize=(20, 20))
58
+ # fig.suptitle("Dogs And Cats IMages")
59
+
60
+ # for i, (img, lab) in zip(range(0, 8 * 8), Loader):
61
+ # x = i // 8
62
+ # y = i % 8
63
+ # print(f"{x},{y}")
64
+ # ax[x, y].imshow(img[i].squeeze().permute(1,2,0))
65
+ # ax[x, y].set_title(f"{lab[i]}")
66
+ # ax[x, y].axis("off")
67
+ # plt.show()
68
+
69
+ # # Add on classifier
70
+ # # HOW TO CHANGE THE INPUT LAYER WHICH ACCEPTS THE 224*224 INPUT
71
+ # # I WANNA CHANGE THAT TO 128*128 THIS SIZE WILL SUFFICE
72
+ # We Use AlexNet for transfer learning
73
+ ##answers below
74
+
75
+ alexnet = torchvision.models.alexnet(pretrained=True)
76
+ for param in alexnet.parameters():
77
+ param.requires_grad = False
78
+
79
+ # Add a avgpool here
80
+ avgpool = nn.AdaptiveAvgPool2d((7, 7))
81
+
82
+ # Replace the classifier layer
83
+ # to customise it according to our output
84
+ alexnet.classifier = nn.Sequential(
85
+ nn.Linear(256 * 7 * 7, 1024),
86
+ nn.Linear(1024, 256),
87
+ nn.Linear(256, 2),
88
+ )
89
+ # putting model in a training mode
90
+ alexnet.train()
91
+
92
+ print(alexnet)
93
+ criterion = nn.CrossEntropyLoss()
94
+ optimizer = torch.optim.Adam(alexnet.parameters(), lr=0.001)
95
+ EPOCHS = 4
96
+
97
+ TRAIN = False
98
+ losses = []
99
+
100
+
101
+ def train_and_validate(model, loss_criterion, optimizer, epochs=25):
102
+ """
103
+ Function to train and validate
104
+ Parameters
105
+ :param model: Model to train and validate
106
+ :param loss_criterion: Loss Criterion to minimize
107
+ :param optimizer: Optimizer for computing gradients
108
+ :param epochs: Number of epochs (default=25)
109
+
110
+ Returns
111
+ model: Trained Model with best validation accuracy
112
+ history: (dict object): Having training loss, accuracy and validation loss, accuracy
113
+ """
114
+
115
+ start = time.time()
116
+ history = []
117
+ best_acc = 0.0
118
+
119
+ for epoch in range(epochs):
120
+ epoch_start = time.time()
121
+ print("Epoch: {}/{}".format(epoch + 1, epochs))
122
+
123
+ # Set to training mode
124
+ # model.train()
125
+
126
+ # Loss and Accuracy within the epoch
127
+ train_loss = 0.0
128
+ train_acc = 0.0
129
+
130
+ valid_loss = 0.0
131
+ valid_acc = 0.0
132
+
133
+ for i, (inputs, labels) in enumerate(Loader):
134
+
135
+ inputs = inputs.to(device)
136
+ labels = labels.to(device)
137
+
138
+ # Clean existing gradients
139
+ optimizer.zero_grad()
140
+
141
+ # Forward pass - compute outputs on input data using the model
142
+ x = alexnet.features(inputs)
143
+ x = avgpool(x)
144
+ x = x.view(-1, 256 * 7 * 7)
145
+ outputs = alexnet.classifier(x)
146
+
147
+ # Compute loss
148
+ loss = loss_criterion(outputs, labels)
149
+
150
+ # Backpropagate the gradients
151
+ loss.backward()
152
+
153
+ # Update the parameters
154
+ optimizer.step()
155
+
156
+ # Compute the total loss for the batch and add it to train_loss
157
+ train_loss += loss.item() * inputs.size(0)
158
+
159
+ # Compute the accuracy
160
+ ret, predictions = torch.max(outputs.data, 1)
161
+ correct_counts = predictions.eq(labels.data.view_as(predictions))
162
+
163
+ # Convert correct_counts to float and then compute the mean
164
+ acc = torch.mean(correct_counts.type(torch.FloatTensor))
165
+
166
+ # Compute total accuracy in the whole batch and add to train_acc
167
+ train_acc += acc.item() * inputs.size(0)
168
+
169
+ # print("Batch number: {:03d}, Training: Loss: {:.4f}, Accuracy: {:.4f}".format(i, loss.item(), acc.item()))
170
+
171
+ # Validation - No gradient tracking needed
172
+ with torch.no_grad():
173
+
174
+ # Set to evaluation mode
175
+ model.eval()
176
+
177
+ # Validation loop
178
+ for j, (inputs, labels) in enumerate(valid_data_loader):
179
+ inputs = inputs.to(device)
180
+ labels = labels.to(device)
181
+
182
+ # Forward pass - compute outputs on input data using the model
183
+ outputs = model(inputs)
184
+
185
+ # Compute loss
186
+ loss = loss_criterion(outputs, labels)
187
+
188
+ # Compute the total loss for the batch and add it to valid_loss
189
+ valid_loss += loss.item() * inputs.size(0)
190
+
191
+ # Calculate validation accuracy
192
+ ret, predictions = torch.max(outputs.data, 1)
193
+ correct_counts = predictions.eq(labels.data.view_as(predictions))
194
+
195
+ # Convert correct_counts to float and then compute the mean
196
+ acc = torch.mean(correct_counts.type(torch.FloatTensor))
197
+
198
+ # Compute total accuracy in the whole batch and add to valid_acc
199
+ valid_acc += acc.item() * inputs.size(0)
200
+
201
+ # print("Validation Batch number: {:03d}, Validation: Loss: {:.4f}, Accuracy: {:.4f}".format(j, loss.item(), acc.item()))
202
+
203
+ # Find average training loss and training accuracy
204
+ avg_train_loss = train_loss / train_data_size
205
+ avg_train_acc = train_acc / train_data_size
206
+
207
+ # Find average training loss and training accuracy
208
+ avg_valid_loss = valid_loss / valid_data_size
209
+ avg_valid_acc = valid_acc / valid_data_size
210
+
211
+ history.append([avg_train_loss, avg_valid_loss, avg_train_acc, avg_valid_acc])
212
+
213
+ epoch_end = time.time()
214
+
215
+ print(
216
+ "Epoch : {:03d}, Training: Loss: {:.4f}, Accuracy: {:.4f}%, \n\t\tValidation : Loss : {:.4f}, Accuracy: {:.4f}%, Time: {:.4f}s".format(
217
+ epoch + 1,
218
+ avg_train_loss,
219
+ avg_train_acc * 100,
220
+ avg_valid_loss,
221
+ avg_valid_acc * 100,
222
+ epoch_end - epoch_start,
223
+ )
224
+ )
225
+
226
+ # Save if the model has best accuracy till now
227
+ torch.save(model, "TrainLoopImproveCatsDogs.pth")
228
+
229
+ return model, history
230
+
231
+
232
+ if TRAIN:
233
+ trained_model, history = train_and_validate(alexnet, criterion, optimizer, EPOCHS)
234
+ plt.plot(losses)
235
+ plt.show()
236
+ history = np.array(history)
237
+ plt.plot(history[:, 0:2])
238
+ plt.legend(["Tr Loss", "Val Loss"])
239
+ plt.xlabel("Epoch Number")
240
+ plt.ylabel("Loss")
241
+ plt.ylim(0, 1)
242
+ plt.savefig(dataset + "_loss_curve.png")
243
+ plt.show()
244
+ plt.plot(history[:, 2:4])
245
+ plt.legend(["Tr Accuracy", "Val Accuracy"])
246
+ plt.xlabel("Epoch Number")
247
+ plt.ylabel("Accuracy")
248
+ plt.ylim(0, 1)
249
+ plt.savefig(dataset + "_accuracy_curve.png")
250
+ plt.show()
251
+
252
+
253
+ TEST = False
254
+
255
+ history = []
256
+
257
+
258
+ def test():
259
+ test = datasets.ImageFolder(root="PetTest/", transform=convert)
260
+ testLoader = DataLoader(test, batch_size=16, shuffle=False)
261
+ checkpoint = torch.load("catsvdogs.pth")
262
+ alexnet.load_state_dict(checkpoint["state_dict"])
263
+ optimizer.load_state_dict(checkpoint["optimizer"])
264
+ for params in alexnet.parameters():
265
+ params.requires_grad == False
266
+ print(alexnet)
267
+
268
+ with torch.no_grad():
269
+
270
+ # Set to evaluation mode
271
+ alexnet.eval()
272
+ train_data_size = 101
273
+ valid_data_size = 101
274
+ # Validation loop
275
+ # Loss and Accuracy within the epoch
276
+ valid_loss = 0.0
277
+ valid_acc = 0.0
278
+ for j, (inputs, labels) in enumerate(testLoader):
279
+ inputs = inputs.to(device)
280
+ labels = labels.to(device)
281
+
282
+ # Forward pass - compute outputs on input data using the model
283
+ x = alexnet.features(inputs)
284
+ x = avgpool(x)
285
+ x = x.view(-1, 256 * 7 * 7)
286
+ outputs = alexnet.classifier(x)
287
+
288
+ # Compute loss
289
+ loss = criterion(outputs, labels)
290
+
291
+ # Compute the total loss for the batch and add it to valid_loss
292
+ valid_loss += loss.item() * inputs.size(0)
293
+
294
+ # Calculate validation accuracy
295
+ ret, predictions = torch.max(outputs.data, 1)
296
+ correct_counts = predictions.eq(labels.data.view_as(predictions))
297
+
298
+ # Convert correct_counts to float and then compute the mean
299
+ acc = torch.mean(correct_counts.type(torch.FloatTensor))
300
+
301
+ # Compute total accuracy in the whole batch and add to valid_acc
302
+ valid_acc += acc.item() * inputs.size(0)
303
+
304
+ print(
305
+ """Validation Batch number: {:03d},
306
+ Validation: Loss: {:.4f},
307
+ Accuracy: {:.4f}""".format(
308
+ j, loss.item(), acc.item()
309
+ )
310
+ )
311
+
312
+ # Find average training loss and training accuracy
313
+ avg_valid_loss = valid_loss / valid_data_size
314
+ avg_valid_acc = valid_acc / valid_data_size
315
+
316
+ history.append([avg_valid_loss, avg_valid_acc])
317
+ print(
318
+ " Training: Loss: {:.4f}, Accuracy: {:.4f}%, \n\t\tValidation : Loss : {:.4f}, Accuracy: {:.4f}%".format(
319
+ avg_train_loss,
320
+ avg_train_acc * 100,
321
+ avg_valid_loss,
322
+ avg_valid_acc * 100,
323
+ )
324
+ )
325
+ plt.plot(valid_acc)
326
+ plt.plot(valid_loss)
327
+ plt.show()
328
+
329
+
330
+ if TEST:
331
+ test()
332
+ print("Validation Complete")
333
+ with open("ModelHistory.txt", "w") as f:
334
+ for i in history:
335
+ f.writelines(f"{i}")
336
+ print("Validation Complete")
337
+
338
+ ## This model reported a accuracy of 97%(on DOGS ONLY) using AlexNet
339
+ ## the Pros of using a pretrained model is clearly seen here
340
+ ## date -- 13th April 2021 (thursday)
341
+ ####ACCURACY AND OTHER THINGS TOO TO BE APPENDED SOON ######
342
+
343
+
344
+ PREDICT = True
345
+
346
+
347
+ def predict(model, test_image_name):
348
+ """
349
+ Function to predict the class of a single test image
350
+ Parameters
351
+ :param model: Model to test
352
+ :param test_image_name: Test image
353
+
354
+ """
355
+ # try:
356
+ transform = transforms.Compose(
357
+ [transforms.Resize((128, 128)), transforms.ToTensor()]
358
+ )
359
+ test_image = Image.open(test_image_name)
360
+ test_image_tensor = transform(test_image).to(device)
361
+ plt.imshow(test_image)
362
+ plt.axis("off")
363
+ plt.imshow(test_image_tensor.cpu().squeeze().permute(1, 2, 0))
364
+ plt.show()
365
+
366
+ with torch.no_grad():
367
+ model.eval()
368
+ test_image_tensor = test_image_tensor.unsqueeze(0)
369
+ print(test_image_tensor.shape)
370
+ x = alexnet.features(test_image_tensor)
371
+ x = avgpool(x)
372
+ x = x.view(-1, 256 * 7 * 7)
373
+ out = alexnet.classifier(x)
374
+ ###THESE ARE SCORES OF THE ACC. ###
375
+ ### UNCOMMENT TO SEE THE SCORES OF EACH CLASS ###
376
+ # ps = torch.exp(out)
377
+ # print(f'ps: {ps}')
378
+ # topk, topclass = ps.topk(2, dim=1)
379
+ # print(f'ps.topk: {ps.topk(2, dim=1)}')
380
+ # print(f'topclass: {topclass}')
381
+ print("Predcition", MAP[out.numpy().argmax()])
382
+
383
+ # print(f"out: {out.numpy().argmax()}")
384
+
385
+
386
+ # except Exception as e:
387
+ # print(e)
388
+
389
+ if PREDICT:
390
+ checkpoint = torch.load(
391
+ "ImprovedCatVsDogsModel.pth", map_location=torch.device("cpu")
392
+ )
393
+ alexnet.load_state_dict(checkpoint["state_dict"])
394
+ alexnet = alexnet.to(device)
395
+ optimizer.load_state_dict(checkpoint["optimizer"])
396
+ for params in alexnet.parameters():
397
+ params.requires_grad == False
398
+ print(predict(alexnet, "PetTest/Cat/12401.jpg"))
CatVsDogsModel.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:37c1a19e5a1bb9f90fc1afd7f970143a0df3ff0f06c8b6917630fc40aa423398
3
+ size 167196523
app.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import gradio as gr
3
+ import torch
4
+ from timm.data import resolve_data_config
5
+ from timm.data.transforms_factory import create_transform
6
+
7
+ LABELS = [0:'Cat', 1:'Dog']
8
+ model = torch.load('CatVsDogModel.py')
9
+ model.eval()
10
+ transform = create_transform(**resolve_data_config({},model=model))
11
+
12
+
13
+ def predict(img):
14
+ img = img.convert('RGB')
15
+ img = transform(img).unsqueeze(0)
16
+ with torch.no_grad():
17
+ out= model(img)
18
+ probability = torch.nn.functional.softmax(out[0],dim=0)
19
+
20
+ values, indices = torch.topk(probability,k=2)
21
+ return {LABELS[i]: v.item() for i,v in zip(indices,values)}
22
+
23
+
24
+ transform = create_transform(**resolve_data_config({},model=model))
25
+ # we do not need to train model , hence using model.eval() to use it only for inference
26
+ model.eval()
27
+
28
+ iface = gr.Interface(fn=predict, inputs=gr.inputs.Image(type='pil'), outputs="label").launch()
29
+ iface.launch()
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ timm
2
+ gradio