深度學習入門筆記(十八):卷積神經網路(一)

我是管小亮發表於2020-02-14

專欄——深度學習入門筆記

宣告

1)該文章整理自網上的大牛和機器學習專家無私奉獻的資料,具體引用的資料請看參考文獻。
2)本文僅供學術交流,非商用。所以每一部分具體的參考資料並沒有詳細對應。如果某部分不小心侵犯了大家的利益,還望海涵,並聯系博主刪除。
3)博主才疏學淺,文中如有不當之處,請各位指出,共同進步,謝謝。
4)此屬於第一版本,若有錯誤,還需繼續修正與增刪。還望大家多多指點。大家都共享一點點,一起為祖國科研的推進添磚加瓦。

深度學習入門筆記(十八):卷積神經網路(一)

推薦部落格:大話卷積神經網路CNN(乾貨滿滿)

1、Padding填充

為了構建深度神經網路,需要學習很多東西,除了前面講過的最基本的卷積,還需要學會使用的一個基本的卷積操作就是 padding,一起來看看它是如何工作的。

我們在 深度學習入門筆記(十六):計算機視覺之邊緣檢測 中講過卷積這個例子,如果用一個3×3的過濾器卷積一個6×6的影象,那麼最後會得到一個4×4的輸出(也就是一個4×4矩陣)。這背後的數學解釋是,如果有一個 n×nn×n 的影象,用 f×ff×f 的過濾器做卷積,步長是1,那麼輸出的維度就是 (nf+1)×(nf+1)(n-f+1)×(n-f+1),即 63+1=46-3+1=4

這樣的話會有兩個缺點:

  • 第一個缺點是,每次卷積,影象就會縮小,從6×6縮小到4×4,再多做幾次之後,比如當一個100層的深層網路,每經過一層影象都縮小,經過100層網路後,就會得到一個很小很小的影象,可能是1×1,可能是別的,但我們不想讓影象在每次識別邊緣或其他特徵時都縮小。
  • 第二個缺點是,如果是在角落邊緣的畫素,這個綠色陰影標記只被一個輸出所觸碰或者使用,因為它位於這個3×3的區域的一角;但如果是在中間的畫素點,比如紅色方框標記,就會有許多個3×3的區域與之重疊,所以那些在角落或者邊緣區域的畫素點在輸出中採用較少,意味著丟失了影象邊緣位置的許多資訊。

在這裡插入圖片描述
為了解決問題,在卷積操作之前可以填充這幅影象。

比如在這個案例中,可以沿著影象邊緣再填充一層畫素,這樣6×6的影象就被填充成了8×8。如果用3×3的影象對這個8×8的影象卷積,得到的輸出就不是4×4而是6×6,這樣就得到了一個尺寸和原始影象相同的影象。

習慣上是用0去填充!如果 pp 是填充的數量,在這個案例中 p=1p=1,因為在原始影象周圍填充了一個畫素點,輸出也就變成了 (n+2pf+1)×(n+2pf+1)(n+2p-f+1)×(n+2p-f+1),所以就變成了 (6+2×13+1)×(6+2×13+1)(6+2×1-3+1)×(6+2×1-3+1),即 6×66×6,和輸入的影象一樣大。這樣的話,塗綠的畫素點(左邊矩陣)影響了輸出中的這些格子(右邊矩陣)。這樣一來,丟失資訊或者更準確來說角落或影象邊緣的資訊發揮的作用較小的這一缺點就被削弱了。

填充畫素通常有兩個選擇,分別叫做 Valid 卷積和 Same 卷積:

  • Valid 卷積意味著不填充,這樣的話,p=0p=0
  • Same 卷積意味著填充,且輸出大小和輸入大小是一樣的。

習慣上,計算機視覺中濾波器大小 ff 是奇數,甚至可能都是這樣,比如1,3,5,為什麼很少能看到偶數的過濾器,大概有兩個原因:

  • 第二個原因是,如果 ff 是一個偶數,那麼只能使用一些不對稱填充,而只有 ff 是奇數的情況下,Same 卷積才會有自然的填充,而不是左邊填充多一點,右邊填充少一點,這樣不對稱的填充。
  • 第二個原因是,當有一個奇數維過濾器,比如3×3或者5×5的,它就有一箇中心點。有時在計算機視覺裡,如果有一箇中心畫素點會更方便,便於指出過濾器的位置。

