Pytorch与视觉竞赛入门4-PyTorch完成Fashion-MNIST分类

基本配置

import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from torch import nn, optim # optim here allow us to get optimizers
from torchvision import datasets, transforms
import torchvision
from torch.utils.data import Dataset, DataLoader
import torch.nn.functional as F # let us to use ReLU and log softmax
import helper
from sklearn.metrics import confusion_matrix

device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Set random seed for reproducibility
manualSeed = 999
#manualSeed = random.randint(1, 10000) # use if you want new results
print("Random Seed: ", manualSeed)
random.seed(manualSeed)
import random
torch.manual_seed(manualSeed)

数据加载和预处理

数据集

Fashion-MNIST dataset

数据加载

通常有两种方法可以上传 MNIST 时尚数据集。

  1. 加载 csv dile ;
  2. 使用 torchvision.datasets。

这里我们使用 torchvision.datasets 包。

#定义图像变换和归一化函数,并将它们转换为张量
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])

# Download and load the training data
trainset = torchvision.datasets.FashionMNIST('~/.pytorch/F_MNIST_data/', download=True, train=True, transform=transform)

# Download and load the test data
testset = torchvision.datasets.FashionMNIST('~/.pytorch/F_MNIST_data/', download=True, train=True, transform=transform)

为训练和测试创建数据加载器

trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=0)

testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=True, num_workers=0)
##   Different  classes in Fashion MNIST dataset

classes=('Tshirt', 'Trouser','Pullover', 'Dress', 'Coat',
'Sandal','Shirt', 'Sneaker','Bag', 'Anke boot' )

可视化数据集

## We can use helper function to see some images of MNIST fashion

def matplotlib_imshow (img, one_channel=False):
if one_channel:
img=im.mean(dim=0)
img=img/2+0.5 # unnormalize
npimg=img.numpy()
if one_channel:
plt.imshow(npimg, cmap="Greys")
else:
plt.imshow(np.transpose(npimg, (1,2,0)))

## Now lets try to get some random images
d=iter(trainloader)
images, labels=d.next()
matplotlib_imshow(torchvision.utils.make_grid(images))
mnist=next(iter(trainloader))
mnist[0].size()
image, label = next(iter(trainloader))
helper.imshow(image[0,:]);
## or we can use this method
image, label=next(iter(trainset))
plt.imshow(image.squeeze(), cmap="gray")
print(label)
## or we can use this method
image, label=next(iter(testset))
plt.imshow(image.squeeze(), cmap="jet")
print(label)

模型定义

class Fashion(nn.Module):
def __init__(self):
super().__init__()
self.c1 = nn.Linear(784, 256)
self.c2 = nn.Linear(256, 128)
self.c3 = nn.Linear(128, 64)
self.c4 = nn.Linear(64, 10)

def forward(self, x):
x = x.view(x.shape[0], -1)

x = F.relu(self.c1(x))
x = F.relu(self.c2(x))
x = F.relu(self.c3(x))
x = F.log_softmax(self.c4(x), dim=1)

return x

训练和测试+可视化

from torch.utils.tensorboard import SummaryWriter
model = Fashion()
model=model.to(device)
error = nn.NLLLoss() #define a metric for our loss function
learning_rate=0.001 # Defining the learning rate
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

tb_writer = SummaryWriter(log_dir="runs/experiment")
# 将模型写入tensorboard
init_img = torch.zeros((1, 1, 28, 28), device=device)
tb_writer.add_graph(model, init_img)
num_epochs=50
for e in range(num_epochs):
running_loss=0
for images, labels in trainloader:
images=images.to(device)
labels=labels.to(device)
log_ps=model(images)
loss=error(log_ps,labels)

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

