【深度学习】翻译:60分钟入门PyTorch(四)——训练一个分类器
前言
原文翻譯自:Deep Learning with PyTorch: A 60 Minute Blitz
翻譯:林不清(https://www.zhihu.com/people/lu-guo-92-42-88)
目錄
60分鐘入門PyTorch(一)——Tensors
60分鐘入門PyTorch(二)——Autograd自動求導
60分鐘入門Pytorch(三)——神經網絡
60分鐘入門PyTorch(四)——訓練一個分類器
訓練一個分類器
你已經學會如何去定義一個神經網絡,計算損失值和更新網絡的權重。
你現在可能在思考:數據哪里來呢?
關于數據
通常,當你處理圖像,文本,音頻和視頻數據時,你可以使用標準的Python包來加載數據到一個numpy數組中.然后把這個數組轉換成torch.*Tensor。
對于圖像,有諸如Pillow,OpenCV包等非常實用
對于音頻,有諸如scipy和librosa包
對于文本,可以用原始Python和Cython來加載,或者使用NLTK和SpaCy 對于視覺,我們創建了一個torchvision包,包含常見數據集的數據加載,比如Imagenet,CIFAR10,MNIST等,和圖像轉換器,也就是torchvision.datasets和torch.utils.data.DataLoader。
這提供了巨大的便利,也避免了代碼的重復。
在這個教程中,我們使用CIFAR10數據集,它有如下10個類別:’airplane’,’automobile’,’bird’,’cat’,’deer’,’dog’,’frog’,’horse’,’ship’,’truck’。這個數據集中的圖像大小為3*32*32,即,3通道,32*32像素。
訓練一個圖像分類器
我們將按照下列順序進行:
使用torchvision加載和歸一化CIFAR10訓練集和測試集.
定義一個卷積神經網絡
定義損失函數
在訓練集上訓練網絡
在測試集上測試網絡
1. 加載和歸一化CIFAR10
使用torchvision加載CIFAR10是非常容易的。
%matplotlib?inline import?torch import?torchvision import?torchvision.transforms?as?transformstorchvision的輸出是[0,1]的PILImage圖像,我們把它轉換為歸一化范圍為[-1, 1]的張量。
注意
如果在Windows上運行時出現BrokenPipeError,嘗試將torch.utils.data.DataLoader()的num_worker設置為0。
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') #這個過程有點慢,會下載大約340mb圖片數據。我們展示一些有趣的訓練圖像。
import?matplotlib.pyplot?as?plt import?numpy?as?np#?functions?to?show?an?imagedef?imshow(img):img?=?img?/?2?+?0.5?????#?unnormalizenpimg?=?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)))2. 定義一個卷積神經網絡
從之前的神經網絡一節復制神經網絡代碼,并修改為接受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. 定義損失函數和優化器
我們使用交叉熵作為損失函數,使用帶動量的隨機梯度下降。
import?torch.optim?as?optimcriterion?=?nn.CrossEntropyLoss() optimizer?=?optim.SGD(net.parameters(),?lr=0.001,?momentum=0.9)4. 訓練網絡
這是開始有趣的時刻,我們只需在數據迭代器上循環,把數據輸入給網絡,并優化。
for?epoch?in?range(2):??#?loop?over?the?dataset?multiple?timesrunning_loss?=?0.0for?i,?data?in?enumerate(trainloader,?0):#?get?the?inputs;?data?is?a?list?of?[inputs,?labels]inputs,?labels?=?data#?zero?the?parameter?gradientsoptimizer.zero_grad()#?forward?+?backward?+?optimizeoutputs?=?net(inputs)loss?=?criterion(outputs,?labels)loss.backward()optimizer.step()#?print?statisticsrunning_loss?+=?loss.item()if?i?%?2000?==?1999:????#?print?every?2000?mini-batchesprint('[%d,?%5d]?loss:?%.3f'?%(epoch?+?1,?i?+?1,?running_loss?/?2000))running_loss?=?0.0print('Finished?Training')保存一下我們的訓練模型
PATH?=?'./cifar_net.pth' torch.save(net.state_dict(),?PATH)點擊這里查看關于保存模型的詳細介紹
5. 在測試集上測試網絡
我們在整個訓練集上訓練了兩次網絡,但是我們還需要檢查網絡是否從數據集中學習到東西。
我們通過預測神經網絡輸出的類別標簽并根據實際情況進行檢測,如果預測正確,我們把該樣本添加到正確預測列表。
第一步,顯示測試集中的圖片一遍熟悉圖片內容。
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)))接下來,讓我們重新加載我們保存的模型(注意:保存和重新加載模型在這里不是必要的,我們只是為了說明如何這樣做):
net?=?Net() net.load_state_dict(torch.load(PATH))現在我們來看看神經網絡認為以上圖片是什么?
outputs?=?net(images)輸出是10個標簽的概率。一個類別的概率越大,神經網絡越認為他是這個類別。所以讓我們得到最高概率的標簽。
_,?predicted?=?torch.max(outputs,?1)print('Predicted:?',?'?'.join('%5s'?%?classes[predicted[j]]for?j?in?range(4)))這結果看起來非常的好。
接下來讓我們看看網絡在整個測試集上的結果如何。
correct?=?0 total?=?0 with?torch.no_grad():for?data?in?testloader:images,?labels?=?dataoutputs?=?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))結果看起來好于偶然,偶然的正確率為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?=?dataoutputs?=?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]?+=?1for?i?in?range(10):print('Accuracy?of?%5s?:?%2d?%%'?%?(classes[i],?100?*?class_correct[i]?/?class_total[i]))接下來干什么?
我們如何在GPU上運行神經網絡呢?
在GPU上訓練
你是如何把一個Tensor轉換GPU上,你就如何把一個神經網絡移動到GPU上訓練。這個操作會遞歸遍歷有所模塊,并將其參數和緩沖區轉換為CUDA張量。
device?=?torch.device("cuda:0"?if?torch.cuda.is_available()?else?"cpu") #?Assume?that?we?are?on?a?CUDA?machine,?then?this?should?print?a?CUDA?device: #假設我們有一臺CUDA的機器,這個操作將顯示CUDA設備。 print(device)接下來假設我們有一臺CUDA的機器,然后這些方法將遞歸遍歷所有模塊并將其參數和緩沖區轉換為CUDA張量:
net.to(device)請記住,你也必須在每一步中把你的輸入和目標值轉換到GPU上:
inputs,?labels?=?inputs.to(device),?labels.to(device)為什么我們沒注意到GPU的速度提升很多?那是因為網絡非常的小。
實踐:
嘗試增加你的網絡的寬度(第一個nn.Conv2d的第2個參數, 第二個nn.Conv2d的第一個參數,他們需要是相同的數字),看看你得到了什么樣的加速。
實現的目標:
深入了解了PyTorch的張量庫和神經網絡
訓練了一個小網絡來分類圖片
在多GPU上訓練
如果你希望使用所有GPU來更大的加快速度,請查看選讀:[數據并行]:(https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html)
接下來做什么?
訓練神經網絡玩電子游戲
在ImageNet上訓練最好的ResNet
使用對抗生成網絡來訓練一個人臉生成器
使用LSTM網絡訓練一個字符級的語言模型
更多示例
更多教程
在論壇上討論PyTorch
在Slack上與其他用戶聊天
總結
以上是生活随笔為你收集整理的【深度学习】翻译:60分钟入门PyTorch(四)——训练一个分类器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【深度学习】李沐《动手学深度学习》的Py
- 下一篇: win11 32位官方版原版镜像文件v2