看起來,也許這些都不是為什麼 ff 通常是奇數的充分原因,但如果看了卷積的文獻,你就會經常會看到3×3的過濾器,也可能會看到一些5×5,7×7的過濾器,甚至有些時候會是1×1的,後面會談到它以及什麼時候它是有意義的。

2、卷積步長

卷積中的步幅是另一個構建卷積神經網路的基本操作,來看一個例子。
在這裡插入圖片描述
如果也想用3×3的過濾器卷積這個7×7的影象,和之前不同的是,現在步幅設定成了2。第一個位置還是和之前一樣取左上方的3×3區域的元素的乘積,再加起來,最後結果為91,然後向右移動兩個空格,以此類推。

所以這個例子中是用3×3的矩陣卷積一個7×7的矩陣,得到一個3×3的輸出,計算公式還是和之前一樣,過程如下:

如果用一個 f×ff×f 的過濾器卷積一個 n×nn×n 的影象,paddingpp,步幅為 ss,在這個例子中 s=2s=2,那麼輸出變為 (n+2pfs+1)×(n+2pfs+1)(\frac{n+2p - f}{s} + 1) \times (\frac{n+2p - f}{s} + 1),其實之前的例子也是一樣,只不過 s=1s=1,而在現在這個例子裡 n=7n=7p=0p=0f=3f=3s=2s=2 7+032+1=3\ \frac{7 + 0 - 3}{2} + 1 =3,即3×3的輸出。
在這裡插入圖片描述
現在只剩下最後的一個細節了,如果商不是一個整數怎麼辦?在這種情況下是會向下取整的,⌊ ⌋ 就是向下取整的符號,也叫做對 zz 進行地板除(floor),這意味著 zz 向下取整到最近的整數。這個原則具體實現的方式是,只在藍框完全包括在影象或填充完的影象內部時,才對它進行運算;如果有任意一個藍框移動到了外面,那就不要進行相乘操作,這是一個慣例。

3、三維卷積

卷積不僅僅可以發生在二維影象上,也可以發生在三維立體上。

來看一個例子,假如說不僅想檢測灰度影象的特徵,也想檢測 RGB 彩色影象的特徵。如果彩色影象是6×6×3,這裡的3指的是三個顏色通道,可以想象成3個6×6影象的堆疊,為了檢測影象的邊緣或者其他的特徵,不是把它跟原來的3×3的過濾器做卷積,而是跟一個三維的3×3×3的過濾器卷積,這樣這個過濾器也有三層,對應紅綠、藍三個通道。

給這些起個名字(原影象),這裡的第一個6代表影象高度,第二個6代表寬度,這個3代表通道的數目。同樣地,過濾器也有一個高,寬和通道數,並且影象的通道數必須和過濾器的通道數匹配,所以這兩個數(紫色方框標記的兩個數,3)必須相等。
在這裡插入圖片描述
還是卷積的過程,最後一個數字通道數必須和過濾器中的通道數相匹配。
在這裡插入圖片描述
把過濾器先放到最左上角的位置,這個3×3×3的過濾器有27個數,27個引數就是3的立方,依次取這27個數,然後乘以相應的紅綠藍通道中的數字:

  • 先取紅色通道的前9個數字,
  • 然後是綠色通道,
  • 然後再是藍色通道,
  • 乘以左邊黃色立方體覆蓋的對應的27個數,
  • 然後把這些數都加起來,就得到了輸出的第一個數字。

如果要計算下一個輸出,就把這個立方體滑動一個單位,執行上面的操作,以此類推。
在這裡插入圖片描述
那麼,這個能幹什麼呢?

舉個例子,這個過濾器是3×3×3的,如果想檢測影象紅色通道的邊緣,那麼可以將第一個過濾器設為 [101101101]\begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\\end{bmatrix},和之前一樣,而綠色通道全為0([000000000]\begin{bmatrix} 0& 0 & 0 \\ 0 &0 & 0 \\ 0 & 0 & 0 \\\end{bmatrix}),藍色也全為0。這樣的三個矩陣堆疊在一起形成一個3×3×3的過濾器就是一個檢測垂直邊界的過濾器,且只對紅色通道有用。
在這裡插入圖片描述
或者如果你不關心垂直邊界在哪個顏色通道里,那麼可以用一個這樣的過濾器,[101101101]\begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\ \end{bmatrix}[101101101]\begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\ \end{bmatrix}[101101101]\begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\\end{bmatrix},三個通道都是這樣的。按照計算機視覺的慣例,過濾器可以有不同的高,不同的寬,但是必須一樣的通道數。

