Bikash Santra
Indian Statistical Institute, Kolkata
# Pytorch libraries
import torch
import torchvision
import torchvision.transforms as transforms
# For displaying images and numpy operations
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
# For CNN Purpose
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
# Loss function and optimizer
import torch.optim as optim
import scipy.io
torch.cuda.set_device(1)
torch.cuda.empty_cache()
# Dataloader
# For fully connected network 20*20
transform = transforms.Compose(
[transforms.Resize(20),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=32,
shuffle=True, num_workers=4)
testset = torchvision.datasets.MNIST(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=32,
shuffle=False, num_workers=4)
mnistClasses = ('zero', 'one', 'two', 'three',
'four', 'five', 'six', 'seven', 'eight', 'nine')
# Visualizing the train images
def imshow(inp, title=None):
"""Imshow for Tensor."""
inp = inp.numpy().transpose((1, 2, 0))
mean = np.array([0.5])
std = np.array([0.5])
inp = std * inp + mean
plt.imshow(inp)
if title is not None:
plt.title(title)
plt.pause(0.001) # pause a bit so that plots are updated
# Get a batch of training data
inputs, classes = next(iter(trainloader))
print(inputs.shape)
# Make a grid from batch
out = torchvision.utils.make_grid(inputs)
imshow(out, title=[mnistClasses[x] for x in classes])
# Network
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(20*20, 800)
self.relu1 = nn.ReLU()
self.drop1 = nn.Dropout()
self.fc2 = nn.Linear(800, 800)
self.relu2 = nn.ReLU()
self.drop2 = nn.Dropout()
self.fc3 = nn.Linear(800, 10)
self.sm = nn.Softmax(dim=1)
def forward(self, x):
# print(x.size())
x = x.view(-1,20*20)
# print(x.size())
x = self.fc1(x)
# print(x.size())
x = self.relu1(x)
# print(x.size())
x = self.drop1(x)
# print(x.size())
x = self.fc2(x)
# print(x.size())
x = self.relu2(x)
# print(x.size())
x = self.drop2(x)
# print(x.size())
x = self.fc3(x)
# print(x.size())
x = self.sm(x)
# print(x.shape[1])
return (x)
# Network object Creation
net = Net()
print(net)
# Using GPU, if available
use_gpu = torch.cuda.is_available()
print(use_gpu)
if use_gpu:
net.cuda()
inputs, classes = next(iter(trainloader))
inputs = inputs.cuda()
out = net(inputs)
print(out)
# Let’s use a Classification Cross-Entropy loss and SGD with momentum
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
# This is when things start to get interesting.
# We simply have to loop over our data iterator, and feed the inputs to the network and optimize
net.train(True)
epochs = 10
lossInEpochs = np.array([])
xaxis = range(epochs)
for epoch in range(epochs): # loop over the dataset multiple times
running_loss = 0.0
total_loss = 0.0
miniBatchEpoch = 0
scheduler.step()
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
# wrap them in Variable
if use_gpu:
inputs, labels =inputs.cuda(), labels.cuda()
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
total_loss += loss.item()
miniBatchEpoch += 1
if i % 1000 == 999: # print every 100 mini-batches
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 1000))
running_loss = 0.0
for param_group in optimizer.param_groups:
print(param_group['lr'])
lossInEpochs = np.hstack([lossInEpochs, total_loss/miniBatchEpoch])
print('Finished Training')
filePath = './epochWiseTrainError/epochError_FCNN_MNIST.mat'
scipy.io.savemat(filePath, mdict={'lossInEpochs': lossInEpochs})
torch.save(net.state_dict(), './trainedModels/model_FCNN_MNIST.pth')
plt.plot(xaxis,lossInEpochs)
# Set model to evaluation mode
net.eval()
correctR = np.array([0], dtype='float')
total = np.array([0], dtype='float')
for data in testloader:
images, labels = data
outputs = net(images.cuda())
outputs = outputs.cpu()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
predicted = predicted.data.cpu().numpy()
labels = labels.data.numpy()
correctR += (predicted == labels).sum()
print('correctR, totalAccuracy of the network on the 10000 test images: %.4f%%' % (
100 * correctR / total))
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
for data in testloader:
images, labels = data
outputs = net(images.cuda())
outputs = outputs.cpu()
_, predicted = torch.max(outputs.data, 1)
predicted = predicted.data.cpu().numpy()
labels = labels.data.numpy()
c = (predicted == labels).squeeze()
for i in range(4):
label = labels[i]
class_correct[label] += c[i]
class_total[label] += 1
for i in range(10):
print('Accuracy of %5s : %.4f%%' % (
mnistClasses[i], 100 * class_correct[i] / class_total[i]))