# PyTorch

Published:

This lesson covers CNN for CIFAR10

# CNN for CIFAR10

topic = "pytorch"
lesson = 9

from n import *
home, models_path = get_project_dir("CIFAR10")

print_(home)
print_(models_path)

/home/naneja/datasets/n/CIFAR10

/home/naneja/datasets/n/CIFAR10/models

# When the minibatch size is multiplied by k,
# multiply the learning rate by k
batch_size = 128
learning_rate = 0.01
epochs = 10

## Training an image classifier

• Load and normalize the CIFAR10 training and test datasets using torchvision

• Define a Convolutional Neural Network

• Define a loss function

• Train the network on the training data

• Test the network on the test data

%matplotlib inline

import torch
import torchvision
import torchvision.transforms as transforms

from tqdm import tqdm

import matplotlib.pyplot as plt
import numpy as np
random.seed(seed)
torch.manual_seed(seed)

trainset = torchvision.datasets.CIFAR10(root=home,
train=True,
transform=transforms.ToTensor())

batch_size=batch_size,
shuffle=True,
num_workers=2)
images, labels = dataiter.next()

print_(images.shape)

img = images[0]
print_(img.shape)

#print(img[0][0])

# Image Values are between [0, 1]
print_(f"min = {torch.min(img):.4f}, max = {torch.max(img):.4f}")

torch.Size([128, 3, 32, 32])

torch.Size([3, 32, 32])

min = 0.1412, max = 0.9686

### Normalize the images

• x = [0, 1]
• y = (x - 0.5)/0.5
• x = 0 -> y = -1
• x = 1 -> y = +1
mean = (0.5, 0.5, 0.5)
std = (0.5, 0.5, 0.5)

tfs = [transforms.ToTensor(),
transforms.Normalize(mean, std)] # [-1, +1]

transform = transforms.Compose(tfs)

trainset = torchvision.datasets.CIFAR10(root=home,
train=True,
transform=transform)

testset = torchvision.datasets.CIFAR10(root=home,
train=False,
transform=transform)

classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
batch_size=batch_size,
shuffle=True,
num_workers=2)

batch_size=batch_size,
shuffle=False,
num_workers=2)
# get some random training images
images, labels = dataiter.next()
print_(images.shape)

img = images[0]
print_(img.shape)

img[0][0]

torch.Size([128, 3, 32, 32])

torch.Size([3, 32, 32])

tensor([0.4039, 0.3961, 0.3961, 0.3882, 0.4118, 0.4353, 0.4431, 0.4431, 0.4588,
0.4588, 0.4667, 0.4824, 0.4902, 0.4902, 0.5137, 0.5765, 0.6627, 0.6863,
0.6471, 0.5843, 0.5373, 0.5216, 0.6078, 0.7020, 0.7569, 0.6392, 0.5294,
0.4824, 0.5686, 0.6235, 0.5529, 0.6235])

### UnNormalize the images

• x = [-1, 1]
• y = (x/2) + 0.5
• x = -1 -> y = 0
• x = +1 -> y = 1
# functions to show an image

def imshow(img):
img = img / 2 + 0.5     # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.axis("off")

img_name = get_img_name(lesson)
plt.savefig(img_name)
insert_image(img_name, topic)

plt.show()
# get some random training images
images, labels = dataiter.next()

print_(classes[labels[0]])
imshow(images[0])

horse

# show images
print_(images.shape)

print_(images[0].shape)

n_grid = 4
grid = torchvision.utils.make_grid(images[:n_grid])

# 32 * 4 image pixels + 5 * 2 border pixels = 128
# 32 image pixels + 2 * 2 border pixels = 36
print_(f"grid = {grid.shape}")

labels = ''.join(f"{classes[i]:10s}" for i in range(n_grid))
print(labels)

imshow(grid)

torch.Size([128, 3, 32, 32])

torch.Size([3, 32, 32])

grid = torch.Size([3, 36, 138])

