. 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_dataOut[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).shapeOut[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 5Out[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()
modelOut[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")