import torch
import torchvision
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter # TensorBoard support
import torchvision.transforms as transforms
import pandas as pd
import json
from IPython.display import clear_output
transform = transforms.Compose([transforms.ToTensor()])
trainset = torchvision.datasets.FashionMNIST(root="FashionMNIST", train=True,
transform=transform, target_transform=None, download=True)
train_set, val_set = torch.utils.data.random_split(trainset, [50000, 10000])
trainloader = torch.utils.data.DataLoader(train_set, batch_size=4,
shuffle=True, num_workers=2)
valloader = torch.utils.data.DataLoader(val_set, batch_size=4,
shuffle=True, num_workers=2)
testset = torchvision.datasets.FashionMNIST(root="FashionMNIST", train=False,
transform=transform, target_transform=None, download=True)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
from google.colab import drive
drive.mount('/content/gdrive')
Below shows some images in the dataset
import matplotlib.pyplot as plt
import numpy as np
def imshow(img):
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
# show images
imshow(torchvision.utils.make_grid(images))
def get_acc(net, loader):
correct, total = 0, 0
with torch.no_grad():
for data in loader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy: %d %%' % (100 * correct / total))
return 100 * correct / total
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 32, 5)
self.fc1 = nn.Linear(512, 200)
self.fc2 = nn.Linear(200, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.reshape(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
def num_flat_features(self, x):
size = x.size()[1:] # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
epochs = 10
for epoch in range(epochs): # loop over the dataset multiple times
running_loss = 0.0
loss_hist = []
val_acc_hist = []
train_acc_hist = []
losses = []
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = loss_fn(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
loss_hist.append(loss.item())
if i % 2000 == 1999: # print every 4000 mini-batches
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
losses.append(running_loss)
running_loss = 0.0
##### get train acc##########
train_acc_hist.append(get_acc(net, trainloader))
##############################
## get test acc
val_acc_hist.append(get_acc(net, valloader))
print('Finished Training')
model_save_name = '1_classifier.pt'
path = F"/content/gdrive/My Drive/{model_save_name}"
torch.save(net.state_dict(), path)
#net.load_state_dict(torch.load(path))
import matplotlib.pyplot as plt
plt.style.use("seaborn-darkgrid")
x = range(6)
fig, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].plot(x, train_acc_hist)
axs[0].set_title("Accuracy history on training set")
axs[1].plot(x, val_acc_hist)
axs[1].set_title("Accuracy history on validation set")
axs[2].plot([l/2000 for l in losses])
axs[2].set_title("Loss history during training")
#axs[1].plot(np.convolve(test_acc_hist, np.ones(10), 'valid') / 10)
#axs[2].plot(np.convolve(loss_hist, np.ones(30), 'valid') / 30)
plotname = 'training.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
correct, total = 0, 0
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the test images: %d %%' % (
100 * correct / total))
def class_acc(class_idx, net, testloader, b_size):
corr, total = 0, 0
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
for b in range(b_size):
if labels[b] == class_idx:
total += 1
if predicted[b] == class_idx:
corr += 1
print("Class accuracy on class"+str(class_idx)+": ", (100 * corr / total))
return 100 * corr / total
class_accs = [class_acc(k, net, testloader, 4) for k in range(10)]
plt.plot(class_accs)
success, fail, false_pred = [], [], []
b_size = 4
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
for b in range(b_size):
if labels[b] == 8 and predicted[b] == 8:
success.append(images[b])
if labels[b] == 6 and predicted[b] != 6:
fail.append(images[b])
false_pred.append(predicted[b])
if len(success) > 4 and len(fail) > 4:
break
Below are some images that the network successfully predicts to be hangbags (class 8)
imshow(torchvision.utils.make_grid(success))
Below we can see that for these images, network fails to recognize them as class 6, but predicts class 4, 3, 4, 2, 0 respectively instead.
imshow(torchvision.utils.make_grid(fail))
print([pred.numpy() for pred in false_pred])
plotname = 'class_acc.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
Below we visualize the 32 filters in the first conv layer of the network
filter = net.conv1.weight
f = filter.detach().numpy()
f.shape
fig, axs = plt.subplots(1, 8, figsize=(24, 3))
for i in range(8):
axs[i].imshow(f[i, 0,:])
plotname = 'filters8.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
fig, axs = plt.subplots(1, 8, figsize=(24, 3))
for i in range(8):
axs[i].imshow(f[i+8,0,:])
plotname = 'filters16.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
fig, axs = plt.subplots(1, 8, figsize=(24, 3))
for i in range(8):
axs[i].imshow(f[i+16,0,:])
plotname = 'filters24.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
fig, axs = plt.subplots(1, 8, figsize=(24, 3))
for i in range(8):
axs[i].imshow(f[i+24,0,:])
plotname = 'filters32.jpg'
path = F"/content/gdrive/My Drive/{plotname}"
plt.savefig(path)
My network architecture:
self.layers = nn.Sequential(
nn.Conv2d(3, 64, 3, padding=3),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(2),
nn.ConvTranspose2d(64, 64, 2, stride=2, padding=0),
nn.Conv2d(64, 128, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, 3, padding=1),
nn.MaxPool2d(2),
nn.ConvTranspose2d(128, 128, 2, stride=2, padding=0),
nn.Conv2d(128, self.n_class, 5, padding=0),
)
!unzip gdrive/'My Drive'/part2.zip
!ls ### note: this is Colab directory
!python part2/train.py
avg_AP = (0.6398084168547654+0.7598914526856534+0.12780097593809658
+0.7694882625129862+0.3478574926158466)/5
print("Average AP is: ", avg_AP)
train_loss = [1.251, 1.181, 1.161, 1.131, 1.119, 1.107, 1.106, 1.095, 1.067, 1.060, 1.032, 1.023, 1.005, 0.989, 0.981, 0.973, 0.967, 0.967, 0.964, 0.958, 0.949, 0.945]
val_loss = [1.214173470224653, 1.105357391493661, 1.0402773363249642, 1.0134815573692322, 0.9960261327879769, 0.9855861152921405, 0.9797338843345642, 0.965831824711391, 0.9399185010365078, 0.9179572207587106, 0.9002114193780082, 0.8827240296772548, 0.8685245258467538, 0.8638482008661542, 0.8585308023861477, 0.8507117458752224, 0.8395993624414716, 0.836676938193185, 0.8319266949381147, 0.8238045062337603, 0.8217411381857735, 0.8163694483893258, 0.8803454414010048]
plt.plot(train_loss)
plt.plot(val_loss)
plt.legend(["Loss on trainset", "Loss on validation set"])
Below demonstrates the network's output on a test image versus the groud truth labels:
out = plt.imread("part2/output_test/y15.png")
truth = plt.imread("part2/starter_set/test_dev/eecs442_0015.png")
ori = plt.imread("part2/output_test/x15.png")
fig, axs = plt.subplots(1, 3, figsize=(15, 3))
axs[0].imshow(out)
axs[1].imshow(truth)
axs[2].imshow(ori)
Below I added my own image to test_dev and produced output labels:
!python part2/train.py
out = plt.imread("part2/y0.png")
truth = plt.imread("part2/x0.png")
fig, axs = plt.subplots(1, 2)
axs[0].imshow(out)
axs[1].imshow(truth)