import matplotlib.pyplot as pltimport numpy as np# Cannot directly use plt.show() to show Tensor# Convert to numpy then use pltdefimshow(img): img = img /2+0.5# unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0)))# channel goes at last plt.xticks([]) plt.yticks([]) plt.show()# get some random training imagesdataiter =iter(trainloader)images, labels = dataiter.next()# Since batch=4, we get four images at a timeimages.size()# show imagesimshow(torchvision.utils.make_grid(images))# print labelsprint(' '.join('%5s'% classes[labels[j]] for j inrange(4)))
Define Model
import torch.nn as nnimport torch.nn.functional as FclassNet(nn.Module):def__init__(self):super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16*5*5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10)defforward(self,x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16*5*5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x)return xnet =Net()
Define Loss function and Optimization
import torch.optim as optim# loss functioncriterion = nn.CrossEntropyLoss()# Optimization methodoptimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
Train the network
for epoch inrange(2):# loop over the dataset multiple times running_loss =0.0for i, data inenumerate(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 =criterion(outputs, labels) loss.backward() optimizer.step()# print statistics running_loss += loss.item()if i %2000==1999:# print every 2000 mini-batchesprint('[%d, %5d] loss: %.3f'% (epoch +1, i +1, running_loss /2000)) running_loss =0.0print('Finished Training')
Save model
PATH ='./cifar_net.pth'torch.save(net.state_dict(), PATH)# To use the saved modelnet =Net()net.load_state_dict(torch.load(PATH))
correct =0total =0with torch.no_grad():for data in testloader: images, labels = data[0].to(device), data[1].to(device) 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 %d test images: %d%%'%(len(testloader.dataset), 100* correct / total))
Evaluate each class
numpy.squeeze() function is used when we want to remove single-dimensional entries from the shape of an array.
class_correct =list(0. for i inrange(10))class_total =list(0. for i inrange(10))with torch.no_grad():for data in testloader: images, labels = data outputs =net(images) _, predicted = torch.max(outputs, 1)# max(outputs, dim=1) returns (values, indices) c = (predicted == labels).squeeze()# remove dim=1for i inrange(4): label = labels[i] class_correct[label]+= c[i].item()#c[i] is a tensor either true or false class_total[label]+=1for i inrange(10):print('Accuracy of %5s : %2d%%'% ( classes[i], 100* class_correct[i] / class_total[i]))
Exercise
Try increasing the width of your network (argument 2 of
the first nn.Conv2d, and argument 1 of the second nn.Conv2d
they need to be the same number), see what kind of speedup you get.