%matplotlib inline
上一讲中已经看到如何去定义一个神经网络,计算损失值和更新网络的权重。
你如今可能在想下一步。python
通常状况下处理图像、文本、音频和视频数据时,可使用标准的Python包来加载数据到一个numpy数组中。
而后把这个数组转换成 torch.*Tensor
。数组
特别的,对于图像任务,咱们建立了一个包
torchvision
,它包含了处理一些基本图像数据集的方法。这些数据集包括
Imagenet, CIFAR10, MNIST 等。除了数据加载之外,torchvision
还包含了图像转换器,
torchvision.datasets
和 torch.utils.data.DataLoader
。网络
torchvision
包不只提供了巨大的便利,也避免了代码的重复。函数
在这个教程中,咱们使用CIFAR10数据集,它有以下10个类别
:‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’,
‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。CIFAR-10的图像都是
3x32x32大小的,即,3颜色通道,32x32像素。学习
依次按照下列顺序进行:测试
torchvision
加载和归一化CIFAR10训练集和测试集在测试集上测试网络优化
使用torchvision
能够很是容易地加载CIFAR10。code
import torch import torchvision import torchvision.transforms as transforms
torchvision的输出是[0,1]的PILImage图像,咱们把它转换为归一化范围为[-1, 1]的张量。orm
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', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2) 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 100%|███████████████████████████████████████████████████████████████▉| 170483712/170498071 [30:34<00:00, 144484.30it/s] Files already downloaded and verified 170500096it [30:50, 144484.30it/s]
咱们展现一些训练图像。视频
import matplotlib.pyplot as plt import numpy as np # 展现图像的函数 def imshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) # 获取随机数据 dataiter = iter(trainloader) images, labels = dataiter.next() # 展现图像 imshow(torchvision.utils.make_grid(images)) # 显示图像标签 print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
ship dog dog plane
从以前的神经网络一节复制神经网络代码,并修改成输入3通道图像。
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()
咱们使用交叉熵做为损失函数,使用带动量的随机梯度降低。
import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
有趣的时刻开始了。
咱们只需在数据迭代器上循环,将数据输入给网络,并优化。
for epoch in range(2): # 多批次循环 running_loss = 0.0 for i, data in enumerate(trainloader, 0): # 获取输入 inputs, labels = data # 梯度置0 optimizer.zero_grad() # 正向传播,反向传播,优化 outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 打印状态信息 running_loss += loss.item() if i % 2000 == 1999: # 每2000批次打印一次 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training')
[1, 2000] loss: 2.168 [1, 4000] loss: 1.848 [1, 6000] loss: 1.663 [1, 8000] loss: 1.573 [1, 10000] loss: 1.529 [1, 12000] loss: 1.458 [2, 2000] loss: 1.412 [2, 4000] loss: 1.390 [2, 6000] loss: 1.352 [2, 8000] loss: 1.317 [2, 10000] loss: 1.306 [2, 12000] loss: 1.299 Finished Training
咱们在整个训练集上进行了2次训练,可是咱们须要检查网络是否从数据集中学习到有用的东西。
经过预测神经网络输出的类别标签与实际状况标签进行对比来进行检测。
若是预测正确,咱们把该样本添加到正确预测列表。
第一步,显示测试集中的图片并熟悉图片内容。
dataiter = iter(testloader) images, labels = dataiter.next() # 显示图片 imshow(torchvision.utils.make_grid(images)) print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
GroundTruth: cat ship ship plane
让咱们看看神经网络认为以上图片是什么。
outputs = net(images)
输出是10个标签的能量。
一个类别的能量越大,神经网络越认为它是这个类别。因此让咱们获得最高能量的标签。
_, predicted = torch.max(outputs, 1) print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))
Predicted: cat ship ship 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: 53 %
结果看起来不错,至少比随机选择要好,随机选择的正确率为10%。
彷佛网络学习到了一些东西。
在识别哪个类的时候好,哪个很差呢?
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 : 61 % Accuracy of bird : 33 % Accuracy of cat : 39 % Accuracy of deer : 43 % Accuracy of dog : 54 % Accuracy of frog : 76 % Accuracy of horse : 47 % Accuracy of ship : 75 % Accuracy of truck : 60 %
下一步?
咱们如何在GPU上运行神经网络呢?
把一个神经网络移动到GPU上训练就像把一个Tensor转换GPU上同样简单。而且这个操做会递归遍历有所模块,并将其参数和缓冲区转换为CUDA张量。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 确认咱们的电脑支持CUDA,而后显示CUDA信息: print(device)
本节的其他部分假定device
是CUDA设备。
而后这些方法将递归遍历全部模块并将模块的参数和缓冲区
转换成CUDA张量:
net.to(device)
记住:inputs 和 targets 也要转换。
inputs, labels = inputs.to(device), labels.to(device)
为何咱们没注意到GPU的速度提高不少?那是由于网络很是的小。
实践:
尝试增长你的网络的宽度(第一个nn.Conv2d
的第2个参数,第二个nn.Conv2d
的第一个参数,它们须要是相同的数字),看看你获得了什么样的加速。
实现的目标:
译者注:后面咱们教程会训练一个真正的网络,使识别率达到90%以上。
若是你想使用全部的GPU获得更大的加速,
请查看数据并行处理。
训练神经网络玩电子游戏 </intermediate/reinforcement_q_learning>
在ImageNet上训练最好的ResNet
使用对抗生成网络来训练一我的脸生成器
使用LSTM网络训练一个字符级的语言模型
更多示例
更多教程
在论坛上讨论PyTorch
Slack上与其余用户讨论