# -*- coding: utf-8 -*-
"""CNN(mnist).ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/1_4EIIBRbLBfS5tDz6VSgPIIpSv1t03Y7
CNN are mainly used to classify the images
A basic CNN requires two additional layers called convoluation and pooling before the FNN
CNN involves a Kernel
Kernel is sliding/convuling matrix across the image with two operations
1. element-wise multiplication
2. summation
Now comes the pooling part mainly there are two types of pooling
1. Max pooling- getting the max element after the kernel iteration over the image
2. average pooling- getting the average of all the elements in the matrix
Now comes stride- it means number of steps in each convulation. By default it is 1.
After using stride we can see that the input size becomes lesser so we add zeros symetrically in the matrix so the output becomes the same dimension of input
The dimension of the output after applying all these
O=(W-K+2P)/25 + 1
W=input
K=kernel size
P=padding=(K-1)/2
S=stride
# Importing libraries
"""
import torch
import torch.nn as nn
from torchvision import transforms,datasets
from torch.utils.data import dataset, DataLoader
import torchvision.datasets as dsets
"""# Loading the data """
#we will be using the mnist dataset for this purpose
train_dataset = dsets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data',
train=False,
transform=transforms.ToTensor())
#making our dataset iterable
batch_size = 100
n_iters = 3000
num_epochs = n_iters / (len(train_dataset) / batch_size)
num_epochs = int(num_epochs)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
"""# Defining our model """
class CNN(nn.Module):
def __init__(self):
super(CNN,self).__init__()
#defining the layers
self.block1=nn.Sequential(nn.Conv2d(1,16,kernel_size=(5,5),stride=1,padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2))
#output after this operation
#(28-5+2/1 +1 =28 then max pooling 28/2=14)
self.block2=nn.Sequential(nn.Conv2d(16,32,kernel_size=(5,5),stride=1,padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2))
#output after this
#(14-5+2*2/1 +1 = 13+1=14 then 14/2= 7)
self.layer=nn.Linear(32*7*7,10)
def forward(self,x):
x=self.block1(x)
x=self.block2(x)
#flatteing the output
x = x.view(x.size(0), -1)
#now feeding inot the linear network
x = self.layer(x)
return x
#making instance
model=CNN()
print(model)
"""# Training the model"""
#initialising the loss and optimizer
criterion=nn.CrossEntropyLoss()
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
print(model.parameters())
print(len(list(model.parameters())))
# Convolution 1: 16 Kernels
print(list(model.parameters())[0].size())
# Convolution 1 Bias: 16 Kernels
print(list(model.parameters())[1].size())
# Convolution 2: 32 Kernels with depth = 16
print(list(model.parameters())[2].size())
# Convolution 2 Bias: 32 Kernels with depth = 16
print(list(model.parameters())[3].size())
# Fully Connected Layer 1
print(list(model.parameters())[4].size())
# Fully Connected Layer Bias
print(list(model.parameters())[5].size())
#lets begin the training
iter=0
for epochs in range(num_epochs):
for i,(images,labels) in enumerate(train_loader):
#loading the images
images.requires_grad_()
#first clearning the parameters
optimizer.zero_grad()
#calclauting the output and loss
output=model(images)
loss=criterion(output,labels)
#backprapgating the loss
loss.backward()
#updating the parameters
optimizer.step()
iter+=1
#printing for every 500 iterations
if iter%500==0:
# Calculate Accuracy
correct = 0
total = 0
#now iterate through the test dataset
for images,labels in test_loader:
images = images.requires_grad_()
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
accuracy = 100 * correct / total
# Print Loss
print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accuracy))
"""Accuracy came out to 96.63
# Model 2
This involves average pooling layer
"""
class CNN2(nn.Module):
def __init__(self):
super().__init__()
#defining the layers
self.block1=nn.Sequential(nn.Conv2d(1,16,kernel_size=(5,5),stride=1,padding=2),
nn.ReLU(),
nn.AvgPool2d(kernel_size=2))
#output after this operation
#(28-5+2/1 +1 =28 then max pooling 28/2=14)
self.block2=nn.Sequential(nn.Conv2d(16,32,kernel_size=(5,5),stride=1,padding=2),
nn.ReLU(),
nn.AvgPool2d(kernel_size=2))
#output after this
#(14-5+2*2/1 +1 = 13+1=14 then 14/2= 7)
self.layer=nn.Linear(32*7*7,10)
def forward(self,x):
x=self.block1(x)
x=self.block2(x)
#flatteing the output
x = x.view(x.size(0), -1)
#now feeding inot the linear network
x = self.layer(x)
return x
#making instance
model2=CNN2()
print(model2)
learning_rate = 0.01
optimizer = torch.optim.SGD(model2.parameters(), lr=learning_rate)
#lets begin the training
iter=0
for epochs in range(num_epochs):
for i,(images,labels) in enumerate(train_loader):
#loading the images
images.requires_grad_()
#first clearning the parameters
optimizer.zero_grad()
#calclauting the output and loss
output=model2(images)
loss=criterion(output,labels)
#backprapgating the loss
loss.backward()
#updating the parameters
optimizer.step()
iter+=1
#printing for every 500 iterations
if iter%500==0:
# Calculate Accuracy
correct = 0
total = 0
#now iterate through the test dataset
for images,labels in test_loader:
images = images.requires_grad_()
outputs = model2(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
accuracy = 100 * correct / total
# Print Loss
print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accuracy))
"""Accuracy came out to be 93 %
# Model 3
This involves vaild pooling which means smaller output size
"""
class CNN3(nn.Module):
def __init__(self):
super(CNN3, self).__init__()
# Convolution 1
self.cnn1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5, stride=1, padding=0)
self.relu1 = nn.ReLU()
# Max pool 1
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
# Convolution 2
self.cnn2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, stride=1, padding=0)
self.relu2 = nn.ReLU()
# Max pool 2
self.maxpool2 = nn.MaxPool2d(kernel_size=2)
# Fully connected 1 (readout)
self.fc1 = nn.Linear(32 * 4 * 4, 10)
def forward(self, x):
# Convolution 1
out = self.cnn1(x)
out = self.relu1(out)
# Max pool 1
out = self.maxpool1(out)
# Convolution 2
out = self.cnn2(out)
out = self.relu2(out)
# Max pool 2
out = self.maxpool2(out)
# Resize
# Original size: (100, 32, 7, 7)
# out.size(0): 100
# New out size: (100, 32*7*7)
out = out.view(out.size(0), -1)
# Linear function (readout)
out = self.fc1(out)
return out
#making instance
model3=CNN3()
print(model3)
learning_rate = 0.01
optimizer = torch.optim.SGD(model3.parameters(), lr=learning_rate)
#lets begin the training
iter=0
for epochs in range(num_epochs):
for i,(images,labels) in enumerate(train_loader):
#loading the images
images.requires_grad_()
#first clearning the parameters
optimizer.zero_grad()
#calclauting the output and loss
output=model3(images)
loss=criterion(output,labels)
#backprapgating the loss
loss.backward()
#updating the parameters
optimizer.step()
iter+=1
#printing for every 500 iterations
if iter%500==0:
# Calculate Accuracy
correct = 0
total = 0
#now iterate through the test dataset
for images,labels in test_loader:
images = images.requires_grad_()
outputs = model3(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
accuracy = 100 * correct / total
# Print Loss
print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accuracy))
"""Accuracy is 96 for the model 3
We can see in the above models the model with max pooling and padding=1 gave the best accuracy
"""