plane     car       bird      cat

## Define a Convolutional Neural Network

$n_{out} = \frac{n_{in} + 2 * \text{padding} - \text{kernel_size}}{stride} + 1$

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(in_channels=3,
out_channels=6,
kernel_size=5,
stride=1,

self.pool = nn.MaxPool2d(kernel_size=2,
stride=2)

self.conv2 = nn.Conv2d(in_channels=6,
out_channels=16,
kernel_size=5)

self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
# (_, 3, 32, 32)

x = self.pool(F.relu(self.conv1(x))) #(32-5) + 1 = 28
# (_, 6, 28, 28) # (28-2)/2 + 1 = 14
# (_, 6, 14, 14)

x = self.pool(F.relu(self.conv2(x))) #(14-5) + 1 = 10
# (_, 16, 10, 10) # (10-2)/2 + 1 = 5
# (_, 16, 5, 5)

x = torch.flatten(x, 1) # flatten all dimensions except batch
# 16 * 5 * 5

x = F.relu(self.fc1(x))
# 120

x = F.relu(self.fc2(x))
# 84

x = self.fc3(x)
# 10

return x

net = Net()
print(net)
Net(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), 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)
)

## Define a Loss function and optimizer

import torch.optim as optim

criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(),
lr=learning_rate,
momentum=0.9)

## Train the network

# loop over the dataset multiple times

net.train()

if torch.cuda.device_count() > 1:
print_(f"Let's use {torch.cuda.device_count()} GPUs!")
# dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs
net = nn.DataParallel(net)
net.to(device)

for epoch in range(epochs):

running_loss = 0.0

# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)

# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

# print statistics
running_loss += loss.item()
print_(f"Epoch {epoch+1} Loss {running_loss:.3f}")

print('Finished Training')
100%|█████████████████████████████████████████| 391/391 [00:04<00:00, 84.74it/s]

Epoch 1 Loss 2.028

80%|███████████████████████████████▉        | 312/391 [00:03<00:00, 102.02it/s]
PATH = f"{models_path}/cifar_net.pth"
print_(PATH)

if torch.cuda.device_count() > 1:
torch.save(net.module.state_dict(), PATH)
else:
torch.save(net.state_dict(), PATH)

## Test the network on the test data

images, labels = dataiter.next()

n_grid = 4
grid = torchvision.utils.make_grid(images[:n_grid])

labels = ''.join(f"{classes[i]:10s}" for i in range(n_grid))
print_(labels)

imshow(grid)
net = Net()

"""

# original saved file with DataParallel

# create new OrderedDict that does not contain module.
from collections import OrderedDict
new_state_dict = OrderedDict()
for k, v in state_dict.items():
# remove module. if DataParallel
name = k.replace("module.", "") #k[7:]
#print(k)
new_state_dict[name] = v

"""

map_location=device)
)
images, labels = dataiter.next()

net.to(device)
images, labels = images.to(device), labels.to(device)

outputs = net(images)

print_(labels[:10])
_, predicted = torch.max(outputs, 1)
print_(predicted[:10])

correct = (predicted == labels).sum().item()
print_(correct)
true_labels = [f"{classes[i]:10s}" for i in labels]
true_labels = " ".join(true_labels[:4])
print(true_labels)

pred_labels = [f"{classes[i]:10s}" for i in predicted]
pred_labels = " ".join(pred_labels[:4])
print(pred_labels)
correct = 0
total = 0

# since we're not training
# we don't need to calculate the gradients for our outputs

net = net.to(device)
net.eval()

images, labels = data
images, labels = images.to(device), labels.to(device)

# calculate outputs by running images through the network
outputs = net(images)

# the class with the highest energy is
# what we choose as prediction
_, predicted = torch.max(outputs.data, 1)

total += labels.size(0)
correct += (predicted == labels).sum().item()

print_(f"Accuracy on the {total} test images: {correct/total:.2%}")

Tags: