參考
5.1 二維卷積層
卷積神經網絡(convolutional neural network)是含有卷積層(convolutional layer)的神經網絡。本章介紹的卷積神經網絡均使用最常見的二維卷積層。它有高和寬兩個空間維度,常用來處理圖像數據。本節中,我們將介紹簡單形式的二維卷積層的工作原理。
5.1.1 二維互相關運算
# 將上述過程實現在 corr2d 函數里.它接受輸入數組 X 與核數組 K,并輸出數組 Y
import torch
from torch import nndef corr2d(X, K): # 本函數已保存在d2lzh_pytorch包中方便以后使用h, w = K.shapeY = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i: i + h, j: j + w] * K).sum()return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
K = torch.tensor([[0, 1], [2, 3]])
corr2d(X, K)
5.1.2 二維卷積層
二維卷積層將輸入和卷積核做互相運算,并加上一個標量偏差來得到輸出。卷積層的模型參數包括了卷積核和標量偏差。在訓練模型的時候,通常我們先對卷積核進行隨機初始化,然后不斷迭代卷積核和偏差。
下面基于corr2d
函數實現一個自定義的二維卷積層。在構造函數__init__
里,我們聲明了weight
和bias
這兩個模型參數。前向計算函數forward
則是直接調用corr2d
函數在加上偏差
class Conv2D(nn.Module):def __init__(self, kernel_size):super(Conv2D, self).__init__()self.weight = nn.Parameter(torch.randn(kernel_size))self.bias = nn.Parameter(torch.randn(1))def forward(self, x):return corr2d(x, self.weight) + self.bias
5.1.3 圖像中物體邊緣檢測
下面我們來看一個卷積的簡單應用: 檢測圖像物體的邊緣,即找到像素變化的位置。首先我們構造一張 6 * 8 的圖像。它中間4列為黑(0),其余為白(1)
X = torch.ones(6, 8)
X[:, 2:6] = 0.
X
然后我們構造一個高和寬分別為1和2的卷積核K。當它與輸入做相關運行時,如果橫向相鄰元素相同,輸出為0; 否則輸出為非0.
K = torch.tensor([[1., -1.]])
K
下面將輸入X和我們設計的卷積核K做相關運算。可以看出,我們將從白到黑和從黑到白的邊緣分別檢測成了1和-1。其余部分的輸出全是0
Y = corr2d(X, K)
Y
5.1.4 通過數據學習核數組
最后我們來看一個例子,它使用物體邊緣檢測中的輸入數據X
和輸出數據Y
來學習我們構造的核數組K
。我們首先構造一個卷積層,其卷積核將被初始化成隨機數組。接下來在每一次迭代中,我們使用平方誤差來比較Y
和卷積層的輸出,然后計算梯度來更新權重。
# 構造一個核數組
conv2d = Conv2D(kernel_size=(1, 2))step ,lr = 60 , 0.01for i in range(step):Y_hat = conv2d(X)l = ((Y_hat - Y) ** 2).sum()l.backward()# 梯度下降conv2d.weight.data -= lr * conv2d.weight.gradconv2d.bias.data -= lr * conv2d.bias.grad# 梯度清0conv2d.weight.grad.fill_(0)conv2d.bias.grad.fill_(0)if(i + 1) % 5 == 0:print("Step %d, loss %.5f "% (i+1, l.item()))
print(conv2d.weight)
print(conv2d.bias)