<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 5.1 二維卷積層 卷積神經網絡(convolutional neural network)是含有卷積層(convolutional layer)的神經網絡。本章中介紹的卷積神經網絡均使用最常見的二維卷積層。它有高和寬兩個空間維度,常用來處理圖像數據。本節中,我們將介紹簡單形式的二維卷積層的工作原理。 ## 5.1.1 二維互相關運算 雖然卷積層得名于卷積(convolution)運算,但我們通常在卷積層中使用更加直觀的互相關(cross-correlation)運算。在二維卷積層中,一個二維輸入數組和一個二維核(kernel)數組通過互相關運算輸出一個二維數組。 我們用一個具體例子來解釋二維互相關運算的含義。如圖5.1所示,輸入是一個高和寬均為3的二維數組。我們將該數組的形狀記為`$ 3 \times 3 $`或(3,3)。核數組的高和寬分別為2。該數組在卷積計算中又稱卷積核或過濾器(filter)。卷積核窗口(又稱卷積窗口)的形狀取決于卷積核的高和寬,即`$ 2 \times 2 $`。圖5.1中的陰影部分為第一個輸出元素及其計算所使用的輸入和核數組元素:`$ 0\times0+1\times1+3\times2+4\times3=19 $`。 :-: ![](https://img.kancloud.cn/55/5c/555c702dc56feb9e1bbf864751d16fa1.svg) <div align=center>圖5.1 二維互相關運算</div> 在二維互相關運算中,卷積窗口從輸入數組的最左上方開始,按從左往右、從上往下的順序,依次在輸入數組上滑動。當卷積窗口滑動到某一位置時,窗口中的輸入子數組與核數組按元素相乘并求和,得到輸出數組中相應位置的元素。圖5.1中的輸出數組高和寬分別為2,其中的4個元素由二維互相關運算得出: ```[tex] 0\times0+1\times1+3\times2+4\times3=19,\\ 1\times0+2\times1+4\times2+5\times3=25,\\ 3\times0+4\times1+6\times2+7\times3=37,\\ 4\times0+5\times1+7\times2+8\times3=43.\\ ``` 下面我們將上述過程實現在`corr2d`函數里。它接受輸入數組`X`與核數組`K`,并輸出數組`Y`。 ``` python import torch from torch import nn def corr2d(X, K): # 本函數已保存在d2lzh_pytorch包中方便以后使用 h, w = K.shape Y = 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 ``` 我們可以構造圖5.1中的輸入數組`X`、核數組`K`來驗證二維互相關運算的輸出。 ``` python X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) K = torch.tensor([[0, 1], [2, 3]]) corr2d(X, K) ``` 輸出: ``` tensor([[19., 25.], [37., 43.]]) ``` ## 5.1.2 二維卷積層 二維卷積層將輸入和卷積核做互相關運算,并加上一個標量偏差來得到輸出。卷積層的模型參數包括了卷積核和標量偏差。在訓練模型的時候,通常我們先對卷積核隨機初始化,然后不斷迭代卷積核和偏差。 下面基于`corr2d`函數來實現一個自定義的二維卷積層。在構造函數`__init__`里我們聲明`weight`和`bias`這兩個模型參數。前向計算函數`forward`則是直接調用`corr2d`函數再加上偏差。 ``` python 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 ``` 卷積窗口形狀為 `$ p \times q $`的卷積層稱為`$ p \times q $`卷積層。同樣,`$ p \times q $`卷積或 `$ p \times q $`卷積核說明卷積核的高和寬分別為`$ p $`和`$ q $`。 ## 5.1.3 圖像中物體邊緣檢測 下面我們來看一個卷積層的簡單應用:檢測圖像中物體的邊緣,即找到像素變化的位置。首先我們構造一張`$ 6\times 8 $` 的圖像(即高和寬分別為6像素和8像素的圖像)。它中間4列為黑(0),其余為白(1)。 ``` python X = torch.ones(6, 8) X[:, 2:6] = 0 X ``` 輸出: ``` tensor([[1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.]]) ``` 然后我們構造一個高和寬分別為1和2的卷積核`K`。當它與輸入做互相關運算時,如果橫向相鄰元素相同,輸出為0;否則輸出為非0。 ``` python K = torch.tensor([[1, -1]]) ``` 下面將輸入`X`和我們設計的卷積核`K`做互相關運算。可以看出,我們將從白到黑的邊緣和從黑到白的邊緣分別檢測成了1和-1。其余部分的輸出全是0。 ``` python Y = corr2d(X, K) Y ``` 輸出: ``` tensor([[ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.]]) ``` 由此,我們可以看出,卷積層可通過重復使用卷積核有效地表征局部空間。 ## 5.1.4 通過數據學習核數組 最后我們來看一個例子,它使用物體邊緣檢測中的輸入數據`X`和輸出數據`Y`來學習我們構造的核數組`K`。我們首先構造一個卷積層,其卷積核將被初始化成隨機數組。接下來在每一次迭代中,我們使用平方誤差來比較`Y`和卷積層的輸出,然后計算梯度來更新權重。 ``` python # 構造一個核數組形狀是(1, 2)的二維卷積層 conv2d = Conv2D(kernel_size=(1, 2)) step = 20 lr = 0.01 for i in range(step): Y_hat = conv2d(X) l = ((Y_hat - Y) ** 2).sum() l.backward() # 梯度下降 conv2d.weight.data -= lr * conv2d.weight.grad conv2d.bias.data -= lr * conv2d.bias.grad # 梯度清0 conv2d.weight.grad.fill_(0) conv2d.bias.grad.fill_(0) if (i + 1) % 5 == 0: print('Step %d, loss %.3f' % (i + 1, l.item())) ``` 輸出: ``` Step 5, loss 1.844 Step 10, loss 0.206 Step 15, loss 0.023 Step 20, loss 0.003 ``` 可以看到,20次迭代后誤差已經降到了一個比較小的值。現在來看一下學習到的卷積核的參數。 ``` python print("weight: ", conv2d.weight.data) print("bias: ", conv2d.bias.data) ``` 輸出: ``` weight: tensor([[ 0.9948, -1.0092]]) bias: tensor([0.0080]) ``` 可以看到,學到的卷積核的權重參數與我們之前定義的核數組`K`較接近,而偏置參數接近0。 ## 5.1.5 互相關運算和卷積運算 實際上,卷積運算與互相關運算類似。**為了得到卷積運算的輸出,我們只需將核數組左右翻轉并上下翻轉,再與輸入數組做互相關運算**。可見,卷積運算和互相關運算雖然類似,但如果它們使用相同的核數組,對于同一個輸入,輸出往往并不相同。 那么,你也許會好奇卷積層為何能使用互相關運算替代卷積運算。其實,在深度學習中核數組都是學出來的:卷積層無論使用互相關運算或卷積運算都不影響模型預測時的輸出。為了解釋這一點,假設卷積層使用互相關運算學出圖5.1中的核數組。設其他條件不變,使用卷積運算學出的核數組即圖5.1中的核數組按上下、左右翻轉。也就是說,圖5.1中的輸入與學出的已翻轉的核數組再做卷積運算時,依然得到圖5.1中的輸出。為了與大多數深度學習文獻一致,如無特別說明,本書中提到的卷積運算均指互相關運算。 > 注:感覺深度學習中的卷積運算實際上是互相關運算是個面試題考點。 ## 5.1.6 特征圖和感受野 二維卷積層輸出的二維數組可以看作是輸入在空間維度(寬和高)上某一級的表征,也叫特征圖(feature map)。影響元素`$ x $`的前向計算的所有可能輸入區域(可能大于輸入的實際尺寸)叫做`$ x $`的感受野(receptive field)。以圖5.1為例,輸入中陰影部分的四個元素是輸出中陰影部分元素的感受野。我們將圖5.1中形狀為`$ 2 \times 2 $`的輸出記為`$ Y $`,并考慮一個更深的卷積神經網絡:將`$ Y $`與另一個形狀為`$ 2 \times 2 $`的核數組做互相關運算,輸出單個元素`$ z $`。那么,`$ z $`在`$ Y $`上的感受野包括`$ Y $`的全部四個元素,在輸入上的感受野包括其中全部9個元素。可見,我們可以通過更深的卷積神經網絡使特征圖中單個元素的感受野變得更加廣闊,從而捕捉輸入上更大尺寸的特征。 我們常使用“元素”一詞來描述數組或矩陣中的成員。在神經網絡的術語中,這些元素也可稱為“單元”。當含義明確時,本書不對這兩個術語做嚴格區分。 ## 小結 * 二維卷積層的核心計算是二維互相關運算。在最簡單的形式下,它對二維輸入數據和卷積核做互相關運算然后加上偏差。 * 我們可以設計卷積核來檢測圖像中的邊緣。 * 我們可以通過數據來學習卷積核。 ----------- > 注:除代碼外本節與原書此節基本相同,[原書傳送門](https://zh.d2l.ai/chapter_convolutional-neural-networks/conv-layer.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看