
目录一、关于数据二、训练分类器1、加载并标准化CIFAR102、定义卷积网络3、定义损失函数和优化器4、训练网络5、在测试数据上测试神经网络三、在GPU上训练一、关于数据通常当你需要处理图像、文本、音频或视频数据时你可以使用标准Python包来将数据加载到NumPy数组中。然后将数组转化为torch.*Tensor。对于图像可以使用包PillowOpenCV对于音频可以使用包scipylibrosa对于文本可以使用NLTKSpaCy特别是对于视觉我们创建了一个名为torchvision的包它包含用于常见数据集的数据加载器如ImagenetCIFAR10MNIST等以及用于图像的数据转换器即torchvision.datasets和torch.utils.data.DataLoader。对于本教程我们将使用CIFAR10数据集。它包含10个类 ‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。图片的大小为3x32x32即尺寸为32×32像素的3通道彩色图像。二、训练分类器我们将会依次执行以下步骤使用torchvision加载和标准化CIFAR10训练和测试数据集定义卷积神经网络定义损失函数在训练数据上训练网络在测试数据上测试网络1、加载并标准化CIFAR10import torch import torchvision import torchvision.transforms as transformstorchvision数据集的输出是范围[0,1]的PILImage图像。 我们将它们转换为归一化范围的tensor[-1,1]。transform transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset torchvision.datasets.CIFAR10(root./data, trainTrue, downloadTrue, transformtransform) trainloader torch.utils.data.DataLoader(trainset, batch_size4, shuffleTrue, num_workers2) testset torchvision.datasets.CIFAR10(root./data, trainFalse, downloadTrue, transformtransform) testloader torch.utils.data.DataLoader(testset, batch_size4, shuffleFalse, num_workers2) classes (plane, car, bird, cat, deer, dog, frog, horse, ship, truck)输出Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz Extracting ./data/cifar-10-python.tar.gz to ./data Files already downloaded and verified让我们展示一些训练图片import matplotlib.pyplot as plt import numpy as np # 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))) plt.show() # get some random training images dataiter iter(trainloader) images, labels dataiter.next() # show images imshow(torchvision.utils.make_grid(images)) # print labels print( .join(%5s % classes[labels[j]] for j in range(4)))输出frog ship cat plane2、定义卷积网络import torch.nn as nn import torch.nn.functional as F class Net(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) def forward(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 x net Net()3、定义损失函数和优化器让我们使用分类交叉熵损失函数和带动量的SGD。import torch.optim as optim criterion nn.CrossEntropyLoss() optimizer optim.SGD(net.parameters(), lr0.001, momentum0.9)4、训练网络我们只需循环遍历数据迭代器并将输入提供给神经网络并进行优化。for epoch in range(2): # loop over the dataset multiple times running_loss 0.0 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 criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss loss.item() if i % 2000 1999: # print every 2000 mini-batches print([%d, %5d] loss: %.3f % (epoch 1, i 1, running_loss / 2000)) running_loss 0.0 print(Finished Training)输出[1, 2000] loss: 2.169 [1, 4000] loss: 1.808 [1, 6000] loss: 1.659 [1, 8000] loss: 1.553 [1, 10000] loss: 1.488 [1, 12000] loss: 1.455 [2, 2000] loss: 1.379 [2, 4000] loss: 1.346 [2, 6000] loss: 1.320 [2, 8000] loss: 1.305 [2, 10000] loss: 1.275 [2, 12000] loss: 1.262 Finished Training5、在测试数据上测试神经网络我们已经在训练数据集上训练了两次。 但我们需要检查神经网络是否已经学到了什么。我们将通过预测神经网络输出的类标签来检查这一点并根据真实情况进行检查。 如果预测正确我们将样本添加到正确预测列表中。我们首先展示测试集中的一些图片dataiter iter(testloader) images, labels dataiter.next() # print images imshow(torchvision.utils.make_grid(images)) print(GroundTruth: , .join(%5s % classes[labels[j]] for j in range(4)))输出GroundTruth: cat ship ship plane现在我们来看一看神经网络认为这些图片是什么。outputs是10个类的能量。 一个类的能量越高网络认为图像是特定类的可能性越大。 那么让我们得到最高能量的索引outputs net(images) _, predicted torch.max(outputs, 1) print(Predicted: , .join(%5s % classes[predicted[j]] for j in range(4)))输出Predicted: cat plane plane ship查看神经网络在整个数据集上的表现correct 0 total 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 10000 test images: %d %% % ( 100 * correct / total))输出Accuracy of the network on the 10000 test images: 54 %查看表现最好的类和最坏的类class_correct list(0. for i in range(10)) class_total list(0. for i in range(10)) with torch.no_grad(): for data in testloader: images, labels data outputs net(images) _, predicted torch.max(outputs, 1) c (predicted labels).squeeze() for i in range(4): label labels[i] class_correct[label] c[i].item() class_total[label] 1 for i in range(10): print(Accuracy of %5s : %2d %% % ( classes[i], 100 * class_correct[i] / class_total[i]))输出Accuracy of plane : 46 % Accuracy of car : 63 % Accuracy of bird : 50 % Accuracy of cat : 37 % Accuracy of deer : 40 % Accuracy of dog : 51 % Accuracy of frog : 70 % Accuracy of horse : 48 % Accuracy of ship : 76 % Accuracy of truck : 64 %三、在GPU上训练如果我们有可用的CUDA我们首先将我们的设备定义为第一个可见的cuda设备device torch.device(cuda:0 if torch.cuda.is_available() else cpu) # Assuming that we are on a CUDA machine, this should print a CUDA device: print(device)输出cuda:0本节的其余部分假定设备是CUDA设备。然后这些方法将递归遍历所有模块并将其参数和缓冲区转换为CUDA tensornet.to(device)还必须将每一步的输入和目标发送到GPUinputs, labels data[0].to(device), data[1].to(device)