Training a classifier
你已經(jīng)學(xué)習(xí)了如何定義神經(jīng)網(wǎng)絡(luò),計(jì)算損失和執(zhí)行網(wǎng)絡(luò)權(quán)重的更新。
現(xiàn)在你或許在思考。
What about data?
通常當(dāng)你需要處理圖像,文本,音頻,視頻數(shù)據(jù),你能夠使用標(biāo)準(zhǔn)的python包將數(shù)據(jù)加載進(jìn)numpy數(shù)組。之后你能夠轉(zhuǎn)換這些數(shù)組到torch.*Tensor。
- 對于圖片,類似于Pillow,OPenCV的包很有用
- 對于音頻,類似于scipy和librosa的包
- 對于文字,無論是基于原生python和是Cython的加載,或者NLTK和SpaCy都有效
對于視覺,我們特意創(chuàng)建了一個(gè)包叫做torchvision,它有常見數(shù)據(jù)集的數(shù)據(jù)加載,比如ImageNet,CIFAR10,MNIST等,還有圖片的數(shù)據(jù)轉(zhuǎn)換,torchvision.datasets和torch.utils.data.Dataloader。
這提供了很方便的實(shí)現(xiàn),避免了寫樣板代碼。
對于這一文章,我們將使用CIFAR10數(shù)據(jù)集。它擁有飛機(jī),汽車,鳥,貓,鹿,狗,霧,馬,船,卡車等類別。CIFAR-10的圖片尺寸為3*32*32,也就是3個(gè)顏色通道和32*32個(gè)像素。
?
Training? an image classifier
?我們將按照順序執(zhí)行如下步驟:
?
1.加載并標(biāo)準(zhǔn)化CIFAR10
使用torchvision,加載CIFAR10非常簡單
import torch import torchvision import torchvision.transforms as transformstorchvision數(shù)據(jù)集的輸出是PIL圖片庫圖片,范圍為[0,1]。我們將它們轉(zhuǎn)換為tensor并標(biāo)準(zhǔn)化為[-1,1]。
import torch import torchvision import torchvision.transforms as transformstransform=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.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') out: Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz Files already downloaded and verified
?我們來觀察一下訓(xùn)練集圖片
import matplotlib.pyplot as plt import numpy as npdef imshow(img):img=img/2+0.5npimg=img.numpy()plt.imshow(np.transpose(npimg,(1,2,0)))dataiter=iter(trainloader) images,labels=dataiter.next()imshow(torchvision.utils.make_grid(images)) plt.show() print(''.join('%5s'%classes[labels[j]] for j in range(4)))?
out: truck truck dog truck?
?2.定義卷積神經(jīng)網(wǎng)絡(luò)
從前面神經(jīng)網(wǎng)絡(luò)章節(jié)復(fù)制神經(jīng)網(wǎng)絡(luò),并把它改成接受3維圖片輸入(而不是之前定義的一維圖片)。
import torch.nn as nn import torch.nn.functional as Fclass 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 xnet=Net()?
?3.定義損失函數(shù)和優(yōu)化器
我們使用分類交叉熵?fù)p失和帶有動量的SGD
import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9)?
4.訓(xùn)練網(wǎng)絡(luò)
我們只需要簡單地迭代數(shù)據(jù),把輸入喂進(jìn)網(wǎng)絡(luò)并優(yōu)化。
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.0for i,data in enumerate(trainloader,0):inputs,labels=dataoptimizer.zero_grad()outputs=net(inputs)loss=criterion(outputs,labels)loss.backward()optimizer.step()running_loss+=loss.item()if i%2000==1999:print('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))running_loss=0 print('Finished Training') out: [1, 2000] loss: 2.208 [1, 4000] loss: 1.797 [1, 6000] loss: 1.627 [1, 8000] loss: 1.534 [1, 10000] loss: 1.508 [1, 12000] loss: 1.453 [2, 2000] loss: 1.378 [2, 4000] loss: 1.365 [2, 6000] loss: 1.326 [2, 8000] loss: 1.309 [2, 10000] loss: 1.290 [2, 12000] loss: 1.262 Finished Training?
?
4.在測試數(shù)據(jù)集上測試網(wǎng)絡(luò)
我們已經(jīng)遍歷了兩遍訓(xùn)練集來訓(xùn)練網(wǎng)絡(luò)。需要檢查下網(wǎng)絡(luò)是不是已經(jīng)學(xué)習(xí)到了什么。
我們將檢查神經(jīng)網(wǎng)絡(luò)輸出的預(yù)測標(biāo)簽是否與真實(shí)標(biāo)簽相同。如果預(yù)測是正確的,我們將這一樣本加入到正確預(yù)測的列表。
我們先來熟悉一下訓(xùn)練圖片。
dataiter=iter(testloader) images,labes=dataiter.next()imshow(torchvision.utils.make_grid(images)) plt.show() print('GroundTruth: ',' '.join('%5s' % classes[labels[j]] for j in range(4)))?
out: GroundTruth: plane deer dog horse?ok,現(xiàn)在讓我們看一下神經(jīng)網(wǎng)絡(luò)認(rèn)為這些樣本是什么。
outputs=net(images)?輸出是10個(gè)類別的量值,大的值代表網(wǎng)絡(luò)認(rèn)為某一類的可能性更大。所以我們來獲得最大值得索引:
_,predicted=torch.max(outputs,1) print("Predicted: ",' '.join('%5s' %classes[predicted[j]] for j in range(4))) out: Predicted: bird dog deer horse?讓我們看看整個(gè)數(shù)據(jù)集上的模型表現(xiàn)。
out: Accuracy of the network on the 10000 test images: 54 %?這看起來要好過瞎猜,隨機(jī)的話只要10%的準(zhǔn)確率(因?yàn)槭?0類)。看來網(wǎng)絡(luò)是學(xué)習(xí)到了一些東西。
我們來繼續(xù)看看在哪些類上的效果好,在哪些類上的效果比較差:
out: Accuracy of plane : 56 % Accuracy of car : 70 % Accuracy of bird : 27 % Accuracy of cat : 16 % Accuracy of deer : 44 % Accuracy of dog : 64 % Accuracy of frog : 61 % Accuracy of horse : 73 % Accuracy of ship : 68 % Accuracy of truck : 61 %好了,接下來該干點(diǎn)啥?
我們怎樣將這個(gè)神經(jīng)網(wǎng)絡(luò)運(yùn)行在GPU上呢?
Trainning on GPU
就像你怎么把一個(gè)Tensor轉(zhuǎn)移到GPU上一樣,現(xiàn)在把神經(jīng)網(wǎng)絡(luò)轉(zhuǎn)移到GPU上。
如果我們有一個(gè)可用的CUDA,首先將我們的設(shè)備定義為第一個(gè)可見的cuda設(shè)備:
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print(device) out: cuda:0?剩下的章節(jié)我們假定我們的設(shè)備是CUDA。
之后這些方法將遞歸到所有模塊,將其參數(shù)和緩沖區(qū)轉(zhuǎn)換為CUDA張量:
net.to(device)?記得你還需要在每步循環(huán)里將數(shù)據(jù)轉(zhuǎn)移到GPU上:
inputs,labels=inputs.to(device),labels.to(device)為什么沒注意到相對于CPU巨大的速度提升?這是因?yàn)槟愕木W(wǎng)絡(luò)還非常小。
?
練習(xí):嘗試增加你網(wǎng)絡(luò)的寬度(第一個(gè)nn.Conv2d的參數(shù)2應(yīng)該與第二個(gè)nn.Conv2d的參數(shù)1是相等的數(shù)字),觀察你得到的速度提升。
達(dá)成目標(biāo):
- 更深一步理解Pytorch的Tensor庫和神經(jīng)網(wǎng)絡(luò)
- 訓(xùn)練一個(gè)小神經(jīng)網(wǎng)絡(luò)來分類圖片
?Trainning on multiple GPUs
如果你想看到更加顯著的GPU加速,請移步:https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html
?
轉(zhuǎn)載于:https://www.cnblogs.com/Thinker-pcw/p/9637411.html
總結(jié)
以上是生活随笔為你收集整理的Training a classifier的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R语言与医学统计图形【4】直方图、金字塔
- 下一篇: 【24小时内第四更】为什么我们要坚持写博