Pytorch中關于nn.Conv2d()參數(shù)的使用
關于nn.Conv2d()參數(shù)的使用
nn.Conv2d()的使用、形參與隱藏的權重參數(shù)
二維卷積應該是最常用的卷積方式了,在Pytorch的nn模塊中,封裝了nn.Conv2d()類作為二維卷積的實現(xiàn)。
使用方法和普通的類一樣,先實例化再使用。
下面是一個只有一層二維卷積的神經(jīng)網(wǎng)絡,作為nn.Conv2d()方法的使用簡介:
class Net(nn.Module):
def __init__(self):
nn.Module.__init__(self)
self.conv2d = nn.Conv2d(in_channels=3,out_channels=64,kernel_size=4,stride=2,padding=1)
def forward(self, x):
print(x.requires_grad)
x = self.conv2d(x)
return x
print(net.conv2d.weight)
print(net.conv2d.bias)它的形參由Pytorch手冊可以查得,前三個參數(shù)是必須手動提供的,后面的有默認值。
接下來將一一介紹

在Pytorch的nn模塊中,它是不需要你手動定義網(wǎng)絡層的權重和偏置的,這也是體現(xiàn)Pytorch使用簡便的地方。
當然,如果有小伙伴適應不了這種不定義權重和偏置的方法,Pytorch還提供了nn.Functional函數(shù)式編程的方法,其中的F.conv2d()就和Tensorflow一樣,要先定義好卷積核的權重和偏置,作為F.conv2d()的形參之一。
回到nn.Conv2d上來,我們可以通過實例名.weight和實例名.bias來查看卷積層的權重和偏置,如上圖所示。
in_channels
這個很好理解,就是輸入的四維張量[N, C, H, W]中的C了,即輸入張量的channels數(shù)。
這個形參是確定權重等可學習參數(shù)的shape所必需的。
out_channels
也很好理解,即期望的四維輸出張量的channels數(shù),不再多說。
kernel_size
卷積核的大小,一般我們會使用5x5、3x3這種左右兩個數(shù)相同的卷積核,因此這種情況只需要寫kernel_size = 5這樣的就行了。
如果左右兩個數(shù)不同,比如3x5的卷積核,那么寫作kernel_size = (3, 5),注意需要寫一個tuple,而不能寫一個列表(list)。
stride = 1
卷積核在圖像窗口上每次平移的間隔,即所謂的步長。這個概念和Tensorflow等其他框架沒什么區(qū)別,不再多言。
padding = 0
Pytorch與Tensorflow在卷積層實現(xiàn)上最大的差別就在于padding上。
Padding即所謂的圖像填充,后面的int型常數(shù)代表填充的多少(行數(shù)、列數(shù)),默認為0。需要注意的是這里的填充包括圖像的上下左右,以padding = 1為例,若原始圖像大小為32x32,那么padding后的圖像大小就變成了34x34,而不是33x33。
Pytorch不同于Tensorflow的地方在于,Tensorflow提供的是padding的模式,比如same、valid,且不同模式對應了不同的輸出圖像尺寸計算公式。而Pytorch則需要手動輸入padding的數(shù)量,當然,Pytorch這種實現(xiàn)好處就在于輸出圖像尺寸計算公式是唯一的,即

當然,上面的公式過于復雜難以記憶。大多數(shù)情況下的kernel_size、padding左右兩數(shù)均相同,且不采用空洞卷積(dilation默認為1),因此只需要記 O = (I - K + 2P)/ S +1這種在深度學習課程里學過的公式就好了。
dilation = 1
這個參數(shù)決定了是否采用空洞卷積,默認為1(不采用)。從中文上來講,這個參數(shù)的意義從卷積核上的一個參數(shù)到另一個參數(shù)需要走過的距離,那當然默認是1了,畢竟不可能兩個不同的參數(shù)占同一個地方吧(為0)。
groups = 1
決定了是否采用分組卷積,現(xiàn)在用的比較多的是groups = in_channel。當groups = in_channel時,是在做的depth-wise conv的,具體思想可以參考MobileNet那篇論文。
bias = True
即是否要添加偏置參數(shù)作為可學習參數(shù)的一個,默認為True。
padding_mode = ‘zeros’
即padding的模式,默認采用零填充。
對nn.Conv2d的group參數(shù)的理解
nn.Conv2d的group參數(shù)
卷積,想必沖浪在一線的大家伙們都已經(jīng)耳熟能詳了,自從深度學習火爆全網(wǎng)之后,大家都在學習一線知識,那么今天想來講講關于Pytorch這個深度學習框架下的nn.Conv2d的group這個參數(shù)。
group這個參數(shù)是為分組卷積而創(chuàng)造出來的,分組卷積的好處呢?就是減少參數(shù)量,還能夠得到更多的feature map。
這篇文章具體是想探討一下分組卷積和普通的卷積之后的結果是否相同呢?
首先先來說一下答案:當參與卷積的卷積核是一樣的時候,結果是一樣,否則則是不一樣的。
誒誒誒,先別著急噴,這里我想表達的意思,您可能還不夠理解,請接著往下看吧。
關于group這個參數(shù),官網(wǎng)給的解釋是這樣子的。

