Skip to content

Commit 5b185ff

Browse files
authored
Create MNIST_Classifier.py
Python program using the provided template to train and test a MNIST dataset using a modified AlexNet model. The program should accept three integers as command line input. First two integers define the labels of the two-class classification and third integer represents the number of epochs for training.
1 parent 52602ea commit 5b185ff

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
"""
2+
This program is a MNIST classifier using AlexNet. It accepts three parameters provided as a command line input.
3+
The first two inputs are two digits between 0-9 which are used to train and test the classifier and the third
4+
parameter controls the number of training epochs.
5+
Syntax: python program.py <number> <number> <number>
6+
7+
For example, to train and test AlexNet with 1 and 2 MNIST samples with 4 training epochs, the command line input should be:
8+
python program.py 1 2 4
9+
10+
"""
11+
12+
13+
import sys
14+
import torch
15+
import torch.nn as nn
16+
import torchvision.datasets as dset
17+
import torchvision.transforms as transforms
18+
from torch.autograd import Variable
19+
import torch.nn.functional as F
20+
import torch.optim as optim
21+
22+
23+
class AlexNet(nn.Module):
24+
def __init__(self, num=10):
25+
super(AlexNet, self).__init__()
26+
self.feature = nn.Sequential(
27+
# Define feature extractor here...
28+
nn.Conv2d(1, 32, kernel_size=5, stride=1, padding=1),
29+
nn.ReLU(inplace=True),
30+
nn.Conv2d(32, 64, kernel_size=3, padding=1),
31+
nn.ReLU(inplace=True),
32+
nn.MaxPool2d(kernel_size=2, stride=2),
33+
nn.Conv2d(64, 96, kernel_size=3, padding=1),
34+
nn.ReLU(inplace=True),
35+
nn.Conv2d(96, 64, kernel_size=3, padding=1),
36+
nn.ReLU(inplace=True),
37+
nn.Conv2d(64, 32, kernel_size=3, padding=1),
38+
nn.ReLU(inplace=True),
39+
nn.MaxPool2d(kernel_size=2, stride=1)
40+
)
41+
42+
self.classifier = nn.Sequential(
43+
# Define classifier here...
44+
nn.Dropout(),
45+
nn.Linear(32*12*12, 2048),
46+
nn.ReLU(inplace=True),
47+
nn.Dropout(),
48+
nn.Linear(2048, 1024),
49+
nn.ReLU(inplace=True),
50+
nn.Linear(1024, 10)
51+
)
52+
53+
def forward(self, x):
54+
# define forward network 'x' that combines feature extractor and classifier
55+
x = self.feature(x)
56+
x = x.view(x.size(0), -1)
57+
x = self.classifier(x)
58+
return x
59+
60+
61+
def load_subset(full_train_set, full_test_set, label_one, label_two):
62+
# Sample the correct train labels
63+
train_set = []
64+
data_lim = 20000
65+
for data in full_train_set:
66+
if data_lim>0:
67+
data_lim-=1
68+
if data[1]==label_one or data[1]==label_two:
69+
train_set.append(data)
70+
else:
71+
break
72+
73+
test_set = []
74+
data_lim = 1000
75+
for data in full_test_set:
76+
if data_lim>0:
77+
data_lim-=1
78+
if data[1]==label_one or data[1]==label_two:
79+
test_set.append(data)
80+
else:
81+
break
82+
83+
return train_set, test_set
84+
85+
def train(model,optimizer,train_loader,epoch):
86+
model.train()
87+
for batch_idx, (data, target) in enumerate(train_loader):
88+
if torch.cuda.is_available():
89+
data, target = data.cuda(), target.cuda()
90+
data, target = Variable(data), Variable(target)
91+
optimizer.zero_grad()
92+
output = model(data)
93+
loss = F.cross_entropy(output, target)
94+
loss.backward()
95+
optimizer.step()
96+
97+
def test(model,test_loader):
98+
model.eval()
99+
test_loss = 0
100+
correct = 0
101+
for data, target in test_loader:
102+
if torch.cuda.is_available():
103+
data, target = data.cuda(), target.cuda()
104+
with torch.no_grad():
105+
data, target = Variable(data), Variable(target)
106+
output = model(data)
107+
test_loss += F.cross_entropy(output, target, reduction='sum').item()#size_average=False
108+
pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability
109+
correct += pred.eq(target.data.view_as(pred)).long().cpu().sum()
110+
111+
test_loss /= len(test_loader.dataset)
112+
acc=100. * float(correct.to(torch.device('cpu')).numpy())
113+
test_accuracy = (acc / len(test_loader.dataset))
114+
return test_accuracy
115+
116+
117+
""" Start to call """
118+
119+
if __name__ == '__main__':
120+
121+
if len(sys.argv) == 3:
122+
print("Usage: python assignment.py <number> <number>")
123+
sys.exit(1)
124+
125+
input_data_one = sys.argv[1].strip()
126+
input_data_two = sys.argv[2].strip()
127+
epochs = sys.argv[3].strip()
128+
129+
""" Call to function that will perform the computation. """
130+
if input_data_one.isdigit() and input_data_two.isdigit() and epochs.isdigit():
131+
132+
label_one = int(input_data_one)
133+
label_two = int(input_data_two)
134+
epochs = int(epochs)
135+
136+
if label_one!=label_two and 0<=label_one<=9 and 0<=label_two<=9:
137+
torch.manual_seed(42)
138+
# Load MNIST dataset
139+
trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (1.0,))])
140+
full_train_set = dset.MNIST(root='./data', train=True, transform=trans, download=True)
141+
full_test_set = dset.MNIST(root='./data', train=False, transform=trans)
142+
batch_size = 16
143+
# Get final train and test sets
144+
train_set, test_set = load_subset(full_train_set,full_test_set,label_one,label_two)
145+
146+
train_loader = torch.utils.data.DataLoader(dataset=train_set,batch_size=batch_size,shuffle=False)
147+
test_loader = torch.utils.data.DataLoader(dataset=test_set,batch_size=batch_size,shuffle=False)
148+
149+
model = AlexNet()
150+
if torch.cuda.is_available():
151+
model.cuda()
152+
153+
optimizer = optim.SGD(model.parameters(), lr=0.01)
154+
155+
for epoch in range(1, epochs+1):
156+
train(model,optimizer,train_loader,epoch)
157+
accuracy = test(model,test_loader)
158+
159+
print(round(accuracy,2))
160+
161+
162+
else:
163+
print("Invalid input")
164+
else:
165+
print("Invalid input")
166+
167+
168+
""" End to call """

0 commit comments

Comments
 (0)