Pytorch中關(guān)于nn.Conv2d()參數(shù)的使用
關(guān)于nn.Conv2d()參數(shù)的使用
nn.Conv2d()的使用、形參與隱藏的權(quán)重參數(shù)
二維卷積應(yīng)該是最常用的卷積方式了,在Pytorch的nn模塊中,封裝了nn.Conv2d()類作為二維卷積的實現(xiàn)。
使用方法和普通的類一樣,先實例化再使用。
下面是一個只有一層二維卷積的神經(jīng)網(wǎng)絡(luò),作為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ù)是必須手動提供的,后面的有默認(rèn)值。
接下來將一一介紹

在Pytorch的nn模塊中,它是不需要你手動定義網(wǎng)絡(luò)層的權(quán)重和偏置的,這也是體現(xiàn)Pytorch使用簡便的地方。
當(dāng)然,如果有小伙伴適應(yīng)不了這種不定義權(quán)重和偏置的方法,Pytorch還提供了nn.Functional函數(shù)式編程的方法,其中的F.conv2d()就和Tensorflow一樣,要先定義好卷積核的權(quán)重和偏置,作為F.conv2d()的形參之一。
回到nn.Conv2d上來,我們可以通過實例名.weight和實例名.bias來查看卷積層的權(quán)重和偏置,如上圖所示。
in_channels
這個很好理解,就是輸入的四維張量[N, C, H, W]中的C了,即輸入張量的channels數(shù)。
這個形參是確定權(quán)重等可學(xué)習(xí)參數(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ù)),默認(rèn)為0。需要注意的是這里的填充包括圖像的上下左右,以padding = 1為例,若原始圖像大小為32x32,那么padding后的圖像大小就變成了34x34,而不是33x33。
Pytorch不同于Tensorflow的地方在于,Tensorflow提供的是padding的模式,比如same、valid,且不同模式對應(yīng)了不同的輸出圖像尺寸計算公式。而Pytorch則需要手動輸入padding的數(shù)量,當(dāng)然,Pytorch這種實現(xiàn)好處就在于輸出圖像尺寸計算公式是唯一的,即

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

大意是什么呢?大概是當(dāng)groups=1的時候,假設(shè)此時 輸入的通道數(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īng)的卷積核也會變?yōu)樵瓉硗ǖ赖囊话搿?/p>
那分組卷積和普通卷積的結(jié)果還會不會相同呢?
看下面的代碼吧。
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)結(jié)果是:

可以從前兩行,在conv的配置相同的情況下,選擇分組卷積的話,他們的卷積核的大小就已經(jīng)不一樣了。
一個是torch.Size([2, 2, 3, 3])
分組卷積的則是torch.Size([2, 1, 3, 3])
可以明顯的看到分組卷積的通道更少,從這里就能直觀的看出,分組卷積它是沿著通道數(shù)分割成n份。
可以看到卷積核就已經(jīng)發(fā)生了明顯的變化,所以最終卷積的結(jié)果肯定是不同的,所以在用同一個卷積核的情況下,普通卷積的結(jié)果肯定是和分組卷積的結(jié)果是不同的。(因為分組卷積的卷積核只是普通卷積的卷積核的一部分。)
(所以一般情況是不同的,并且對應(yīng)的情況一般是,這分成的n個組卷積之后的結(jié)果 的 對應(yīng)點相加,才等于普通卷積卷積出的結(jié)果。)
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python開發(fā)之快速搭建自動回復(fù)微信公眾號功能
這篇文章主要介紹了Python開發(fā)之快速搭建自動回復(fù)微信公眾號功能的相關(guān)資料,需要的朋友可以參考下2016-04-04
python執(zhí)行scp命令拷貝文件及文件夾到遠(yuǎn)程主機的目錄方法
今天小編就為大家分享一篇python執(zhí)行scp命令拷貝文件及文件夾到遠(yuǎn)程主機的目錄方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python模塊psycopg2連接postgresql的實現(xiàn)
本文主要介紹了Python模塊psycopg2連接postgresql的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
python抓取網(wǎng)頁時字符集轉(zhuǎn)換問題處理方案分享
python學(xué)習(xí)過程中發(fā)現(xiàn)英文不好學(xué)起來挺困難的,其中小弟就遇到一個十分蛋疼的問題,百度了半天就沒找到解決辦法~囧~摸索了半天自己解決了,記錄下來與君共勉。2014-06-06

