Pytorch中關(guān)于nn.Conv2d()參數(shù)的使用
關(guān)于nn.Conv2d()參數(shù)的使用
nn.Conv2d()的使用、形參與隱藏的權(quán)重參數(shù)
二維卷積應(yīng)該是最常用的卷積方式了,在Pytorch的nn模塊中,封裝了nn.Conv2d()類作為二維卷積的實(shí)現(xiàn)。
使用方法和普通的類一樣,先實(shí)例化再使用。
下面是一個(gè)只有一層二維卷積的神經(jīng)網(wǎng)絡(luò),作為nn.Conv2d()方法的使用簡(jiǎn)介:
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手冊(cè)可以查得,前三個(gè)參數(shù)是必須手動(dòng)提供的,后面的有默認(rèn)值。
接下來將一一介紹
在Pytorch的nn模塊中,它是不需要你手動(dòng)定義網(wǎng)絡(luò)層的權(quán)重和偏置的,這也是體現(xiàn)Pytorch使用簡(jiǎn)便的地方。
當(dāng)然,如果有小伙伴適應(yīng)不了這種不定義權(quán)重和偏置的方法,Pytorch還提供了nn.Functional函數(shù)式編程的方法,其中的F.conv2d()就和Tensorflow一樣,要先定義好卷積核的權(quán)重和偏置,作為F.conv2d()的形參之一。
回到nn.Conv2d上來,我們可以通過實(shí)例名.weight和實(shí)例名.bias來查看卷積層的權(quán)重和偏置,如上圖所示。
in_channels
這個(gè)很好理解,就是輸入的四維張量[N, C, H, W]中的C了,即輸入張量的channels數(shù)。
這個(gè)形參是確定權(quán)重等可學(xué)習(xí)參數(shù)的shape所必需的。
out_channels
也很好理解,即期望的四維輸出張量的channels數(shù),不再多說。
kernel_size
卷積核的大小,一般我們會(huì)使用5x5、3x3這種左右兩個(gè)數(shù)相同的卷積核,因此這種情況只需要寫kernel_size = 5這樣的就行了。
如果左右兩個(gè)數(shù)不同,比如3x5的卷積核,那么寫作kernel_size = (3, 5),注意需要寫一個(gè)tuple,而不能寫一個(gè)列表(list)。
stride = 1
卷積核在圖像窗口上每次平移的間隔,即所謂的步長(zhǎng)。這個(gè)概念和Tensorflow等其他框架沒什么區(qū)別,不再多言。
padding = 0
Pytorch與Tensorflow在卷積層實(shí)現(xiàn)上最大的差別就在于padding上。
Padding即所謂的圖像填充,后面的int型常數(shù)代表填充的多少(行數(shù)、列數(shù)),默認(rèn)為0。需要注意的是這里的填充包括圖像的上下左右,以padding = 1為例,若原始圖像大小為32x32,那么padding后的圖像大小就變成了34x34,而不是33x33。
Pytorch不同于Tensorflow的地方在于,Tensorflow提供的是padding的模式,比如same、valid,且不同模式對(duì)應(yīng)了不同的輸出圖像尺寸計(jì)算公式。而Pytorch則需要手動(dòng)輸入padding的數(shù)量,當(dāng)然,Pytorch這種實(shí)現(xiàn)好處就在于輸出圖像尺寸計(jì)算公式是唯一的,即
當(dāng)然,上面的公式過于復(fù)雜難以記憶。大多數(shù)情況下的kernel_size、padding左右兩數(shù)均相同,且不采用空洞卷積(dilation默認(rèn)為1),因此只需要記 O = (I - K + 2P)/ S +1這種在深度學(xué)習(xí)課程里學(xué)過的公式就好了。
dilation = 1
這個(gè)參數(shù)決定了是否采用空洞卷積,默認(rèn)為1(不采用)。從中文上來講,這個(gè)參數(shù)的意義從卷積核上的一個(gè)參數(shù)到另一個(gè)參數(shù)需要走過的距離,那當(dāng)然默認(rèn)是1了,畢竟不可能兩個(gè)不同的參數(shù)占同一個(gè)地方吧(為0)。
groups = 1
決定了是否采用分組卷積,現(xiàn)在用的比較多的是groups = in_channel。當(dāng)groups = in_channel時(shí),是在做的depth-wise conv的,具體思想可以參考MobileNet那篇論文。
bias = True
即是否要添加偏置參數(shù)作為可學(xué)習(xí)參數(shù)的一個(gè),默認(rèn)為True。
padding_mode = ‘zeros’
即padding的模式,默認(rèn)采用零填充。
對(duì)nn.Conv2d的group參數(shù)的理解
nn.Conv2d的group參數(shù)
卷積,想必沖浪在一線的大家伙們都已經(jīng)耳熟能詳了,自從深度學(xué)習(xí)火爆全網(wǎng)之后,大家都在學(xué)習(xí)一線知識(shí),那么今天想來講講關(guān)于Pytorch這個(gè)深度學(xué)習(xí)框架下的nn.Conv2d的group這個(gè)參數(shù)。
group這個(gè)參數(shù)是為分組卷積而創(chuàng)造出來的,分組卷積的好處呢?就是減少參數(shù)量,還能夠得到更多的feature map。
這篇文章具體是想探討一下分組卷積和普通的卷積之后的結(jié)果是否相同呢?
首先先來說一下答案:當(dāng)參與卷積的卷積核是一樣的時(shí)候,結(jié)果是一樣,否則則是不一樣的。
誒誒誒,先別著急噴,這里我想表達(dá)的意思,您可能還不夠理解,請(qǐng)接著往下看吧。
關(guān)于group這個(gè)參數(shù),官網(wǎng)給的解釋是這樣子的。
大意是什么呢?大概是當(dāng)groups=1的時(shí)候,假設(shè)此時(shí) 輸入的通道數(shù)為n,輸出的通道數(shù)為m,那么理解為把輸入的通道分成1組(不分組),每一個(gè)輸出通道需要在所有的輸入通道上做卷積,也就是一種參數(shù)共享的局部全連接。
如果把groups改成2,可以理解為把 輸入的通道分成兩組,此時(shí)每一個(gè)輸出通道只需要在其中一組上做卷積。
如果groups=in_channels,也就是把 輸入的通道分成in_channels組(每一組也就一個(gè)通道),此時(shí)每一個(gè)輸出通道只需要在其中一個(gè)輸入通道上做卷積。
不太理解吧?
假如group=2的話,就是把輸入通道一分為二,比如我現(xiàn)在的輸入格式為 2 ∗ 3 ∗ 3 2*3*3 2∗3∗3的話,現(xiàn)在就是將輸入改為 1 ∗ 3 ∗ 3 1*3*3 1∗3∗3,同樣的我對(duì)應(yīng)的卷積核也會(huì)變?yōu)樵瓉硗ǖ赖囊话搿?/p>
那分組卷積和普通卷積的結(jié)果還會(huì)不會(huì)相同呢?
看下面的代碼吧。
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)不一樣了。
一個(gè)是torch.Size([2, 2, 3, 3])
分組卷積的則是torch.Size([2, 1, 3, 3])
可以明顯的看到分組卷積的通道更少,從這里就能直觀的看出,分組卷積它是沿著通道數(shù)分割成n份。
可以看到卷積核就已經(jīng)發(fā)生了明顯的變化,所以最終卷積的結(jié)果肯定是不同的,所以在用同一個(gè)卷積核的情況下,普通卷積的結(jié)果肯定是和分組卷積的結(jié)果是不同的。(因?yàn)榉纸M卷積的卷積核只是普通卷積的卷積核的一部分。)
(所以一般情況是不同的,并且對(duì)應(yīng)的情況一般是,這分成的n個(gè)組卷積之后的結(jié)果 的 對(duì)應(yīng)點(diǎn)相加,才等于普通卷積卷積出的結(jié)果。)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python開發(fā)之快速搭建自動(dòng)回復(fù)微信公眾號(hào)功能
這篇文章主要介紹了Python開發(fā)之快速搭建自動(dòng)回復(fù)微信公眾號(hào)功能的相關(guān)資料,需要的朋友可以參考下2016-04-04python執(zhí)行scp命令拷貝文件及文件夾到遠(yuǎn)程主機(jī)的目錄方法
今天小編就為大家分享一篇python執(zhí)行scp命令拷貝文件及文件夾到遠(yuǎn)程主機(jī)的目錄方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07對(duì)python修改xml文件的節(jié)點(diǎn)值方法詳解
今天小編就為大家分享一篇對(duì)python修改xml文件的節(jié)點(diǎn)值方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12Python模塊psycopg2連接postgresql的實(shí)現(xiàn)
本文主要介紹了Python模塊psycopg2連接postgresql的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07超級(jí)實(shí)用的8個(gè)Python列表技巧
這篇文章主要介紹了實(shí)用的8個(gè)Python列表技巧,幫助大家更好的理解和學(xué)習(xí)python列表的知識(shí),感興趣的朋友可以了解下2020-08-08python抓取網(wǎng)頁時(shí)字符集轉(zhuǎn)換問題處理方案分享
python學(xué)習(xí)過程中發(fā)現(xiàn)英文不好學(xué)起來挺困難的,其中小弟就遇到一個(gè)十分蛋疼的問題,百度了半天就沒找到解決辦法~囧~摸索了半天自己解決了,記錄下來與君共勉。2014-06-06