Image Classification (MNIST)
English translation
Imports
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
from torch.utils.data import DataLoader
import random
import matplotlib.pyplot as plt
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)
# for reproducibility
torch.manual_seed(777)
if device == 'cuda':
torch.cuda.manual_seed_all(777)cuda
1 MNIST dataset
# MNIST dataset
mnist_train = dsets.MNIST(root='MNIST_data/',
train=True,
transform=transforms.ToTensor(),
download=True)
mnist_test = dsets.MNIST(root='MNIST_data/',
train=False,
transform=transforms.ToTensor(),
download=True)Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to MNIST_data/MNIST/raw/train-images-idx3-ubyte.gz
100%|██████████| 9912422/9912422 [00:00<00:00, 17901167.12it/s]
Extracting MNIST_data/MNIST/raw/train-images-idx3-ubyte.gz to MNIST_data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz to MNIST_data/MNIST/raw/train-labels-idx1-ubyte.gz
100%|██████████| 28881/28881 [00:00<00:00, 515824.43it/s]
Extracting MNIST_data/MNIST/raw/train-labels-idx1-ubyte.gz to MNIST_data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to MNIST_data/MNIST/raw/t10k-images-idx3-ubyte.gz
100%|██████████| 1648877/1648877 [00:00<00:00, 1925518.73it/s]
Extracting MNIST_data/MNIST/raw/t10k-images-idx3-ubyte.gz to MNIST_data/MNIST/raw Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to MNIST_data/MNIST/raw/t10k-labels-idx1-ubyte.gz
100%|██████████| 4542/4542 [00:00<00:00, 3221804.29it/s]
Extracting MNIST_data/MNIST/raw/t10k-labels-idx1-ubyte.gz to MNIST_data/MNIST/raw
# dataset loader
batch_size = 100
data_loader = DataLoader(dataset=mnist_train,
batch_size=batch_size,
shuffle=True,
drop_last=True)
2 CNN model
- Input (input structure)
- Input type:
torch.Tensor - Input shape: (N x C x H x W)
- N: Batch size, C: # of channels, H: height, W: width
- (?, 1, 28, 28)
- Assume multiple grayscale images of size 28x28
- Input type:
- Layer design
- Layer 1
- Conv2d >> C: 32, Kernel size (filter size): 3, Stride: 1, Padding: 1
- ReLU
- MaxPool >> Kernel size: 2, Stride: 2
- Input–output (?, 1, 28, 28) >> (?, 32, 14, 14)
- Layer 2
- Conv2d >> C: 64, Kernel size (filter size): 3, Stride: 1, Padding: 1
- ReLU
- MaxPool >> Kernel size: 2, Stride: 2
- Input–output (?, 32, 14, 14) >> (?, 64, 7, 7)
- Layer 3
- Linear >> input: 7x7x64 output: 10
- Softmax
- Layer 1
class CNN(torch.nn.Module):
def __init__(self):
super(CNN, self).__init__()
# L1 Input shape=(?, 1, 28, 28)
# Conv -> (?, 32, 28, 28)
# Pool -> (?, 32, 14, 14)
self.layer1 = torch.nn.Sequential(
torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# L2 Input shape=(?, 32, 14, 14)
# Conv ->(?, 64, 14, 14)
# Pool ->(?, 64, 7, 7)
self.layer2 = torch.nn.Sequential(
torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# L3 Linear 64x7x7 inputs -> 10 outputs
self.fc = torch.nn.Linear(64*7*7, 10, bias=True)
torch.nn.init.xavier_uniform_(self.fc.weight)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = out.view(out.size(0), -1) # Flatten them for FC
out = self.fc(out)
return out
3 Training
# parameters
learning_rate = 0.001
training_epochs = 15
# contruct model
model = CNN().to(device)
# define cost/loss & optimizer
criterion = torch.nn.CrossEntropyLoss().to(device) # Softmax
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# train
total_batch = len(data_loader)
print('Learning started. It takes sometime.')
for epoch in range(training_epochs):
avg_cost = 0
for X, Y in data_loader:
X = X.to(device)
Y = Y.to(device)
optimizer.zero_grad()
hypothesis = model(X)
cost = criterion(hypothesis, Y)
cost.backward()
optimizer.step()
avg_cost += cost / total_batch
print('[Epoch: {:>4}] cost = {:>.9}'.format(epoch + 1, avg_cost))
print('Learning Finished!')Learning started. It takes sometime. [Epoch: 1] cost = 0.225600749 [Epoch: 2] cost = 0.0629422814 [Epoch: 3] cost = 0.0462685339 [Epoch: 4] cost = 0.0374453217 [Epoch: 5] cost = 0.0312564597 [Epoch: 6] cost = 0.0261451434 [Epoch: 7] cost = 0.0218881592 [Epoch: 8] cost = 0.0182996988 [Epoch: 9] cost = 0.0160796437 [Epoch: 10] cost = 0.0133214388 [Epoch: 11] cost = 0.0101956706 [Epoch: 12] cost = 0.00985957589 [Epoch: 13] cost = 0.00824302062 [Epoch: 14] cost = 0.00647699879 [Epoch: 15] cost = 0.00701776193 Learning Finished!
# Test model and check accuracy
with torch.no_grad():
X_test = mnist_test.data.view(len(mnist_test), 1, 28, 28).float().to(device)
Y_test = mnist_test.targets.to(device)
prediction = model(X_test)
correct_prediction = torch.argmax(prediction, 1) == Y_test
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())Accuracy: 0.9848999977111816
# Random sample test
with torch.no_grad():
r = random.randint(0, len(mnist_test) - 1)
img_sample = mnist_test.data[r].view(1, 1, 28, 28).float().to(device)
label_sample = mnist_test.targets[r].to(device)
print('Label: ', label_sample.item())
sample_prediction = model(img_sample)
print('Prediction: ', torch.argmax(sample_prediction, axis=1).item())
plt.imshow(mnist_test.data[r].view(28, 28), cmap='Greys', interpolation='nearest')
plt.show()Label: 9 Prediction: 9
<Figure size 640x480 with 1 Axes>
3 Assignment
Use the following incomplete code to train on new data
- Training data image
- Shape: (?, 3, 64, 128)
- Assume multiple RGB images of size 64x128
- Shape: (?, 3, 64, 128)
- Test data image
- Shape: (?, 3, ?, ?)
- Assume multiple RGB images of unknown size
- Shape: (?, 3, ?, ?)
- Labels
- There are 2 image classes
- Refer to the data folder structure
- Data folder location
- Copy the 2 data folders from the notebook's GitHub repository to a suitable location for use
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
from torch.utils.data import DataLoader
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)
from google.colab import drive
drive.mount('/content/drive')
# for reproducibility
torch.manual_seed(777)
if device == 'cuda':
torch.cuda.manual_seed_all(777)
# Model
##### Use the model written in the previous assignment
##### Adapt it to the changed image input
##### Note that the new image size is 64x128, with 3 RGB channels rather than grayscale
# parameters
##### Modify as appropriate
learning_rate =
training_epochs =
# contruct model
model = CNN().to(device)
# define cost/loss & optimizer
criterion = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# train
##### Learn this function's behavior; it is often used when training with your own dataset
##### Look up the relevant function information on the official pytorch website
trans = transforms.Compose([transforms.ToTensor()])
train_data = dsets.ImageFolder(root='/content/drive/MyDrive/Colab Notebooks/courses/AI_Appl/train_data', transform=trans)
data_loader = DataLoader(dataset = train_data, batch_size = 8, shuffle = True)
total_batch = len(data_loader)
##### Training loop
##### You may reuse the previous source code, but try writing it yourself for practice
# test
##### Learn this function's behavior; it is often used when training with your own dataset
##### Look up the relevant function information on the official pytorch website
trans=transforms.Compose([transforms.Resize((64,128)),transforms.ToTensor()])
test_data = dsets.ImageFolder(root='/content/drive/MyDrive/Colab Notebooks/courses/AI_Appl/test_data', transform=trans)
test_set = DataLoader(dataset = test_data, batch_size = len(test_data))
with torch.no_grad():
##### Loop for testing the results
##### You may reuse the previous source code, but try writing it yourself for practice
cuda
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
Learning started. It takes sometime.
[Epoch: 1] cost = 0.158599436
[Epoch: 2] cost = 0.00020430611
[Epoch: 3] cost = 2.68744279e-05
[Epoch: 4] cost = 5.39911434e-06
[Epoch: 5] cost = 1.20812297e-06
Learning Finished!
Accuracy: 1.0