正文為方便用戶使用,,PyTorch實(shí)現(xiàn)了神經(jīng)網(wǎng)絡(luò)中絕大多數(shù)的layer,,這些layer都繼承于nn.Module,封裝了可學(xué)習(xí)參數(shù)parameter,,并實(shí)現(xiàn)了forward函數(shù),,且很多都專門針對GPU運(yùn)算進(jìn)行了CuDNN優(yōu)化,其速度和性能都十分優(yōu)異,。 如nn.Linear(in_features, out_features, bias),,需關(guān)注這三個(gè)參數(shù)的作用。 如nn.Linear中有weight和bias兩個(gè)可學(xué)習(xí)參數(shù)輸入輸出的形狀,如nn.linear的輸入形狀是(N, input_features),,輸出為(N,,output_features),N是batch_size,。 在PyTorch里面編寫神經(jīng)網(wǎng)絡(luò),,所有的層結(jié)構(gòu)和損失函數(shù)都來自于torch.nn,所有的模型構(gòu)建都是從這個(gè)基類 nn.Module 繼承的,,于是有了下面這個(gè)模板,。
這樣就建立了一個(gè)計(jì)算圖 ,并且這個(gè)結(jié)構(gòu)可以復(fù)用多次,,每次調(diào)用就相當(dāng)于用該計(jì)算圖定義的相同參數(shù)做一次前向傳播,,這得益于 PyTorch 的自動(dòng)求導(dǎo)功能,所以我們不需要自己編寫反向傳播,,而所有的網(wǎng)絡(luò)層都是由 nn 這個(gè)包得到的,,比如線性層nn.Linear,等之后使用的時(shí)候我們可以詳細(xì)地介紹每一種網(wǎng)絡(luò)對應(yīng)的結(jié)構(gòu),,以及如何調(diào)用,。 定義完模型之后 ,我們需要通過nn這個(gè)包來定義損失函數(shù),。 常見的損失函數(shù)都已經(jīng)定義在了nn巾,,比如均方誤差 、多分類的交叉熵,,以及二分類的交叉熵,,等等,調(diào)用這些已經(jīng)定義好的損失函數(shù)也很簡單: criterion = nn.CrossEntropyLoss( ) loss = criterion(output, target) 這樣就能求得我們的輸出和真實(shí)目標(biāo)之間的損失函數(shù)了 常見的神經(jīng)網(wǎng)絡(luò)層:卷積層conv = nn.Conv2d(1, 1, (3, 3), 1, bias=False) 池化層pool = nn.AvgPool2d(2,2) Linear:全連接層linear = nn.Linear(3, 4) BatchNorm:批規(guī)范化層bn = nn.BatchNorm1d(4) Dropout:dropout層dropout = nn.Dropout(0.5)#0.5的概率舍棄 激活函數(shù)relu = nn.ReLU(True) # Embedding層,,有4個(gè)詞,,每個(gè)詞用5維的向量表示 embedding = nn.Embedding(4, 5) 搭建網(wǎng)絡(luò)的兩種方式我們在搭建神經(jīng)網(wǎng)絡(luò)的時(shí)候,可以將多個(gè)神經(jīng)網(wǎng)絡(luò)層組合在一起,,我們可以使用Sequential和ModuleList這兩種方式,。 我們先來看一下Sequential,它我們可以看作是一個(gè)module # Sequential的三種寫法 寫法一:為每一個(gè)神經(jīng)網(wǎng)絡(luò)層添加一個(gè)名字 net1 = nn.Sequential() net1.add_module('conv', nn.Conv2d(3, 3, 3)) net1.add_module('batchnorm', nn.BatchNorm2d(3)) net1.add_module('activation_layer', nn.ReLU()) 因?yàn)橛忻?,所以我們可以根?jù)名字來取出神經(jīng)網(wǎng)絡(luò)的每一層 net1.conv net1.batchnorm 前向傳播out=net1(input) 寫法二: net2 = nn.Sequential( nn.Conv2d(3, 3, 3), nn.BatchNorm2d(3), nn.ReLU() ) 這個(gè)沒有名字,,我們可以通過索引取出Sequential中神經(jīng)網(wǎng)路的每一層 net2[0] 前向傳播out=net2(input) 寫法三:使用OrderedDict將神經(jīng)網(wǎng)絡(luò)層封裝為一個(gè)字典,然后傳遞到Sequential中 from collections import OrderedDict net3= nn.Sequential(OrderedDict([ ('conv1', nn.Conv2d(3, 3, 3)), ('bn1', nn.BatchNorm2d(3)), ('relu1', nn.ReLU()) ])) 可以根據(jù)名字取出神經(jīng)網(wǎng)絡(luò)的每一層 net3.conv1 前向傳播 方式一:output = net3(input) 方式二:output = net3.relu1(net1.batchnorm(net1.conv(input))) ModuleList的使用方式,,注意ModuleList在Module中使用它的時(shí)候(在實(shí)現(xiàn)nn.Module的__init__()方法中使用的時(shí)候),,才能自動(dòng)識別為子module。 class Net4(nn.Module): def __init__(self): super(Net4, self).__init__() self.module_list = nn.ModuleList([nn.Conv2d(3, 3, 3), nn.ReLU()]) def forward(self): model = MyModule() ModuleList其實(shí)就是一個(gè)List,,只不過在Module中它會(huì)自動(dòng)識別為module,,識別為module的好處就是它會(huì)作為整個(gè)module的一個(gè)整體,,在反向傳播中跟新其參數(shù)。 除ModuleList之外還有ParameterList,,其是一個(gè)可以包含多個(gè)parameter的類list對象,。我們?nèi)绻窃趇nit中用到list,我們應(yīng)該用ModuleList或ParameterList,,而不是使用list,。
這個(gè)表示建立一個(gè)全連接層,w和b就是全連接層的權(quán)重參數(shù),,其中w的維度是(輸出,,輸入) nn.Parameter中會(huì)自帶梯度求梯度功能 獲取參數(shù)Net.parameters()表示獲取net的所有參數(shù) List表示轉(zhuǎn)換為列表形式,此時(shí)這個(gè)列表應(yīng)該是[w0,b0,w1,b1] 遍歷所有的模型的參數(shù),,其中name表示模型的參數(shù),,注意這個(gè)名字中沒有net.1,這是因?yàn)閚n.ReLU是模型的第二層,,但是這里并沒有參數(shù),,所以net.0之后沒有net.1,而直接是net.2 Named——children表示獲取net的網(wǎng)絡(luò)的孩子結(jié)點(diǎn) 獲取所有結(jié)點(diǎn),從子結(jié)點(diǎn)開始逐漸到孫子結(jié)點(diǎn) 自定義展開層
|
|