%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上與其餘用戶討論