当前位置: 代码迷 >> 综合 >> Pytorch基本练习MLP-MNIST
  详细解决方案

Pytorch基本练习MLP-MNIST

热度:106   发布时间:2023-10-29 03:13:59.0

训练MLP对MNIST手写数字数据库中的图像进行分类。训练分为几步:1.加载和可视化数据 2.定义神经网络 3.训练模型 4.评估已训练模型在测试数据集上的性能!

模块导入

# import libraries
import torch
import numpy as np
from torchvision import datasets
import torchvision.transforms as transforms
from torch.utils.data.sampler import SubsetRandomSampler

加载数据(train,valid,test):train和valid是模型训练时调节网络并保存模型参数,test是模型训练完后进行测试。

# number of subprocesses to use for data loading
num_workers = 0
# how many samples per batch to load
batch_size = 20valid_size = 0.2# convert data to torch.FloatTensor
transform = transforms.ToTensor()# choose the training and test datasets
train_data = datasets.MNIST(root='data', train=True,download=True, transform=transform)
test_data = datasets.MNIST(root='data', train=False,download=True, transform=transform)num_train = len(train_data)
indices = list(range(num_train))
np.random.shuffle(indices)
split = int(np.floor(valid_size * num_train))
train_idx,valid_idx = indices[split:],indices[:split]train_sampler = SubsetRandomSampler(train_idx)
valid_sampler = SubsetRandomSampler(valid_idx)# prepare data loaders
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size,sampler=train_sampler,num_workers=num_workers)
valid_loader = torch.utils.data.DataLoader(train_data,batch_size=batch_size,sampler=valid_sampler,num_workers=num_workers)
test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, num_workers=num_workers)

可视化训练数据

import matplotlib.pyplot as plt
%matplotlib inline# obtain one batch of training images
dataiter = iter(train_loader)
images, labels = dataiter.next()
images = images.numpy()# plot the images in the batch, along with the corresponding labels
fig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])ax.imshow(np.squeeze(images[idx]), cmap='gray')# print out the correct label for each image# .item() gets the value contained in a Tensorax.set_title(str(labels[idx].item()))

定义网络结构:该结构需要将每个图像的 784 维像素值张量当做输入,并生成长度为 10(表示类别数量)的张量,表示输入图像的类别分数。这个示例使用了两个隐藏层和丢弃层,以避免过拟合。

import torch.nn as nn
import torch.nn.functional as F## TODO: Define the NN architecture
class Net(nn.Module):def __init__(self):super(Net, self).__init__()# linear layer (784 -> 1 hidden node)self.fc1 = nn.Linear(28 * 28, 512)self.fc2 = nn.Linear(512,256)self.fc3 = nn.Linear(256,10)self.dropout = nn.Dropout(0.2)def forward(self, x):# flatten image inputx = x.view(-1, 28 * 28)# add hidden layer, with relu activation functionx = self.dropout(F.relu(self.fc1(x)))x = self.dropout(F.relu(self.fc2(x)))x = self.fc3(x)return x# initialize the NN
model = Net()
print(model)

指定损失函数和优化器:对于分类任务来说,建议使用交叉熵损失。 PyTorch 的交叉熵函数向输出层应用了 softmax 函数,然后计算对数损失。

## TODO: Specify loss and optimization functions# specify loss function
criterion = nn.CrossEntropyLoss()# specify optimizer
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

训练网络:1.清空所有已优化变量的梯度 2.前向传播:通过向模型传入输入,计算预测输出。 3.计算损失 4.反向传播:计算损失相对于模型参数的梯度 5.执行一个优化步骤(参数更新) 6.更新平均训练损失

# number of epochs to train the model
n_epochs = 50  # suggest training between 20-50 epochs# initialize tracker for minimum validation loss
valid_loss_min = np.Inf # set initial "min" to infinityfor epoch in range(n_epochs):# monitor training losstrain_loss = 0.0valid_loss = 0.0model.train() # prep model for training#################### train the model ####################for data, target in train_loader:# clear the gradients of all optimized variablesoptimizer.zero_grad()# forward pass: compute predicted outputs by passing inputs to the modeloutput = model(data)# calculate the lossloss = criterion(output, target)# backward pass: compute gradient of the loss with respect to model parametersloss.backward()# perform a single optimization step (parameter update)optimizer.step()# update running training losstrain_loss += loss.item()*data.size(0)######################    # validate the model #######################model.eval()for data,target in valid_loader:output = model(data)loss = criterion(output,target)valid_loss += loss.item()*data.size(0)# print training/validation statistics # calculate average loss over an epochtrain_loss = train_loss/len(train_loader.dataset)valid_loss = valid_loss/len(valid_loader.dataset)print('Epoch: {} \tTraining Loss: {:.6f}\tValidation Loss:{:.6f}'.format(epoch+1, train_loss,valid_loss))# save model if validation loss has decreasedif valid_loss <= valid_loss_min:print("Validation los decreased({:.6f}-->{:.6f}). Saving model ..".format(valid_loss_min,valid_loss))torch.save(model.state_dict(),"model.pt")valid_loss_min = valid_loss

测试训练的网络:model.eval( 会将模型中的所有层级设为评估模式。这样会影响到丢弃层等层级,但是应该会允许所有节点接受评估。丢弃层是指会在训练期间按照某个概率关闭节点的层级。

# initialize lists to monitor test loss and accuracy
test_loss = 0.0
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))model.eval() # prep model for *evaluation*for data, target in test_loader:# forward pass: compute predicted outputs by passing inputs to the modeloutput = model(data)# calculate the lossloss = criterion(output, target)# update test loss test_loss += loss.item()*data.size(0)# convert output probabilities to predicted class_, pred = torch.max(output, 1)# compare predictions to true labelcorrect = np.squeeze(pred.eq(target.data.view_as(pred)))# calculate test accuracy for each object classfor i in range(batch_size):label = target.data[i]class_correct[label] += correct[i].item()class_total[label] += 1# calculate and print avg test loss
test_loss = test_loss/len(test_loader.dataset)
print('Test Loss: {:.6f}\n'.format(test_loss))for i in range(10):if class_total[i] > 0:print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (str(i), 100 * class_correct[i] / class_total[i],np.sum(class_correct[i]), np.sum(class_total[i])))else:print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (100. * np.sum(class_correct) / np.sum(class_total),np.sum(class_correct), np.sum(class_total)))