本文主要介紹PyTorch中的nn.Conv1d
和nn.Conv2d
方法,并給出相應代碼示例,加深理解。
一維卷積nn.Conv1d
一般來說,一維卷積nn.Conv1d
用于文本數據,只對寬度進行卷積,對高度不卷積。通常,輸入大小為word_embedding_dim * max_length
,其中,word_embedding_dim
為詞向量的維度,max_length
為句子的最大長度。卷積核窗口在句子長度的方向上滑動,進行卷積操作。
定義
class torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
主要參數說明:
-
in_channels
:在文本應用中,即為詞向量的維度 -
out_channels
:卷積產生的通道數,有多少個out_channels,就需要多少個一維卷積(也就是卷積核的數量) -
kernel_size
:卷積核的尺寸;卷積核的第二個維度由in_channels
決定,所以實際上卷積核的大小為kernel_size * in_channels
-
padding
:對輸入的每一條邊,補充0的層數
代碼示例
輸入:批大小為32,句子的最大長度為35,詞向量維度為256
目標:句子分類,共2類
conv1 = nn.Conv1d(in_channels=256, out_channels=100, kernel_size=2)
input = torch.randn(32, 35, 256)
input = input.permute(0, 2, 1)
output = conv1(input)
假設window_size = [3, 4, 5, 6]
,即共有四個卷積核,基于上述代碼,具體計算過程如下:
- 原始輸入大小為
(32, 35, 256)
,經過permute(0, 2, 1)
操作后,輸入的大小變為(32, 256, 35)
; - 使用1個卷積核進行卷積,可得到1個大小為
32 x 100 x 1
的輸出,共4個卷積核,故共有4個大小為32 x 100 x 1
的輸出; - 將上一步得到的4個結果在
dim = 1
上進行拼接,輸出大小為32 x 400 x 1
; -
view
操作后,輸出大小變為32 x 400
; - 全連接,最終輸出大小為
32 x 2
,即分別預測為2類的概率大小。
一維卷積過程圖解
Yoon Kim在2014年發表的論文Convolutional Neural Networks for Sentence Classification中,給出了一個非常形象的圖,詮釋了文本卷積模型的框架,如下所示。
二維卷積nn.Conv2d
一般來說,二維卷積nn.Conv2d
用于圖像數據,對寬度和高度都進行卷積。
定義
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
代碼示例
假設現有大小為32 x 32
的圖片樣本,輸入樣本的channels
為1,該圖片可能屬于10個類中的某一類。CNN框架定義如下:
class CNN(nn.Module):
def __init__(self):
nn.Model.__init__(self)
self.conv1 = nn.Conv2d(1, 6, 5) # 輸入通道數為1,輸出通道數為6
self.conv2 = nn.Conv2d(6, 16, 5) # 輸入通道數為6,輸出通道數為16
self.fc1 = nn.Linear(5 * 5 * 16, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# 輸入x -> conv1 -> relu -> 2x2窗口的最大池化
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
# 輸入x -> conv2 -> relu -> 2x2窗口的最大池化
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
# view函數將張量x變形成一維向量形式,總特征數不變,為全連接層做準備
x = x.view(x.size()[0], -1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
網絡整體結構:[conv + relu + pooling] * 2 + FC * 3
原始輸入樣本的大小:32 x 32 x 1
-
第一次卷積:使用6個大小為
5 x 5
的卷積核,故卷積核的規模為(5 x 5) x 6
;卷積操作的stride
參數默認值為1 x 1
,32 - 5 + 1 = 28,并且使用ReLU對第一次卷積后的結果進行非線性處理,輸出大小為28 x 28 x 6
; -
第一次卷積后池化:
kernel_size
為2 x 2
,輸出大小變為14 x 14 x 6
; -
第二次卷積:使用16個卷積核,故卷積核的規模為
(5 x 5 x 6) x 16
;使用ReLU對第二次卷積后的結果進行非線性處理,14 - 5 + 1 = 10,故輸出大小為10 x 10 x 16
; -
第二次卷積后池化:
kernel_size
同樣為2 x 2
,輸出大小變為5 x 5 x 16
; -
第一次全連接:將上一步得到的結果鋪平成一維向量形式,5 x 5 x 16 = 400,即輸入大小為
400 x 1
,W大小為120 x 400
,輸出大小為120 x 1
; -
第二次全連接,W大小為
84 x 120
,輸入大小為120 x 1
,輸出大小為84 x 1
; -
第三次全連接:W大小為
10 x 84
,輸入大小為84 x 1
,輸出大小為10 x 1
,即分別預測為10類的概率值。
注意
- 在PyTorch中,池化操作默認的
stride
大小與卷積核的大小一致; - 如果池化核的大小為一個方陣,則僅需要指明一個數,即
kernel_size
參數為常數n,表示池化核大小為n x n
。