running_loss+=loss.item()
else:
mean_loss=running_loss/len(trainloader)
print(f"Training loss: {running_loss/len(trainloader)}")
model.eval()
with torch.no_grad():
total=0
correct=0
for images,labels in testloader:
images=images.to(device)
labels=labels.to(device)
log_ps=model(images)
mx_index=torch.argmax(log_ps,dim=1)
total+=labels.numel()
correct+=sum(mx_index==labels).item()
print(f"Test Accuracy {correct/total*100:.2f}")
# 注意这里直接加的是float
tb_writer.add_scalar("train_loss", mean_loss, e)
tb_writer.add_scalar("accuracy", correct/total*100, e)
# 学习率
tb_writer.add_scalar("learning_rate", optimizer.param_groups[0]["lr"], e)
Training loss: 0.5184546974517389
Test Accuracy 84.38
Training loss: 0.3788776620745913
Test Accuracy 87.54
Training loss: 0.33836390459334165
Test Accuracy 88.54
Training loss: 0.312769211566588
Test Accuracy 89.35
Training loss: 0.29623160883784294
Test Accuracy 90.01
Training loss: 0.27754005589591924
Test Accuracy 90.14
Training loss: 0.26361305692366194
Test Accuracy 90.73
Training loss: 0.2531202086873019
Test Accuracy 91.00
Training loss: 0.24045277232014295
Test Accuracy 91.86
Training loss: 0.23074886283831303
Test Accuracy 91.32
Training loss: 0.22216772602231644
Test Accuracy 92.75
Training loss: 0.21136155409583532
Test Accuracy 93.00
Training loss: 0.2046388833523432
Test Accuracy 92.74
Training loss: 0.19458908333119426
Test Accuracy 93.41
Training loss: 0.18638811663174426
Test Accuracy 92.99
Training loss: 0.18099606320706765
Test Accuracy 93.62
Training loss: 0.16946962415012343
Test Accuracy 93.98
Training loss: 0.16408071364722907
Test Accuracy 93.25
Training loss: 0.15635767262150993
Test Accuracy 93.57
Training loss: 0.15740170869936568
Test Accuracy 94.50
Training loss: 0.14828259150372514
Test Accuracy 95.32
Training loss: 0.14066051659998355
Test Accuracy 94.68
Training loss: 0.1356164852042061
Test Accuracy 95.47
Training loss: 0.13447571505429046
Test Accuracy 95.45
Training loss: 0.12650341864651454
Test Accuracy 95.85
Training loss: 0.12489128283270673
Test Accuracy 95.73
Training loss: 0.11923427860002353
Test Accuracy 96.26
Training loss: 0.11319202443322679
Test Accuracy 95.31
Training loss: 0.1154530997177574
Test Accuracy 96.13
Training loss: 0.1072914944862379
Test Accuracy 96.58
Training loss: 0.10244416040398165
Test Accuracy 96.20
Training loss: 0.10448560929263452
Test Accuracy 96.37
Training loss: 0.09810208319835285
Test Accuracy 96.46
Training loss: 0.09480555668207151
Test Accuracy 96.38
Training loss: 0.0906216712844278
Test Accuracy 96.96
Training loss: 0.08993256978962674
Test Accuracy 96.31
Training loss: 0.08628608498857347
Test Accuracy 97.14
Training loss: 0.08517631656800045
Test Accuracy 96.91
Training loss: 0.08814828924244957
Test Accuracy 96.75
Training loss: 0.08050761009101817
Test Accuracy 96.98
Training loss: 0.08286095018893766
Test Accuracy 96.66
Training loss: 0.08155279546114269
Test Accuracy 96.50
Training loss: 0.0733050029334634
Test Accuracy 97.57
Training loss: 0.07111362080106627
Test Accuracy 97.56
Training loss: 0.0743615166956821
Test Accuracy 97.28
Training loss: 0.0720261309138521
Test Accuracy 97.52
Training loss: 0.06857110534696334
Test Accuracy 97.48
Training loss: 0.0671807692628473
Test Accuracy 97.32
Training loss: 0.0644429779243169
Test Accuracy 97.64
Training loss: 0.06474769708353217
Test Accuracy 97.72

预测

import helper

# Test out your network!

dataiter = iter(testloader)
images, labels = dataiter.next()
img = images[1]

# Calculate the class probabilities (softmax) for img
ps = torch.exp(model(img))

# Plot the image and probabilities
helper.view_classify(img, ps, version='Fashion')

helper文件

import matplotlib.pyplot as plt
import numpy as np
from torch import nn, optim
from torch.autograd import Variable


def test_network(net, trainloader):

criterion = nn.MSELoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)

dataiter = iter(trainloader)
images, labels = dataiter.next()

# Create Variables for the inputs and targets
inputs = Variable(images)
targets = Variable(images)

# Clear the gradients from all Variables
optimizer.zero_grad()

# Forward pass, then backward pass, then update weights
output = net.forward(inputs)
loss = criterion(output, targets)
loss.backward()
optimizer.step()

return True


def imshow(image, ax=None, title=None, normalize=True):
"""Imshow for Tensor."""
if ax is None:
fig, ax = plt.subplots()
image = image.numpy().transpose((1, 2, 0))

if normalize:
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
image = std * image + mean
image = np.clip(image, 0, 1)

ax.imshow(image)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.tick_params(axis='both', length=0)
ax.set_xticklabels('')
ax.set_yticklabels('')

return ax


def view_recon(img, recon):
''' Function for displaying an image (as a PyTorch Tensor) and its
reconstruction also a PyTorch Tensor
'''

fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
axes[0].imshow(img.numpy().squeeze())
axes[1].imshow(recon.data.numpy().squeeze())
for ax in axes:
ax.axis('off')
ax.set_adjustable('box-forced')

def view_classify(img, ps, version="MNIST"):
''' Function for viewing an image and it's predicted classes.
'''
ps = ps.data.numpy().squeeze()

fig, (ax1, ax2) = plt.subplots(figsize=(6,9), ncols=2)
ax1.imshow(img.resize_(1, 28, 28).numpy().squeeze())
ax1.axis('off')
ax2.barh(np.arange(10), ps)
ax2.set_aspect(0.1)
ax2.set_yticks(np.arange(10))
if version == "MNIST":
ax2.set_yticklabels(np.arange(10))
elif version == "Fashion":
ax2.set_yticklabels(['T-shirt/top',
'Trouser',
'Pullover',
'Dress',
'Coat',
'Sandal',
'Shirt',
'Sneaker',
'Bag',
'Ankle Boot'], size='small');
ax2.set_title('Class Probability')
ax2.set_xlim(0, 1.1)

plt.tight_layout()

参考资料

Fashion-MNIST Classification using PyTorch

helper文件