# 5.3 多輸入通道和多輸出通道
前面兩節里我們用到的輸入和輸出都是二維數組,但真實數據的維度經常更高。例如,彩色圖像在高和寬2個維度外還有RGB(紅、綠、藍)3個顏色通道。假設彩色圖像的高和寬分別是`$ h $`和`$ w $`(像素),那么它可以表示為一個`$ 3\times h\times w $`的多維數組。我們將大小為3的這一維稱為通道(channel)維。本節我們將介紹含多個輸入通道或多個輸出通道的卷積核。
## 5.3.1 多輸入通道
當輸入數據含多個通道時,我們需要構造一個輸入通道數與輸入數據的通道數相同的卷積核,從而能夠與含多通道的輸入數據做互相關運算。假設輸入數據的通道數為`$ c_i $`,那么卷積核的輸入通道數同樣為`$ c_i $`。設卷積核窗口形狀為`$ k_h\times k_w $`。當`$ c_i=1 $`時,我們知道卷積核只包含一個形狀為`$ k_h\times k_w $`的二維數組。當`$ c_i > 1 $`時,我們將會為每個輸入通道各分配一個形狀為`$ k_h\times k_w $`的核數組。把這`$ c_i $`個數組在輸入通道維上連結,即得到一個形狀為`$ c_i\times k_h\times k_w $`的卷積核。由于輸入和卷積核各有 `$ c_i $`個通道,我們可以在各個通道上對輸入的二維數組和卷積核的二維核數組做互相關運算,再將這`$ c_i $`個互相關運算的二維輸出按通道相加,得到一個二維數組。這就是含多個通道的輸入數據與多輸入通道的卷積核做二維互相關運算的輸出。
圖5.4展示了含2個輸入通道的二維互相關計算的例子。在每個通道上,二維輸入數組與二維核數組做互相關運算,再按通道相加即得到輸出。圖5.4中陰影部分為第一個輸出元素及其計算所使用的輸入和核數組元素:`$ (1\times1+2\times2+4\times3+5\times4)+(0\times0+1\times1+3\times2+4\times3)=56 $`。
:-: 
<div align=center>圖5.4 含2個輸入通道的互相關計算</div>
接下來我們實現含多個輸入通道的互相關運算。我們只需要對每個通道做互相關運算,然后通過`add_n`函數來進行累加。
``` python
import torch
from torch import nn
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l
def corr2d_multi_in(X, K):
# 沿著X和K的第0維(通道維)分別計算再相加
res = d2l.corr2d(X[0, :, :], K[0, :, :])
for i in range(1, X.shape[0]):
res += d2l.corr2d(X[i, :, :], K[i, :, :])
return res
```
我們可以構造圖5.4中的輸入數組`X`、核數組`K`來驗證互相關運算的輸出。
``` python
X = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
corr2d_multi_in(X, K)
```
輸出:
```
tensor([[ 56., 72.],
[104., 120.]])
```
## 5.3.2 多輸出通道
當輸入通道有多個時,因為我們對各個通道的結果做了累加,所以不論輸入通道數是多少,輸出通道數總是為1。設卷積核輸入通道數和輸出通道數分別為`$ c_i $`和`$ c_o $`,高和寬分別為`$ k_h $`和`$ k_w $`。如果希望得到含多個通道的輸出,我們可以為每個輸出通道分別創建形狀為`$ c_i\times k_h\times k_w $`的核數組。將它們在輸出通道維上連結,卷積核的形狀即`$ c_o\times c_i\times k_h\times k_w $` 。在做互相關運算時,每個輸出通道上的結果由卷積核在該輸出通道上的核數組與整個輸入數組計算而來。
下面我們實現一個互相關運算函數來計算多個通道的輸出。
``` python
def corr2d_multi_in_out(X, K):
# 對K的第0維遍歷,每次同輸入X做互相關計算。所有結果使用stack函數合并在一起
return torch.stack([corr2d_multi_in(X, k) for k in K])
```
我們將核數組`K`同`K+1`(`K`中每個元素加一)和`K+2`連結在一起來構造一個輸出通道數為3的卷積核。
``` python
K = torch.stack([K, K + 1, K + 2])
K.shape # torch.Size([3, 2, 2, 2])
```
下面我們對輸入數組`X`與核數組`K`做互相關運算。此時的輸出含有3個通道。其中第一個通道的結果與之前輸入數組`X`與多輸入通道、單輸出通道核的計算結果一致。
```python
corr2d_multi_in_out(X, K)
```
輸出:
```
tensor([[[ 56., 72.],
[104., 120.]],
[[ 76., 100.],
[148., 172.]],
[[ 96., 128.],
[192., 224.]]])
```
## 5.3.3 `$ 1\times 1 $`卷積層
最后我們討論卷積窗口形狀為`$ 1\times 1 $`(`$ k_h=k_w=1 $`)的多通道卷積層。我們通常稱之為`$ 1\times 1 $`卷積層,并將其中的卷積運算稱為`$ 1\times 1 $`卷積。因為使用了最小窗口,`$ 1\times 1 $`卷積失去了卷積層可以識別高和寬維度上相鄰元素構成的模式的功能。實際上,`$ 1\times 1 $`卷積的主要計算發生在通道維上。圖5.5展示了使用輸入通道數為3、輸出通道數為2的`$ 1\times 1 $`卷積核的互相關計算。值得注意的是,輸入和輸出具有相同的高和寬。輸出中的每個元素來自輸入中在高和寬上相同位置的元素在不同通道之間的按權重累加。假設我們將通道維當作特征維,將高和寬維度上的元素當成數據樣本,**那么`$ 1\times 1 $`卷積層的作用與全連接層等價**。
:-: 
<div align=center>圖5.5 1x1卷積核的互相關計算。輸入和輸出具有相同的高和寬</div>
下面我們使用全連接層中的矩陣乘法來實現`$ 1\times 1 $`卷積。這里需要在矩陣乘法運算前后對數據形狀做一些調整。
``` python
def corr2d_multi_in_out_1x1(X, K):
c_i, h, w = X.shape
c_o = K.shape[0]
X = X.view(c_i, h * w)
K = K.view(c_o, c_i)
Y = torch.mm(K, X) # 全連接層的矩陣乘法
return Y.view(c_o, h, w)
```
經驗證,做`$ 1\times 1 $`卷積時,以上函數與之前實現的互相關運算函數`corr2d_multi_in_out`等價。
``` python
X = torch.rand(3, 3, 3)
K = torch.rand(2, 3, 1, 1)
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
(Y1 - Y2).norm().item() < 1e-6
```
輸出:
```
True
```
在之后的模型里我們將會看到`$ 1\times 1 $`卷積層被當作保持高和寬維度形狀不變的全連接層使用。于是,我們可以通過調整網絡層之間的通道數來控制模型復雜度。
## 小結
* 使用多通道可以拓展卷積層的模型參數。
* 假設將通道維當作特征維,將高和寬維度上的元素當成數據樣本,那么`$ 1\times 1 $`卷積層的作用與全連接層等價。
* `$ 1\times 1 $`卷積層通常用來調整網絡層之間的通道數,并控制模型復雜度。
-----------
> 注:除代碼外本節與原書此節基本相同,[原書傳送門](https://zh.d2l.ai/chapter_convolutional-neural-networks/channels.html)
- Home
- Introduce
- 1.深度學習簡介
- 深度學習簡介
- 2.預備知識
- 2.1環境配置
- 2.2數據操作
- 2.3自動求梯度
- 3.深度學習基礎
- 3.1 線性回歸
- 3.2 線性回歸的從零開始實現
- 3.3 線性回歸的簡潔實現
- 3.4 softmax回歸
- 3.5 圖像分類數據集(Fashion-MINST)
- 3.6 softmax回歸的從零開始實現
- 3.7 softmax回歸的簡潔實現
- 3.8 多層感知機
- 3.9 多層感知機的從零開始實現
- 3.10 多層感知機的簡潔實現
- 3.11 模型選擇、反向傳播和計算圖
- 3.12 權重衰減
- 3.13 丟棄法
- 3.14 正向傳播、反向傳播和計算圖
- 3.15 數值穩定性和模型初始化
- 3.16 實戰kaggle比賽:房價預測
- 4 深度學習計算
- 4.1 模型構造
- 4.2 模型參數的訪問、初始化和共享
- 4.3 模型參數的延后初始化
- 4.4 自定義層
- 4.5 讀取和存儲
- 4.6 GPU計算
- 5 卷積神經網絡
- 5.1 二維卷積層
- 5.2 填充和步幅
- 5.3 多輸入通道和多輸出通道
- 5.4 池化層
- 5.5 卷積神經網絡(LeNet)
- 5.6 深度卷積神經網絡(AlexNet)
- 5.7 使用重復元素的網絡(VGG)
- 5.8 網絡中的網絡(NiN)
- 5.9 含并行連結的網絡(GoogLeNet)
- 5.10 批量歸一化
- 5.11 殘差網絡(ResNet)
- 5.12 稠密連接網絡(DenseNet)
- 6 循環神經網絡
- 6.1 語言模型
- 6.2 循環神經網絡
- 6.3 語言模型數據集(周杰倫專輯歌詞)
- 6.4 循環神經網絡的從零開始實現
- 6.5 循環神經網絡的簡單實現
- 6.6 通過時間反向傳播
- 6.7 門控循環單元(GRU)
- 6.8 長短期記憶(LSTM)
- 6.9 深度循環神經網絡
- 6.10 雙向循環神經網絡
- 7 優化算法
- 7.1 優化與深度學習
- 7.2 梯度下降和隨機梯度下降
- 7.3 小批量隨機梯度下降
- 7.4 動量法
- 7.5 AdaGrad算法
- 7.6 RMSProp算法
- 7.7 AdaDelta
- 7.8 Adam算法
- 8 計算性能
- 8.1 命令式和符號式混合編程
- 8.2 異步計算
- 8.3 自動并行計算
- 8.4 多GPU計算
- 9 計算機視覺
- 9.1 圖像增廣
- 9.2 微調
- 9.3 目標檢測和邊界框
- 9.4 錨框
- 10 自然語言處理
- 10.1 詞嵌入(word2vec)
- 10.2 近似訓練
- 10.3 word2vec實現
- 10.4 子詞嵌入(fastText)
- 10.5 全局向量的詞嵌入(Glove)
- 10.6 求近義詞和類比詞
- 10.7 文本情感分類:使用循環神經網絡
- 10.8 文本情感分類:使用卷積網絡
- 10.9 編碼器--解碼器(seq2seq)
- 10.10 束搜索
- 10.11 注意力機制
- 10.12 機器翻譯