. Mnist Using Cnn Theory

[2]:
123456789101112
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import datasets,transforms
from torchvision.utils import make_grid

import numpy as np 
import pandas as pd
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
[3]:
1
transform=transforms.ToTensor()
[4]:
1
train_data=datasets.MNIST(root='../Data',train=True,download=True,transform=transform)
[5]:
1
test_data=datasets.MNIST(root='../Data',train=False,download=True,transform=transform)
[6]:
12
train_data
Out[6]:
Dataset MNIST Number of datapoints: 60000 Root location: ../Data Split: Train StandardTransform Transform: ToTensor()
[7]:
1
test_data
Out[7]:
Dataset MNIST Number of datapoints: 10000 Root location: ../Data Split: Test StandardTransform Transform: ToTensor()
[8]:
123
train_loader=DataLoader(train_data,batch_size=10,shuffle=True)
test_loader=DataLoader(test_data,batch_size=10,shuffle=False)
[9]:
1234567891011121314
# we will have convolution layer 
conv1=nn.Conv2d(1,4,3,1)
# 1 input channel since grey scale images 
# 6 output channel for feature channel or 6 filter (output channel)
# 3 means above 6 filters are 3*3 filters
# 1 step size , strids 

conv2=nn.Conv2d(4,6,3,1)
# This layer will take input from above input layer 
# 6 filters from previous layers 
# 16 filter to this layer (arbitary choice)
# 3 means above 6 filters are 3*3 filters
# 1 step size , strids 
[ ]:
1
[10]:
12
for i ,(X_train,y_train) in enumerate(train_data):
    break
[11]:
1
X_train.shape # this is the shape of 1 image but this is not how we will receive from data loader 
Out[11]:
torch.Size([1, 28, 28])
[12]:
123
# since data loader is going to give us images in batch so there will be a extra dimension added to above X-train
# we can simulate the same using view method as follows adding just 1 image in batch instead of 10 
X_train.view(1,1,28,28).shape
Out[12]:
torch.Size([1, 1, 28, 28])
[13]:
1
x=X_train.view(1,1,28,28)
[14]:
12
# lets pass this x to the first convolution layer and the relu activation 
x=F.relu(conv1(x))
[15]:
12345
x.shape # see the shape now 4 is the filters we gave 
# but why 26 * 26 
# since we are doing a convolution we are loosing border information here hence 28 reduce to 26
# therefore we need to do padding here 
Out[15]:
torch.Size([1, 4, 26, 26])
[16]:
12345
# we will now pass this to a polling layer 
x=F.max_pool2d(x,2,2)
# kernal size 2
# stride 2
[17]:
1
x.shape  # due to kernal 2*2 we are cutting it into half 
Out[17]:
torch.Size([1, 4, 13, 13])
[18]:
1
x=F.relu(conv2(x))  # second conv 
[19]:
1
x=F.max_pool2d(x,2,2)
[20]:
1
x.shape  # 5.5 rounded to 5
Out[20]:
torch.Size([1, 6, 5, 5])
[22]:
123
# finally this is sent to outputlayer but befor this we will need to flatten this
x.view(-1,6*5*5).shape
Out[22]:
torch.Size([1, 150])
[23]:
12345678910111213141516171819202122
class ConvolutionIMNST(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1=nn.Conv2d(1,6,3,1)
        self.conv2=nn.Conv2d(6,16,3,1)
        self.fc1=nn.Linear(5*5*16,120)
        self.fc2=nn.Linear(120,84)
        self.fc3=nn.Linear(84,10)
    
    def forward(self,X): 
        X=F.relu(self.conv1(X))
        X=F.max_pool2d(X,2,2)
        X=F.relu(self.conv2(X))
        X=F.max_pool2d(X,2,2)

        X=X.view(-1,16*5*5)
        X=F.relu(self.fc1(X))
        X=F.relu(self.fc2(X))
        X=self.fc3(X)

        return F.log_softmax(X,dim=1)
[24]:
123
torch.manual_seed(42)
model=ConvolutionIMNST()
model
Out[24]:
ConvolutionIMNST( (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1)) (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1)) (fc1): Linear(in_features=400, out_features=120, bias=True) (fc2): Linear(in_features=120, out_features=84, bias=True) (fc3): Linear(in_features=84, out_features=10, bias=True) )
[26]:
12
for prm in model.parameters():
    print(prm.numel())
stdout
54 6 864 16 48000 120 10080 84 840 10
[27]:
12
criterion=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.001)
[ ]:
1234567891011121314151617181920212223
import time
start_time=time.time()

# VARIABLES
epochs=5
train_losses=[]
test_losses=[]
train_correct=[]
test_correct=[]

for i in range(epochs):
    trn_corr=0
    tst_corr=0
    for b,(X_train,y_train) in enumerate(train_loader):
        b+=1
        y_pred=model(X_train)
        loss=criterion(y_pred,y_train)

        predicted=torch.max(y_pred.data,1)[1]
        batch_correct=(predicted==y_train).sum()

current_time =time.time() - start_time
print(f"Training took {total/60} minutes")