Professional Documents
Culture Documents
dinushasan / courseproject04 0 0
2 months ago
In [2]:
In [3]:
import opendatasets as od
In [4]:
Choose Files No file chosen Upload widget is only available when the cell has been executed in the
current browser session. Please rerun this cell to enable.
In [5]:
od.download('https://www.kaggle.com/chetankv/dogs-cats-images')
In [6]:
import os
import torch
import torchvision
import tarfile
from torchvision.datasets.utils import download_url
f t h til d t i t d lit
from torch.utils.data import random_split
In [7]:
project_name='courseproject04'
In [8]:
data_dir = './dogs-cats-images/dataset'
print(os.listdir(data_dir))
classes = os.listdir(data_dir + "/training_set")
print(classes)
['training_set', 'test_set']
['dogs', 'cats']
In [9]:
In [10]:
In [11]:
trainset = './dogs-cats-images/dataset/training_set'
In [12]:
In [13]:
len(trainset)
Out[13]:
39
In [14]:
testset = './dogs-cats-images/dataset/test_set'
In [15]:
1000
1000
In [16]:
len(testset)
Out[16]:
35
In [18]:
In [19]:
Looping through the dataset and getting the sizes of first 10 images
In [20]:
im_count = 0
for image,_ in dataset:
im_count += 1
print(image.shape)
if im count == 10:
if im_count == 10:
break
In [21]:
height = []
width = []
for image,_ in dataset:
height.append(image.shape[1])
width.append(image.shape[2])
print("minimum height: {}, maximum height: {}, minimum width: {}, maximum width: {}".format(m
minimum height: 41, maximum height: 768, minimum width: 57, maximum width: 1050
As the minimum height of an image of dataset is 41, I transform them to size of 40 x 40 to avoid problems of the shapes
of images
In [22]:
In [23]:
In [24]:
len(train_ds)
Out[24]:
8000
In [25]:
len(valid_ds)
Out[25]:
2000
In [26]:
im_count = 0
for image,_ in train_ds:
im_count += 1
print(image.shape)
if im_count == 10:
break
In [27]:
height = []
width = []
for image,_ in train_ds:
height.append(image.shape[1])
width.append(image.shape[2])
print("minimum height: {}, maximum height: {}, minimum width: {}, maximum width: {}".format(m
minimum height: 40, maximum height: 40, minimum width: 40, maximum width: 40
In [28]:
In [29]:
print(train_ds.classes)
['cats', 'dogs']
In [30]:
print(len(train_ds.classes))
In [31]:
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
matplotlib.rcParams['figure.facecolor'] = '#ffffff'
In [32]:
def show_example(img, label):
print('Label: ', train_ds.classes[label], "("+str(label)+")")
plt.imshow(img.permute(1, 2, 0))
In [33]:
show_example(*train_ds[0])
In [34]:
show_example(*train_ds[6000])
In [ ]:
In [ ]:
import jovian
In [ ]:
[ ]:
jovian.commit(project=project_name)
In [35]:
batch_size = 128
In [36]:
In [37]:
def show_batch(dl):
for images, labels in dl:
fig, ax = plt.subplots(figsize=(14, 14))
ax.set_xticks([]); ax.set_yticks([])
ax.imshow(make_grid(images[:32], nrow=8).permute(1, 2, 0).clamp(0,1))
break
In [38]:
show_batch(train_dl)
In [39]:
In [39]:
import torch.nn as nn
import torch.nn.functional as F
In [40]:
In [41]:
simple_model = nn.Sequential(
nn.Conv2d(3, 8, kernel_size=3, stride=1, padding=1),
nn.MaxPool2d(2, 2)
)
In [42]:
Extending an ImageClassificationBase class which contains helper methods for training & validation
In [43]:
class ImageClassificationBase(nn.Module):
def training_step(self, batch):
images, labels = batch
out = self(images) # Generate predictions
loss = F.cross_entropy(out, labels) # Calculate loss
return loss
Using nn.Sequential to chain the layers and activations functions into a single network architecture.
In [44]:
class PetsModel(ImageClassificationBase):
def __init__(self):
super().__init__()
self.network = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2), # output: 64 x 20 x 20
nn.Flatten(),
nn.Linear(256*5*5, 2048),
nn.ReLU(),
nn.Linear(2048, 1024),
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 2))
In [45]:
model = PetsModel()
model
Out[45]:
PetsModel(
(network): Sequential(
(0): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU()
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(6): ReLU()
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU()
(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU()
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU()
(14): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(15): Flatten(start_dim=1, end_dim=-1)
(16): Linear(in_features=6400, out_features=2048, bias=True)
(17): ReLU()
(18): Linear(in_features=2048, out_features=1024, bias=True)
(19): ReLU()
(20): Linear(in_features=1024, out_features=512, bias=True)
(21): ReLU()
(22): Linear(in_features=512, out_features=2, bias=True)
)
)
In [46]:
Using GPU
In [47]:
def get_default_device():
""" i k if il bl l """
"""Pick GPU if available, else CPU"""
if torch.cuda.is_available():
return torch.device('cuda')
else:
return torch.device('cpu')
class DeviceDataLoader():
"""Wrap a dataloader to move data to a device"""
def __init__(self, dl, device):
self.dl = dl
self.device = device
def __iter__(self):
"""Yield a batch of data after moving it to device"""
for b in self.dl:
yield to_device(b, self.device)
def __len__(self):
"""Number of batches"""
return len(self.dl)
In [48]:
device = get_default_device()
device
Out[48]:
device(type='cuda')
In [49]:
In [50]:
@torch.no_grad()
def evaluate(model, val_loader):
model.eval()
outputs = [model.validation_step(batch) for batch in val_loader]
return model.validation_epoch_end(outputs)
def fit(epochs lr model train loader val loader opt func=torch optim SGD):
def fit(epochs, lr, model, train_loader, val_loader, opt_func torch.optim.SGD):
history = []
optimizer = opt_func(model.parameters(), lr)
for epoch in range(epochs):
# Training Phase
model.train()
train_losses = []
for batch in train_loader:
loss = model.training_step(batch)
train_losses.append(loss)
loss.backward()
optimizer.step()
optimizer.zero_grad()
# Validation phase
result = evaluate(model, val_loader)
result['train_loss'] = torch.stack(train_losses).mean().item()
model.epoch_end(epoch, result)
history.append(result)
return history
In [51]:
In [52]:
evaluate(model, val_dl)
Out[52]:
{'val_acc': 0.48828125, 'val_loss': 0.6933683156967163}
In [53]:
num_epochs = 10
opt_func = torch.optim.Adam
lr = 0.0001
In [54]:
jovian.reset()
jovian.log_hyperparams({
'num_epochs': num_epochs,
'opt_func': opt_func.__name__,
'batch_size': batch_size,
'lr': lr,
})
In [56]:
In [ ]:
In [57]:
evaluate(model, val_dl)
Out[57]:
{'val_acc': 0.8261343240737915, 'val_loss': 0.42191097140312195}
In [58]:
jovian.log_metrics(train_loss=history[-1]['train_loss'],
val_loss=history[-1]['val_loss'],
val_acc=history[-1]['val_acc'])
[jovian] Metrics logged.
In [59]:
def plot_accuracies(history):
accuracies = [x['val_acc'] for x in history]
plt.plot(accuracies, '-x')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.title('Accuracy vs. No. of epochs');
In [60]:
plot_accuracies(history)
In [61]:
def plot_losses(history):
train_losses = [x.get('train_loss') for x in history]
val_losses = [x['val_loss'] for x in history]
plt.plot(train_losses, '-bx')
plt.plot(val_losses, '-rx')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['Training', 'Validation'])
plt.title('Loss vs. No. of epochs');
In [62]:
plot_losses(history)
In [64]:
jovian.commit(project=project_name)
In [68]:
In [69]:
In [72]:
In [73]:
In [74]:
jovian.commit(project=project_name)
In [75]:
jovian.reset()
jovian.log_hyperparams({
'num_epochs': num_epochs,
'opt_func': opt_func.__name__,
'batch_size': batch_size,
'lr': lr,
})
In [77]:
jovian.log_metrics(train_loss=history[-1]['train_loss'],
val_loss=history[-1]['val_loss'],
val_acc=history[-1]['val_acc'])
jovian.commit(project=project_name)