PyTorch教程之Neural Networks
我們可以通過torch.nn package構建神經網絡。
現在我們已經了解了autograd,nn基於autograd來定義模型並對他們有所區分。
一個 nn.Module模塊由如下部分構成:若幹層,以及返回output的
forward(input)方法。
例如,這張圖描述了進行數字圖像分類的神經網絡:
這是一個簡單的前饋( feed-forward)網絡,讀入input內容,每層接受前一級的輸入,並輸出到下一級,直到給出outpu結果。
一個經典神經網絡的訓練程序如下:
1.定義具有可學習參數(或權重)的神經網絡
2.遍歷iinput數據集
3.通過神經網絡對input進行處理得到output結果
4.計算損失(ouput離正確值有多遠)
5.將梯度返回到神經網絡的參數中
6.更新神經網絡的權重,通常使用一個簡單的更新規則:
weight = weight - learning_rate * gradient
一、如何在pytorch中定義神經網絡
定義神經網絡:
import torch from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): # 定義Net的初始化函數,本函數定義了神經網絡的基本結構def __init__(self): # 繼承父類的初始化方法,即先運行nn.Module的初始化函數 super(Net,self).__init__() # 定義卷積層:輸入1通道(灰度圖)的圖片,輸出6張特征圖,卷積核5x5 self.conv1 = nn.Conv2d(1,6,(5,5)) # 定義卷積層:輸入6張特征圖,輸出16張特征圖,卷積核5x5 self.conv2 = nn.Conv2d(6,16,5) # 定義全連接層:線性連接(y = Wx + b),16*5*5個節點連接到120個節點上self.fc1 = nn.Linear(16*5*5,120) # 定義全連接層:線性連接(y = Wx + b),120個節點連接到84個節點上 self.fc2 = nn.Linear(120,84) # 定義全連接層:線性連接(y = Wx + b),84個節點連接到10個節點上 self.fc3 = nn.Linear(84,10) # 定義向前傳播函數,並自動生成向後傳播函數(autograd) def forward(self,x): # 輸入x->conv1->relu->2x2窗口的最大池化->更新到x x = F.max_pool2d(F.relu(self.conv1(x)),(2,2)) # 如果大小是一個正方形,可以只指定一個數字 x = F.max_pool2d(F.relu(self.conv2(x)),2) # view函數將張量x變形成一維向量形式,總特征數不變,為全連接層做準備 x = x.view(-1,self.num_flat_features(x)) # 輸入x->fc1->relu,更新到x x = F.relu(self.fc1(x)) # 輸入x->fc2->relu,更新到x x = F.relu(self.fc2(x)) # 輸入x->fc3,更新到x x = self.fc3(x) return x # 計算張量x的總特征量 def num_flat_features(selfself,x): # 由於默認批量輸入,第零維度的batch剔除 size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features net = Net() print(net)
輸出結果:
Net ( (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) (fc1): Linear (400 -> 120) (fc2): Linear (120 -> 84) (fc3): Linear (84 -> 10) )
通過net.parameters()可以得到可學習的參數:
params = list(net.parameters()) print(len(params)) print(params[0].size()) # conv1‘s .weight
輸出結果:
10
torch.Size([6, 1, 5, 5])
我們模擬一下單向傳播,其中input和output均為autograd.Variable:
input = Variable(torch.randn(1, 1, 32, 32)) out = net(input) print(out)
輸出結果:
Variable containing:
-0.0618 -0.0648 -0.0350 0.0443 0.0633 -0.0414 0.0317 -0.1100 -0.0569 -0.0636
[torch.FloatTensor of size 1x10]
對所有參數的梯度緩沖區歸零並設置隨機梯度反向傳播:
net.zero_grad()
out.backward(torch.randn(1, 10))
整個torch.nn包只接受那種小批量樣本的數據,而無法接受單個樣本。 例如,nn.Conv2d能夠構建一個四維的Tensor:nSamples x nChannels x Height x Width。
如果需要對單個樣本進行操作,使用input.unsqueeze(0)來加一個假維度就可以了。
我們回顧一下目前出現過的概念:
torch.Tensor - 一個多維數組
autograd.Variable - 改變Tensor並且記錄下來歷史操作過程。和Tensor擁有相同的API,以及backward()的一些API。同時包含著和Tensor 相關的梯度。
nn.Module - 神經網絡模塊。便捷的數據封裝,能夠將運算移往GPU,還包括一些輸入輸出的東西。
nn.Parameter - 一種變量(Variable),當將任何值賦予Module時自動註冊為一個參數。
autograd.Function - 實現了使用自動求導方法的前饋和後饋的定義。每個Variable的操作都會生成至少一個獨立的Function節點,與生成了Variable的函數相連之後記錄下歷史操作過程。
二、Loss Function
PyTorch教程之Neural Networks