Pytorch卷積層原理和示例

househou發表於2017-07-13

卷積層是用一個固定大小的矩形區去席捲原始資料,將原始資料分成一個個和卷積核大小相同的小塊,然後將這些小塊和卷積核相乘輸出一個卷積值(注意這裡是一個單獨的值,不再是矩陣了)。

卷積的本質就是用卷積核的引數來提取原始資料的特徵,通過矩陣點乘的運算,提取出和卷積核特徵一致的值,如果卷積層有多個卷積核,則神經網路會自動學習卷積核的引數值,使得每個卷積核代表一個特徵。

這裡我們拿最常用的conv1d舉例說明卷積過程的計算。

conv1d是一維卷積,它和conv2d的區別在於只對寬度進行卷積,對高度不卷積。

函式定義:

torch.nn.functional.conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)

引數說明:

 input:輸入的Tensor資料,格式為(batch,channels,W),三維陣列,第一維度是樣本數量,第二維度是通道數或者記錄數。三維度是寬度。

 weight:卷積核權重,也就是卷積核本身。是一個三維陣列,(out_channels, in_channels/groups, kW)。out_channels是卷積核輸出層的神經元個數,也就是這層有多少個卷積核;in_channels是輸入通道數;kW是卷積核的寬度。

 bias:位移引數,可選項,一般也不用管。

 stride:滑動視窗,預設為1,指每次卷積對原資料滑動1個單元格。

 padding:是否對輸入資料填充0。Padding可以將輸入資料的區域改造成是卷積核大小的整數倍,這樣對不滿足卷積核大小的部分資料就不會忽略了。通過padding引數指定填充區域的高度和寬度,預設0(就是填充區域為0,不填充的意思)

 dilation:卷積核之間的空格,預設1。

 groups:將輸入資料分組,通常不用管這個引數,沒有太大意義。

測試程式碼

import torch

from torch.autograd import Variable

import torch.nn as nn

import torch.nn.functional as F

print("conv1d sample")

a=range(16)

x = Variable(torch.Tensor(a))

x=x.view(1,1,16)

print("x variable:", x)

b=torch.ones(3)

b[0]=0.1

b1=0.2

b2=0.3

weights = Variable(b)#torch.randn(1,1,2,2)) #out_channel*in_channel*H*W

weights=weights.view(1,1,3)

print ("weights:",weights)

y=F.conv1d(x, weights, padding=0)

print ("y:",y)

最終結果:

enter image description here

我們看看它是怎麼計算的:

(1) 原始資料大小是0-15的一共16個數字,卷積核寬度是3,向量是[0.1,0.2,0.3]。 我們看第一個卷積是對x[0:3]共3個值[0,1,2]進行卷積,公式如下:

0*0.1+1*0.2+2*0.3=0.8

(2) 對第二個目標卷積,是x[1:4]共3個值[1,2,3]進行卷積,公式如下:

1*0.1+2*0.2+3*0.3=1.4

看到和計算結果完全一致!

enter image description here

該圖就是conv1d的示意圖,和conv2d的區別就是隻對寬度卷積,不對高度卷積。最後的結果的寬度是原始資料的寬度減去卷積核的寬度再加上1,這裡就是14。

所以最終卷積之後的結果一共是14個數值,顯示如下:

enter image description here

我們再看看輸入資料有多個通道的情況:

核心程式碼:

print("conv1d sample")

a=range(16)

x = Variable(torch.Tensor(a))

x=x.view(1,2,8)

print("x variable:", x)

b=torch.ones(6)

b[0]=0.1

b1=0.2

b2=0.3

weights = Variable(b)

weights=weights.view(1,2,3)

print ("weights:",weights)

y=F.conv1d(x, weights, padding=0)

print ("y:",y)

我們看看返回結果第一個元素27.8是怎麼計算出來的,這時候卷積核有2個通道:

[0.1,0.2,0.3]和[1,1,1]

第1個卷積物件也有2個通道:

[0,1,2]和[8,9,10]

結果是2個卷積核分別對應2個輸入通道進行卷積然後求和。

卷積核對第1個卷積物件的卷積值:(0.1*0+0.2*1+0.3*2)+(1*8+1*9+1*10)=27.8

第2個卷積物件也有2個通道:

[1,2,3]和[9,10,11]

卷積核對第2個卷積物件的卷積值:(0.1*1+0.2*2+0.3*3)+(1*9+1*10+1*11)=31.4

和pytorch計算結果相同。

相關文章