現在我們已經瞭解瞭如何對立方體卷積,還有最後一個概念就是,如果不僅僅想要檢測垂直邊緣怎麼辦?如果同時檢測垂直邊緣和水平邊緣,還有45°傾斜的邊緣,還有70°傾斜的邊緣怎麼做?換句話說,如果想同時用多個過濾器怎麼辦?

一個6×6×3的影象和這個3×3×3的過濾器卷積,得到4×4的輸出:

  • 第一個過濾器可能是一個垂直邊界檢測器或者是學習檢測其他的特徵;
  • 第二個過濾器可以是一個水平邊緣檢測器。

在這裡插入圖片描述
所以和第一個過濾器卷積,可以得到第一個4×4的輸出,然後卷積第二個過濾器,得到另一個不同的4×4的輸出,待做完卷積之後把這兩個4×4的輸出,把兩個輸出堆疊在一起得到了一個4×4×2的輸出立方體。

小結一下 維度問題,如果有一個 n×n×ncn \times n \times n_{c} 的輸入影象,在上面是6×6×3,ncn_{c} 是通道(或者深度)數目,然後卷積上一個 f×f×ncf×f×n_{c},在上面是3×3×3,按照慣例,這個(前一個 ncn_{c})和這個(後一個 ncn_{c})必須數值相同,然後就得到了 nf+1×nf+1×nc(n-f+1)×(n-f+1)×n_{c^{'}},這裡 ncn_{c^{'}} 其實就是下一層的通道數,就是用的過濾器的個數,在上面就是4×4×2。這對立方體卷積的概念真的很有用!用它的一小部分直接在三個通道的 RGB 影象上進行操作,更重要的是,可以檢測兩個特徵,比如垂直和水平邊緣或者10個或者128個或者幾百個不同的特徵,並且輸出的通道數會等於準備要檢測的特徵數。

4、單層卷積網路

做了這麼多準備之後,終於可以開始構建卷積神經網路的卷積層,下面來看個例子。

通過兩個過濾器卷積處理一個三維影象,並輸出兩個不同的矩陣:
在這裡插入圖片描述
最終各自形成一個卷積神經網路層,然後增加偏差(實數),通過 Python 的廣播機制給這16個元素都加上同一偏差,然後應用非線性啟用函式 ReLU,輸出結果是一個4×4矩陣。對於第二個4×4矩陣,是加上了不同的偏差(實數),然後應用非線性函式,最終得到另一個4×4矩陣。然後重複之前的步驟,把這兩個矩陣堆疊起來,得到一個4×4×2的矩陣。

廣播機制看這裡:深度學習入門筆記(五):神經網路的程式設計基礎

通過計算,從6×6×3的輸入推匯出一個4×4×2矩陣,它是卷積神經網路的一層,把它對映到標準神經網路中四個卷積層中的某一層或者一個非卷積神經網路中。

注意,前向傳播中一個操作就是 z[1]=W[1]a[0]+b[1]z^{[1]} = W^{[1]}a^{[0]} + b^{[1]},其中 a[0]=xa^{[0]} =x,執行非線性函式得到 a[1]a^{[1]},即 a[1]=g(z[1])a^{[1]} = g(z^{[1]}),輸入是a[0]a^{\left\lbrack 0\right\rbrack},也就是 xx,過濾器用變數 W[1]W^{[1]} 表示。在整個卷積過程中,對這3×3×3=27個數進行操作,其實是27×2(因為用了兩個過濾器),取這些數做乘法,實際執行了一個線性函式,得到一個4×4的矩陣,卷積操作的輸出結果是一個4×4的矩陣,它的作用類似於 W[1]a[0]W^{[1]}a^{[0]},也就是這兩個4×4矩陣的輸出結果,然後加上偏差。
在這裡插入圖片描述
這一部分(圖中藍色邊框標記的部分)就是應用啟用函式 ReLU 之前的值,它的作用類似於 z[1]z^{[1]},最後應用非線性函式,得到的這個4×4×2矩陣,成為神經網路的下一層,也就是啟用層,這就是 a[0]a^{[0]}a[1]a^{[1]} 的演變過程。

示例中有兩個過濾器,也就是有兩個特徵,因此最終才得到一個4×4×2的輸出,但如果用了10個過濾器,而不是2個,最後會得到一個4×4×10維度的輸出影象,因為我們選取了其中10個特徵對映(而不僅僅是2個)將它們堆疊在一起,形成一個4×4×10的輸出影象,也就是 a[1]a^{\left\lbrack1 \right\rbrack}