大意是什么呢?大概是當groups=1的時候,假設此時 輸入的通道數(shù)為n,輸出的通道數(shù)為m,那么理解為把輸入的通道分成1組(不分組),每一個輸出通道需要在所有的輸入通道上做卷積,也就是一種參數(shù)共享的局部全連接。
如果把groups改成2,可以理解為把 輸入的通道分成兩組,此時每一個輸出通道只需要在其中一組上做卷積。
如果groups=in_channels,也就是把 輸入的通道分成in_channels組(每一組也就一個通道),此時每一個輸出通道只需要在其中一個輸入通道上做卷積。
不太理解吧?
假如group=2的話,就是把輸入通道一分為二,比如我現(xiàn)在的輸入格式為 2 ∗ 3 ∗ 3 2*3*3 2∗3∗3的話,現(xiàn)在就是將輸入改為 1 ∗ 3 ∗ 3 1*3*3 1∗3∗3,同樣的我對應的卷積核也會變?yōu)樵瓉硗ǖ赖囊话搿?/p>
那分組卷積和普通卷積的結果還會不會相同呢?
看下面的代碼吧。
import torch
import torch.nn as nn
from torch.autograd import Variable
x=torch.FloatTensor([[1,2,3],[4,5,6],[7,8,9],
[1,2,3],[4,5,6],[7,8,9]]).view(1,2,3,3)
//輸入X是通道數(shù)為2的3*3矩陣。
x = Variable(x)
conv1 = nn.Conv2d(in_channels=2,
out_channels=2,
kernel_size=3,
stride=1,
padding=0,
groups=1,
bias=False) //conv1普通卷積
conv2 = nn.Conv2d(in_channels=2,
out_channels=2,
kernel_size=3,
stride=1,
padding=0,
groups=2,
bias=False) //conv2是分組卷積
print(conv1.weight.data.size())
print(conv2.weight.data.size())
conv1.weight.data = torch.FloatTensor([[[[1,2,3],[4,5,6],[7,8,9]],
[[9,8,7],[6,5,4],[3,2,1]]],
[[[1,2,3],[4,5,6],[7,8,9]],
[[9,8,7],[6,5,4],[3,2,1]]]])
conv2.weight.data = torch.FloatTensor([[[[1,2,3],[4,5,6],[7,8,9]]],
[[[9,8,7],[6,5,4],[3,2,1]]]] )
print(conv1.weight.data)
print(conv2.weight.data)
output=conv1(x)
print(output)
output=conv2(x)
print(output)結果是:

可以從前兩行,在conv的配置相同的情況下,選擇分組卷積的話,他們的卷積核的大小就已經(jīng)不一樣了。
一個是torch.Size([2, 2, 3, 3])
分組卷積的則是torch.Size([2, 1, 3, 3])
可以明顯的看到分組卷積的通道更少,從這里就能直觀的看出,分組卷積它是沿著通道數(shù)分割成n份。
可以看到卷積核就已經(jīng)發(fā)生了明顯的變化,所以最終卷積的結果肯定是不同的,所以在用同一個卷積核的情況下,普通卷積的結果肯定是和分組卷積的結果是不同的。(因為分組卷積的卷積核只是普通卷積的卷積核的一部分。)
(所以一般情況是不同的,并且對應的情況一般是,這分成的n個組卷積之后的結果 的 對應點相加,才等于普通卷積卷積出的結果。)
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
python服務器與android客戶端socket通信實例
這篇文章主要介紹了python服務器與android客戶端socket通信的實現(xiàn)方法,實例形式詳細講述了Python的服務器端實現(xiàn)原理與方法,以及對應的Android客戶端實現(xiàn)方法,需要的朋友可以參考下2014-11-11
Python實現(xiàn)過濾單個Android程序日志腳本分享
這篇文章主要介紹了Python實現(xiàn)過濾單個Android程序日志腳本分享,本文講解了原理、實現(xiàn)代碼、使用方法、最新代碼等內容,需要的朋友可以參考下2015-01-01
基于python+opencv調用電腦攝像頭實現(xiàn)實時人臉眼睛以及微笑識別
這篇文章主要為大家詳細介紹了基于python+opencv調用電腦攝像頭實現(xiàn)實時人臉眼睛以及微笑識別,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
python中用shutil.move移動文件或目錄的方法實例
在python操作中大家對os,shutil,sys,等通用庫一定不陌生,下面這篇文章主要給大家介紹了關于python中用shutil.move移動文件或目錄的相關資料,需要的朋友可以參考下2022-12-12
python 自動化將markdown文件轉成html文件的方法
這篇文章主要介紹了python 自動化將markdown文件轉成html文件的方法的相關資料,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下2016-09-09
vscode寫python時的代碼錯誤提醒和自動格式化的方法
這篇文章主要介紹了vscode寫python時的代碼錯誤提醒和自動格式化的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05

