PyTorch学习笔记(1)nn.Sequential、nn.Conv2d、nn.BatchNorm2d、nn.ReLU和nn.MaxPool2d
文章目錄
- 一、nn.Sequential
- 二、nn.Conv2d
- 三、nn.BatchNorm2d
- 四、nn.ReLU
- 五、nn.MaxPool2d
一、nn.Sequential
torch.nn.Sequential是一個(gè)Sequential容器,模塊將按照構(gòu)造函數(shù)中傳遞的順序添加到模塊中。
使用方式:
官方給出案例(上面所提的方式1 和 方式2的列子):
# Sequential使用實(shí)例model = nn.Sequential(nn.Conv2d(1,20,5),nn.ReLU(),nn.Conv2d(20,64,5),nn.ReLU())# Sequential with OrderedDict使用實(shí)例 model = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(1,20,5)),('relu1', nn.ReLU()),('conv2', nn.Conv2d(20,64,5)),('relu2', nn.ReLU())]))以上兩種形式為一致。一種自動(dòng)命名,一種指定名字。
驗(yàn)證:
需要在pytorch環(huán)境下運(yùn)行。
先添加:
打印模型輸出:
print(model) --------------------------------------------------------- Sequential((0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))(1): ReLU()(2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))(3): ReLU() )使用torch.nn.Sequential可以快速的搭建一個(gè)神經(jīng)網(wǎng)絡(luò)
為比較,先用普通方法搭建一個(gè)神經(jīng)網(wǎng)絡(luò)來對(duì)比
class Net(torch.nn.Module):def __init__(self, n_feature, n_hidden, n_output):super(Net, self).__init__()self.hidden = torch.nn.Linear(n_feature, n_hidden)self.predict = torch.nn.Linear(n_hidden, n_output)def forward(self, x):x = F.relu(self.hidden(x))x = self.predict(x)return xnet1 = Net(1, 10, 1)上面class繼承了一個(gè)torch中的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu), 然后對(duì)其進(jìn)行了修改;
接下來我們來使用torch.nn.Sequential來快速搭建一個(gè)神經(jīng)網(wǎng)絡(luò)。
打印輸出上面2個(gè)神經(jīng)網(wǎng)絡(luò)數(shù)據(jù),查看區(qū)別:
print(net1) --------------------------------------------------------- Net ((hidden): Linear (1 -> 10)(predict): Linear (10 -> 1) ) --------------------------------------------------------- print(net2) --------------------------------------------------------- Sequential ((0): Linear (1 -> 10)(1): ReLU ()(2): Linear (10 -> 1) ) ---------------------------------------------------------我們可以發(fā)現(xiàn),使用torch.nn.Sequential會(huì)自動(dòng)加入激勵(lì)函數(shù), 但是 net1 中, 激勵(lì)函數(shù)實(shí)際上是在 forward() 功能中才被調(diào)用的.
torch.nn.Sequential與torch.nn.Module區(qū)別與選擇
- 使用torch.nn.Module,我們可以根據(jù)自己的需求改變傳播過程,如RNN等
- 如果你需要快速構(gòu)建或者不需要過多的過程,直接使用torch.nn.Sequential即可。
- nn.Sequentialt使對(duì)于加入其中的子模塊在forward中可以通過循環(huán)實(shí)現(xiàn)調(diào)用
- Module 里面也可以使用 Sequential,同時(shí) Module 非常靈活
二、nn.Conv2d
源自:https://pytorch.org/docs/1.2.0/nn.html#conv2d
nn.Conv2d是二維卷積方法,相對(duì)應(yīng)的還有一維卷積方法nn.Conv1d,常用于文本數(shù)據(jù)的處理,而nn.Conv2d一般用于二維圖像。
接口定義:
參數(shù)解釋:
- in_channels(int):輸入圖像的channel(通道數(shù)),例如,RGB圖像通道數(shù)為3
- out_channels(int): 輸出圖像(特征層)的channel
- kernel_size(int or tuple):kernel(卷積核)的大小,kennel_size=5,意味著卷積大小(5,5)/5×5,kennel_size=(2,3),意味著卷積大小(2,3)/2×3 ,即非正方形卷積
- stride(int or tuple,optional): 卷積的步長,默認(rèn)為1,stride=2,意味著步長上下左右掃描皆為2, stride=(2,3),左右掃描步長為2、上下為3
- padding(int or tuple,optional):四周pad的大小,默認(rèn)為0,在卷積之前補(bǔ)0,四周都補(bǔ)0,
- dilation(int or tuple,optional): kernel元素間的距離,默認(rèn)為1(dilation翻譯為擴(kuò)張,有時(shí)候也稱為“空洞”1)
- groups(int ,optional):將原始輸入channel劃分成的組數(shù),默認(rèn)為1
- bias(bool,optional):如果是True,則輸出的bias可學(xué),默認(rèn)為True。卷積后是否加偏移量
- padding_mode:默認(rèn)為“zeros”,填充0
channel:通道數(shù)。
一般的RGB圖片,channels 數(shù)量是 3 (紅、綠、藍(lán));而單色/灰度圖片,channels 數(shù)量是 1。
channels 一般分為三種:
dilation:空洞卷積,控制 kernel 點(diǎn)之間的空間距離,實(shí)際在上采樣上有利用(在FCN、U-net等網(wǎng)絡(luò)結(jié)構(gòu)中),看下圖有助于理解
groups:分組卷積
Convolution 層的參數(shù)中有一個(gè)group參數(shù),其意思是將對(duì)應(yīng)的輸入通道與輸出通道數(shù)進(jìn)行分組, 默認(rèn)值為1, 也就是說默認(rèn)輸出輸入的所有通道各為一組。
比如:輸入數(shù)據(jù)大小為90x100x100x32,通道數(shù)32,要經(jīng)過一個(gè)3x3x48的卷積,group默認(rèn)是1,就是全連接的卷積層。
如果group是2,那么對(duì)應(yīng)要將輸入的32個(gè)通道分成2個(gè)16的通道,將輸出的48個(gè)通道分成2個(gè)24的通道。對(duì)輸出的2個(gè)24的通道,第一個(gè)24通道與輸入的第一個(gè)16通道進(jìn)行全卷積,第二個(gè)24通道與輸入的第二個(gè)16通道進(jìn)行全卷積。
極端情況下,輸入輸出通道數(shù)相同,比如為24,group大小也為24,那么每個(gè)輸出卷積核,只與輸入的對(duì)應(yīng)的通道進(jìn)行卷積。
三、nn.BatchNorm2d
源自:https://pytorch.org/docs/1.2.0/nn.html#batchnorm2d
BatchNorm(批規(guī)范化)主要是為了加速神經(jīng)網(wǎng)絡(luò)的收斂過程以及提高訓(xùn)練過程中的穩(wěn)定性。通常用于解決多層神經(jīng)網(wǎng)絡(luò)中間層的協(xié)方差偏移(Internal Covariate Shift)問題,類似于網(wǎng)絡(luò)輸入進(jìn)行零均值化和方差歸一化的操作,不過是在中間層的輸入中操作而已。使一批(Batch)feature map滿足均值為0,方差為1的分布規(guī)律。這樣不僅數(shù)據(jù)分布一致,而且避免發(fā)生梯度消失。
接口定義:
參數(shù)解釋:
- num_features: 一般輸入?yún)?shù)為batch_size num_features (height*width),即為其中特征的數(shù)量,為輸入BN層的通道數(shù);
- eps: 分母中添加的一個(gè)值,目的是為了計(jì)算的穩(wěn)定性,默認(rèn)為:1e-05,避免分母為0;為公式中的ε\ ε\,?ε
- momentum:動(dòng)態(tài)均值和動(dòng)態(tài)方差所使用的動(dòng)量。默認(rèn)為0.1。一個(gè)用于運(yùn)行過程中均值和方差的一個(gè)估計(jì)參數(shù)(我的理解是一個(gè)穩(wěn)定系數(shù),類似于SGD中的momentum的系數(shù));
- affine: 當(dāng)設(shè)為true時(shí),會(huì)給定可以學(xué)習(xí)的系數(shù)矩陣γ\ γ\,?γ和β\ β\,?β。布爾值,當(dāng)設(shè)為true,給該層添加可學(xué)習(xí)的仿射變換參數(shù)。
- track_running_stats:布爾值,當(dāng)設(shè)為true,記錄訓(xùn)練過程中的均值和方差;
公式:
y=γ×(x?E[x]Var[x]+ε)+β\ y=γ×({x-E[x] \over \sqrt{Var[x]+ε} \quad })+β\, ?y=γ×(Var[x]+ε?x?E[x]?)+β
(γ\ γ\,?γ 和β\ β\,?β在反向傳播過程中訓(xùn)練得到,是對(duì)像素在BN的基礎(chǔ)上進(jìn)行的調(diào)整,具體數(shù)值是模型學(xué)習(xí)出來的,初始化γ=1\ γ=1\,?γ=1用來調(diào)整方差, β=0\ β=0\,?β=0用來調(diào)整均值。
用于抵消部分標(biāo)準(zhǔn)化帶來的影響,因?yàn)橛袝r(shí)候可能標(biāo)準(zhǔn)化了不好,這個(gè)時(shí)候這兩個(gè)變量就有足夠的彈性來學(xué)習(xí)修整這種標(biāo)準(zhǔn)化了。)
在訓(xùn)練時(shí),該層計(jì)算每次輸入的均值和方差,進(jìn)行移動(dòng)平均。移動(dòng)平均momentum 默認(rèn)的動(dòng)量值為0.1
在驗(yàn)證時(shí),訓(xùn)練求得的均值和方差將用于標(biāo)準(zhǔn)化驗(yàn)證數(shù)據(jù)。
參數(shù)詳解:
在BN操作中,最重要的無非是這四個(gè)式子:
- 輸入:B=(x1,x2,...,xm)\ Β = (x_1,x_2,...,x_m )\,?B=(x1?,x2?,...,xm?),為m個(gè)樣本組成的一個(gè)batch數(shù)據(jù)
- 輸出:需要學(xué)習(xí)到的是γ\ γ\,?γ和β\ β\,?β,在框架中一般表述成weight和bias
更新過程:
注意到這里的最后一步也稱之為仿射(affine),引入這一步的目的主要是設(shè)計(jì)一個(gè)通道,使得輸出output至少能夠回到輸入input的狀態(tài)(當(dāng) γ=1\ γ=1\,?γ=1, β=0\ β=0\,?β=0時(shí))使得BN的引入至少不至于降低模型的表現(xiàn),這是深度網(wǎng)絡(luò)設(shè)計(jì)的一個(gè)套路。
一般來說pytorch中的模型都是繼承nn.Module類的,都有一個(gè)屬性trainning指定是否是訓(xùn)練狀態(tài),訓(xùn)練狀態(tài)與否將會(huì)影響到某些層的參數(shù)是否是固定的,比如BN層或者Dropout層。通常用model.train()指定當(dāng)前模型model為訓(xùn)練狀態(tài),model.eval()指定當(dāng)前模型為測試/驗(yàn)證狀態(tài)。
同時(shí),BN的API中有幾個(gè)參數(shù)需要比較關(guān)心的,一個(gè)是affine指定是否需要仿射,還有個(gè)是track_running_stats指定是否跟蹤當(dāng)前batch的統(tǒng)計(jì)特性。容易出現(xiàn)問題也正好是這三個(gè)參數(shù):trainning,affine,track_running_stats。
- 其中的affine指定是否需要仿射,也就是是否需要上面算式的第四個(gè),如果affine=False,則 γ=1\ γ=1\,?γ=1, β=0\ β=0\,?β=0,并且不能學(xué)習(xí)被更新。一般都會(huì)設(shè)置成affine=True
- trainning和track_running_stats,track_running_stats=True表示跟蹤整個(gè)訓(xùn)練過程中的batch的統(tǒng)計(jì)特性,得到方差和均值,而不只是僅僅依賴與當(dāng)前輸入的batch的統(tǒng)計(jì)特性。相反的,如果track_running_stats=False那么就只是計(jì)算當(dāng)前輸入的batch的統(tǒng)計(jì)特性中的均值和方差了。當(dāng)在推理階段的時(shí)候,如果track_running_stats=False,此時(shí)如果batch_size比較小,那么其統(tǒng)計(jì)特性就會(huì)和全局統(tǒng)計(jì)特性有著較大偏差,可能導(dǎo)致糟糕的效果。
神經(jīng)網(wǎng)絡(luò)中有各種歸一化算法:Batch Normalization (BN)、Layer Normalization (LN)、Instance Normalization (IN)、Group Normalization (GN)。
從公式看它們都差不多:無非是減去均值,除以標(biāo)準(zhǔn)差,再施以線性映射。
y=γ(x?μ(x)σ(x))+β\ y=γ({x-μ(x) \overσ (x)})+β\, ?y=γ(σ(x)x?μ(x)?)+β這些歸一化算法的主要區(qū)別在于操作的 feature map 維度不同。
- BatchNorm(BN):batch方向做歸一化,算NHW的均值,對(duì)小batchsize效果不好;BN主要缺點(diǎn)是對(duì)batchsize的大小比較敏感,由于每次計(jì)算均值和方差是在一個(gè)batch上,所以如果batchsize太小,則計(jì)算的均值、方差不足以代表整個(gè)數(shù)據(jù)分布
- LayerNorm (LN):channel方向做歸一化,算CHW的均值,主要對(duì)RNN作用明顯;
- InstanceNorm(IN):一個(gè)channel內(nèi)做歸一化,算H*W的均值,用在風(fēng)格化遷移;因?yàn)樵趫D像風(fēng)格化中,生成結(jié)果主要依賴于某個(gè)圖像實(shí)例,所以對(duì)整個(gè)batch歸一化不適合圖像風(fēng)格化中,因而對(duì)HW做歸一化??梢约铀倌P褪諗?#xff0c;并且保持每個(gè)圖像實(shí)例之間的獨(dú)立。
- GroupNorm(GN):將channel方向分group,然后每個(gè)group內(nèi)做歸一化,算(C//G)HW的均值;這樣與batchsize無關(guān),不受其約束。
- SwitchableNorm是將BN、LN、IN結(jié)合,賦予權(quán)重,讓網(wǎng)絡(luò)自己去學(xué)習(xí)歸一化層應(yīng)該使用什么方法。
Batch Normalization (BN) 是最早出現(xiàn)的,也通常是效果最好的歸一化方式。feature map:x∈RN×C×H×W.\ x∈R^{N×C×H×W} \,.?x∈RN×C×H×W.包含 N 個(gè)樣本,每個(gè)樣本通道數(shù)為 C,高為 H,寬為 W。對(duì)其求均值和方差時(shí),將在 N、H、W上操作,而保留通道 C 的維度。
具體來說,就是把第1個(gè)樣本的第1個(gè)通道,加上第2個(gè)樣本第1個(gè)通道 … 加上第 N 個(gè)樣本第1個(gè)通道,求平均,得到通道 1 的均值(注意是除以 N×H×W 而不是單純除以 N,最后得到的是一個(gè)代表這個(gè) batch 第1個(gè)通道平均值的數(shù)字,而不是一個(gè) H×W 的矩陣)。求通道 1 的方差也是同理。對(duì)所有通道都施加一遍這個(gè)操作,就得到了所有通道的均值和方差。具體公式為:
這里有個(gè)特別好的比喻,便于理解:
如果把x∈RN×C×H×W.\ x∈R^{N×C×H×W} \,.?x∈RN×C×H×W.類比為一摞書,這摞書總共有 N 本,每本有 C 頁,每頁有 H 行,每行 W 個(gè)字符。BN 求均值時(shí),相當(dāng)于把這些書按頁碼一一對(duì)應(yīng)地加起來(例如第1本書第36頁,第2本書第36頁…),再除以每個(gè)頁碼下的字符總數(shù):N×H×W.\ N×H×W \,.?N×H×W.,因此可以把 BN 看成求“平均書”的操作(注意這個(gè)“平均書”每頁只有一個(gè)字),求標(biāo)準(zhǔn)差時(shí)也是同理。
詳細(xì)區(qū)別和參數(shù)細(xì)節(jié)建議參考:知乎,CSDN。
四、nn.ReLU
源自:https://pytorch.org/docs/1.2.0/nn.html#relu
nn.ReLU() 是封裝好的類,繼承nn.Module
接口定義:
參數(shù)定義:
inplace: can optionally do the operation in=plase. Default: False
inplace:默認(rèn)為false(選擇是否進(jìn)行覆蓋運(yùn)算,意思是:是否將得到的值計(jì)算得到的值覆蓋之前的值)
inplace=True,會(huì)改變輸入數(shù)據(jù),inplace=False,不會(huì)改變輸入數(shù)據(jù),只會(huì)產(chǎn)生新的輸出
注:產(chǎn)生的計(jì)算結(jié)果不會(huì)有影響。利用in-place計(jì)算可以節(jié)省內(nèi)(顯)存,同時(shí)還可以省去反復(fù)申請(qǐng)和釋放內(nèi)存的時(shí)間。但是會(huì)對(duì)原變量覆蓋,只要不帶來錯(cuò)誤就用。
對(duì)于ReLU非線性激勵(lì)函數(shù),其公式為:
ReLU(x)=max(0,x)\ ReLU(x)=max(0, x)\,?ReLU(x)=max(0,x)
nn.ReLU() 與 F.relu()的區(qū)別
nn.ReLU() :
F.relu():
import torch.nn.functional as F ''' out = F.relu(input)其實(shí)這兩種方法都是使用relu激活,只是使用的場景不一樣,F.relu()是函數(shù)調(diào)用,一般使用在foreward函數(shù)里。而nn.ReLU()是模塊調(diào)用,一般在定義網(wǎng)絡(luò)層的時(shí)候使用,作為一個(gè)層結(jié)構(gòu),必須添加到nn.Module容器中才能使用。
1.為什么引入非線性激勵(lì)函數(shù)?
如果不適用激勵(lì)函數(shù),那么在這種情況下每一層的輸出都是上層輸入的線性函數(shù),很容易驗(yàn)證,無論你神經(jīng)網(wǎng)絡(luò)有多少層,輸出都是輸入的線性組合,與沒有隱藏層效果相當(dāng),這種情況就是最原始的感知機(jī)(perceptron)了。正因?yàn)樯厦娴脑?#xff0c;我們決定引入非線性函數(shù)作為激勵(lì)函數(shù),這樣深層神經(jīng)網(wǎng)絡(luò)就有意義了,不再是輸入的線性組合,可以逼近任意函數(shù),最早的想法是用sigmoid函數(shù)或者tanh函數(shù),輸出有界,很容易充當(dāng)下一層的輸入
2.為什么引入Relu?
其實(shí),relu函數(shù)的作用就是增加了神經(jīng)網(wǎng)絡(luò)各層之間的非線性關(guān)系,否則,如果沒有激活函數(shù),層與層之間是簡單的線性關(guān)系,每層都相當(dāng)于矩陣相乘,這樣怎么能夠完成我們需要神經(jīng)網(wǎng)絡(luò)完成的復(fù)雜任務(wù),
五、nn.MaxPool2d
源自:https://pytorch.org/docs/1.2.0/nn.html#torch.nn.MaxPool2d
接口定義:
class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)參數(shù)定義:
- kernel_size(int or tuple):取最大值(max pooling)的窗口大小,如果是一個(gè)值單int,高度和寬度都使用相同的值;如果是tuple兩個(gè)整數(shù),第一個(gè)是height ,第二個(gè)是height 。(最大池化的方法就是取這個(gè)窗口覆蓋元素中的最大值。)
- stride(int or tuple, optional):窗口移動(dòng)的步長。默認(rèn)值為kernel_size(上一個(gè)參數(shù)我們確定了滑動(dòng)窗口的大小,現(xiàn)在我們來確定這個(gè)窗口如何進(jìn)行滑動(dòng)。如果不指定這個(gè)參數(shù),那么默認(rèn)步長跟最大池化窗口大小一致。如果指定了參數(shù),那么將按照我們指定的參數(shù)進(jìn)行滑動(dòng)。)
- padding (int or tuple, optional):輸入的每一條邊補(bǔ)充0的層數(shù)
- dilation (int or tuple, optional):控制窗口中元素步長的參數(shù)
- return_indices:如果為True,會(huì)返回輸出最大值的位置索引,對(duì)于上采樣(torch.nn.MaxUnpool2d)操作會(huì)有幫助。
- ceil_mode: 如果等于True,計(jì)算輸出信號(hào)大小的時(shí)候,會(huì)使用向上取整,代替默認(rèn)的向下取整的操作。(關(guān)于 ceil_mode 的詳解:建議參考CSDN)
如果padding 不是0,會(huì)在輸入的每一邊添加相應(yīng)數(shù)目0,如padding=1,則在每一邊分別補(bǔ)0,其實(shí)最后的結(jié)果補(bǔ)出來是bias
最大池化的方法示意圖:
總結(jié)
以上是生活随笔為你收集整理的PyTorch学习笔记(1)nn.Sequential、nn.Conv2d、nn.BatchNorm2d、nn.ReLU和nn.MaxPool2d的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XTU OJ 1397 Patchoul
- 下一篇: 我们能做出量子计算机却至今摸不透量子力学