原标题 | A Gentle Introduction to PyTorch 1.2
作 者 | Elvis
翻 译 | 天字一号(郑州大学)、Pita、david95(杭州电子科技大学)、韦纳尔•邓肯
这篇教程将为你全面的介绍使用PyTorch训练神经网络的基本知识。
在我们之前的教程中,我们介绍了如何在Google Colab上快速上手PyTorch 1.2。这一次,我们会再次回顾学习一些基本的模块,介绍如何使用PyTorch构建一个神经网络模型。比如,我们会使用少量的堆叠层,构建一个图像分类器模型,然后评估这个模型。
这次的教程会比较短,并且尽可能地避免使用“术语”和太难懂的代码。就是说,这可能是你能用PyTorch构建出的最基础的神经网络模型。
实际上,这次要讲的非常基础,非常适合PyTorch和机器学习的初学者。所以如果你有一个朋友或者同学想要一起学习,我强烈建议你推荐他们以这篇教程作为入门。让我们开始吧!
在开始上手写代码之前,你需要先安装最新版本的 PyTorch。我们在此教程中使用 Google Colab,因此我们将使用以下命令安装 PyTorch。你也可以在这篇博文的末尾找到一个 Colab notebook。
pip3 install torch==1.2.0+cu92 torchvision==0.4.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html
现在我们需要导入一些模块,这些模块将有助于获得必要的函数,以帮助我们建立我们的神经网络模型。主要导入的模块有 torch 和 torchvision。它们包含了让你入门 PyTorch 所需的大部分功能。但是,由于这是一个机器学习教程,我们还需要 torch.nn、torch.nn.functional 和 torchvision.transforms,它们都包含实用函数以构建我们的模型。我们可能不会使用下面列出的所有模块,但它们是你开始你的机器学习项目之前需要导入的典型模块。
## The usual imports
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
## for printing image
import matplotlib.pyplot as plt
import numpy as np
我们使用下面的命令检查 PyTorch 版本,以确保你正在使用的是本教程使用的正确版本。在本教程中,我们使用 PyTorch 1.2。
加载数据
开始一个机器学习的工程,首先需要加载数据。这里我们使用 MNIST数据集(http://yann.lecun.com/exdb/mnist/)。这个数据集可以看做是机器学习的入门数据集。
该数据集中包含一系列的手写数字图像,图像大小为28*28。下面我们会对数据进行介绍,加载数据的时候采用批量大小为32,如下图所示。
下面是我们加载数据的完整步骤:
我们来仔细看看trainset和testset包含的内容:
print(trainset)
print(testset)
## output
Dataset MNIST
Number of datapoints: 60000
Root location: ./data
Split: Train
StandardTransform
Transform: Compose(ToTensor())
Dataset MNIST
Number of datapoints: 10000
Root location: ./data
Split: Test
StandardTransform Transform: Compose(ToTensor())
下面详细介绍几个参数:
再看一看transforms.Compose(...) 函数和它的功能。我们随便生成一张图像,看看它是怎么使用的。
image = transforms.ToPILImage(mode='L')(torch.randn(1, 96, 96))
显示生成的图像
plt.imshow(image)
输出结果
现在我们有了一张图像,我们对它应用一些虚拟变换。对图像进行45度旋转,以下的转换过程将解决这个问题:
## dummy transformation
dummy_transform = transforms.Compose(
[transforms.RandomRotation(45)])
dummy_result = dummy_transform(image)
plt.imshow(dummy_result)
输出结果
你可以使用transforms.Compose(...)对图像进行多种变换。Pytorch内置了多种变换函数,事实上你也可以自己写转换函数。看看另外一个变换的效果:旋转+水平翻转
## dummy transform
dummy2_transform = transforms.Compose(
[transforms.RandomRotation(45), transforms.RandomVerticalFlip()])
dummy2_result = dummy2_transform(image)
plt.imshow(dummy2_result)
输出结果
是不是看起来很酷,你可以尝试其他的转换方法。关于进一步研究我们的数据的主题,让我们接下来仔细看看我们的图像数据集。
探索数据
作为一名从业者和研究人员,我总是花费一些时间和精力来探索和理解我的数据集。这是一个有趣的并且很有意义的做法,以确保训练模型之前一切井然。
让我们检查训练和测试数据集包含的内容。我将使用 matplotlib 库从数据集打印出一些图像。使用一点numpy代码,我可以将图像转换为正确的格式来打印出来。下面我打印出一整批 32 张图像:
## functions to show an image
def imshow(img):
#img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
## get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
## show images
imshow(torchvision.utils.make_grid(images))
输出结果:
打印batches的维度信息:
for images, labels in trainloader:
print("Image batch dimensions:", images.shape)
print("Image label dimensions:", labels.shape)
break
结果
模型
现在可以构建用于执行图像分类任务的卷积神经网络模型了。为了简化,我们的将堆叠使用一个dense层,一个dropout层和一个output层 来训练模型。
关于模型的讨论:
首先,以下结构涉及名为MyModel的类,是用于在PyTorch中构建神经网络模型的标准代码:
## the model
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.d1 = nn.Linear(28 * 28, 128)
self.dropout = nn.Dropout(p=0.2)
self.d2 = nn.Linear(128, 10)
def forward(self, x):
x = x.flatten(start_dim = 1)
x = self.d1(x)
x = F.relu(x)
x = self.dropout(x)
logits = self.d2(x)
out = F.softmax(logits, dim=1)
return out
直观地说,下面就是我们刚刚构建的模型图。但是隐藏层比图中显示的大很多,但由于空间限制,该图应被视为实际模型的近似表示。
正如我在前面的教程中所做的那样,我总是鼓励用一个批处理来测试模型,以确保输出的维度符合我们的预期。请注意,我们是怎样迭代数据加载器,它可以方便地存储图像和标签对。out 包含模型的输出,这是应用了softmax层的logits来帮助预测。
## test the model with 1 batch
model = MyModel()
for images, labels in trainloader:
print("batch size:", images.shape)
out = model(images)
print(out.shape)
break
输出结果:
batch size: torch.Size([32, 1, 28, 28])
torch.Size([32, 10])
我们可以清楚地看到,我们返回批次中有10个输出值与批次中的每个图像相关联;这些值将被用于检查模型的性能。
训练模型
在准备好训练模型之前,我们需要设置一个损失函数、一个优化器和一个效用函数来计算模型的准确性:
learning_rate = 0.001
num_epochs = 5
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = MyModel()
model = model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
效用函数将在下面进行定义,它有助于计算模型的准确率。了解它是如何计算的在目前来看并不是很重要,我们只需要了解它是通过比较模型的输出结果(预测)和实际目标值(数据集的标签)来计算预测的准确率。
训练模型
现在可以训练模型了,代码如下:
## train the model
for epoch in range(num_epochs):
train_running_loss = 0.0
train_acc = 0.0
## commence training
model = model.train()
## training step
for i, (images, labels) in enumerate(trainloader):
images = images.to(device)
labels = labels.to(device)
## forward + backprop + loss
predictions = model(images)
loss = criterion(predictions, labels)
optimizer.zero_grad()
loss.backward()
## update model params
optimizer.step()
train_running_loss += loss.detach().item()
train_acc += get_accuracy(predictions, labels, BATCH_SIZE)
model.eval()
print('Epoch: %d | Loss: %.4f | Train Accuracy: %.2f' \
%(epoch, train_running_loss / i, train_acc/i))
for epoch in range(num_epochs):
...
输出结果如下:
Epoch: 0 | Loss: 1.6167 | Train Accuracy: 86.02
Epoch: 1 | Loss: 1.5299 | Train Accuracy: 93.26
Epoch: 2 | Loss: 1.5143 | Train Accuracy: 94.69
Epoch: 3 | Loss: 1.5059 | Train Accuracy: 95.46
Epoch: 4 | Loss: 1.5003 | Train Accuracy: 95.98
训练完毕,我们可以清楚地看到损失值一直在下降,精度一直在上升,说明我们的模型是有效的,可以用于图像的分类任务。
我们可以通过对测试数据计算精度,来验证我们的模型是否在分类任务表现良好。通过下面的代码,你可以看到,在MINIST分类任务上,我们的模型表现的很好。
test_acc = 0.0
for i, (images, labels) in enumerate(testloader, 0):
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
test_acc += get_accuracy(outputs, labels, BATCH_SIZE)
print('Test Accuracy: %.2f'%( test_acc/i))
输出测试精度:
Test Accuracy: 96.32
结语
恭喜你已完成本教程?。这是一个全面的教程,目的是对使用神经网络和PyTorch进行基本的图像分类做一个非常基本的介绍。
本教程深受此TensorFlow教程的启发(https://www.tensorflow.org/beta/tutorials/quickstart/beginner)。我们感谢相应参考文献的作者所做的宝贵工作。
参考内容
? Colab Notebook(Colab 笔记本,https://colab.research.google.com/drive/1kl3--YxUIOoCcthoP47YLoSOoTxhNl0V)
? GitHub Repo (Github 仓库,https://github.com/omarsar/pytorch_notebooks)
via https://medium.com/dair-ai/pytorch-1-2-introduction-guide-f6fa9bb7597c