為了加深理解,來做一個練習。

假設現在有10個過濾器,而不是2個,神經網路的一層是3×3×3,那麼,這一層有多少個引數呢???

來一起計算一下,每一層都是一個3×3×3的矩陣,因此每個過濾器有27個引數,也就是27個數,然後加上一個偏差,用引數 bb 表示,現在引數增加到28個,有10個過濾器,即28×10,也就是280個引數。不過,請注意一點,不論輸入圖片有多大,1000×1000也好,5000×5000也好,引數始終都是280個,即使這些圖片很大,引數卻很少,這就是卷積神經網路的一個特徵,叫作 避免過擬合

避免過擬合的方式看這裡:深度學習入門筆記(十):正則化

5、總結

最後總結一下用於描述卷積神經網路中的一層(以 ll 層為例),也就是卷積層的各種標記:

這一層是卷積層,用 f[l]f^{[l]} 表示過濾器大小,上標 [l]\lbrack l\rbrack 用來標記 ll 層,上標 [l]\lbrack l\rbrack 表示 ll 層中過濾器大小為 f×ff×f;用 p[l]p^{[l]} 來標記 padding 的數量,valid 卷積,即無 paddingsame 卷積,即選定 padding;用 s[l]s^{[l]} 標記步幅。

這一層的輸入會是某個維度的資料,表示為 n×n×ncn \times n \times n_{c}ncn_{c} 表示某層上的顏色通道數。只要稍作修改,增加上標 [l1]\lbrack l -1\rbrack,即 n[l1]×n[l1]×nc[l1]n^{\left\lbrack l - 1 \right\rbrack} \times n^{\left\lbrack l -1 \right\rbrack} \times n_{c}^{\left\lbrack l - 1\right\rbrack},就變成了上一層的啟用值。

使用圖片的高度和寬度可以都一樣,但也有可能不同,所以分別用上下標 HHWW 來標記,即 nH[l1]×nW[l1]×nc[l1]n_{H}^{\left\lbrack l - 1 \right\rbrack} \times n_{W}^{\left\lbrack l - 1 \right\rbrack} \times n_{c}^{\left\lbrack l - 1\right\rbrack}ll 層的輸入就是上一層的輸出,因此上標是 [l1]\lbrack l - 1\rbrack,這一層中會有輸出(影象),其大小為 nH[l]×nW[l]×nc[l]n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]}。計算方式前面提到過,至少給出了高度和寬度,n+2pfs+1\lfloor\frac{n+2p - f}{s} + 1\rfloor(注意:n+2pfs+1\frac{n + 2p - f}{s} +1 直接用這個運算結果,也可以向下取整)。

那麼通道數量又是什麼?這些數字從哪兒來的?

輸出影象也具有深度,等於該層中過濾器的數量,就是輸入通道數量,所以過濾器維度等於 f[l]×f[l]×nc[l1]f^{[l]} \times f^{[l]} \times n_{c}^{\left\lbrack l - 1 \right\rbrack}。應用偏差和非線性函式之後,這一層的輸出等於它的啟用值 a[l]a^{[l]}(三維體),即 nH[l]×nW[l]×nc[l]n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]}。當執行批量梯度下降或小批量梯度下降時,如果有 mm 個例子,就是有 mm 個啟用值的集合,那麼輸出 A[l]=m×nH[l]×nW[l]×nc[l]A^{[l]} = m \times n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]}

該如何確定權重引數,即引數W呢?

過濾器的維度已知,為 f[l]×f[l]×nc[l1]f^{[l]} \times f^{[l]} \times n_{c}^{[l - 1]},這只是一個過濾器的維度,如果是多個,nc[l]n_{c}^{[l]} 是過濾器的數量,權重也就是所有過濾器的集合再乘以過濾器的總數量,即 f[l]×f[l]×nc[l1]×nc[l]f^{[l]} \times f^{[l]} \times n_{c}^{[l - 1]} \times n_{c}^{[l]}

最後看看偏差引數,每個過濾器都有一個偏差引數(實數),它是某維度上的一個向量,為了方便,在程式碼中常常表示為一個1×1×1×nc[l]n_{c}^{[l]} 的四維向量或四維張量。

推薦閱讀

參考文章

  • 吳恩達——《神經網路和深度學習》視訊課程

相關文章