Implement USPS Handwritten Digits Classification with Pytorch

Define parameters and paths, transform the raw data to 32×32 to feed it into LeNET.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
from torchvision.datasets import USPS
from torch.utils.data import DataLoader

# Define parameters
batch_size = 64
learning_rate = 0.001
num_epochs = 10

train_dataset_path = 'USPS/train'
test_dataset_path = 'USPS/test'

# Transformations
transform = transforms.Compose([
transforms.Resize((32, 32)), # LeNet expects 32x32 images
transforms.ToTensor(),
])

# Download datasets
train_dataset = USPS(train_dataset_path, train = True, transform = transform, download = True)
test_dataset = USPS(test_dataset_path, train = False, transform = transform, download = True)

# Initialize dataloaders
train_loader = DataLoader(train_dataset, batch_size = batch_size, shuffle = True)
test_loader = DataLoader(test_dataset, batch_size = batch_size, shuffle = True)

Define LeNet Model

image-17.png

In this implementation, we use ReLU instead of tanh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Define LeNet
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(400, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
x = nn.functional.relu(self.conv1(x))
x = nn.functional.max_pool2d(x, 2)
x = nn.functional.relu(self.conv2(x))
x = nn.functional.max_pool2d(x, 2)
x = x.view(x.size(0), -1)
x = nn.functional.relu(self.fc1(x))
x = nn.functional.relu(self.fc2(x))
x = self.fc3(x)
return x

# Model, Loss, and Optimizer
model = LeNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

Train

1
2
3
4
5
6
7
8
9
10
11
12
13
# Training
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
outputs = model(images)
loss = criterion(outputs, labels)

optimizer.zero_grad()
loss.backward()
optimizer.step()

print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item():.4f}')

print("Training finished.")

Evaluation

1
2
3
4
5
6
7
8
9
10
11
12
# Evaluation
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

print('Accuracy of the model on the test images: {}%'.format(100 * correct / total))

Run SVM on USPS dataset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from sklearn import svm
from sklearn.metrics import accuracy_score
import numpy as np

# Flatten the dataset and convert to numpy arrays
X_train = np.array([x[0].numpy().ravel() for x in train_dataset])
y_train = np.array([x[1] for x in train_dataset])

X_test = np.array([x[0].numpy().ravel() for x in test_dataset])
y_test = np.array([x[1] for x in test_dataset])

# Define and train the SVM
clf = svm.SVC()
clf.fit(X_train, y_train)

# Predict
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)

# Compute the accuracy
train_accuracy = accuracy_score(y_train, y_pred_train)
test_accuracy = accuracy_score(y_test, y_pred_test)

print(f"Training Accuracy: {train_accuracy * 100:.2f}%")
print(f"Test Accuracy: {test_accuracy * 100:.2f}%")