Ng深度學習筆記——卷積神經網路基礎

CeciliaFinch發表於2020-11-08

計算機視覺(Computer vision)

一般計算機視覺的問題:

  • 圖片分類Image Classification

  • 目標識別Object detection

  • 圖片風格遷移Neural Style Transfer

在這裡插入圖片描述

使用傳統神經網路處理機器視覺的一個主要問題是輸入層維度很大。例如一張64x64x3的圖片,神經網路輸入層的維度為12288。如果圖片尺寸較大,例如一張1000x1000x3的圖片,神經網路輸入層的維度將達到3百萬,使得網路權重W非常龐大。這樣會造成兩個後果,一是神經網路結構複雜,資料量相對不夠,容易出現過擬合;二是所需記憶體、計算量較大。解決這一問題的方法就是使用卷積神經網路(CNN)。

邊緣檢測示例(Edge detection example)

使用邊緣檢測作為入門樣例,如何在一張圖片中進行邊緣檢測。

給了這樣一張圖片,讓電腦去搞清楚照片裡有什麼物體,你可能做的第一件事是檢測圖片中的垂直邊緣。比如說,在這張圖片中的欄杆就對應垂直線,與此同時,這些行人的輪廓線某種程度上也是垂線,這些線是垂直邊緣檢測器的輸出。同樣,你可能也想檢測水平邊緣,比如說這些欄杆就是很明顯的水平線,它們也能被檢測到。在這裡插入圖片描述

所以如何在影像中檢測這些邊緣?
在這裡插入圖片描述

看一個例子,這是一個6×6的灰度影像, 它是6×6×1的矩陣,而不是6×6×3的,因為沒有RGB三通道。為了檢測影像中的垂直邊緣,你可以構造一個3×3矩陣。在卷積神經網路的術語中,它被稱為過濾器。我要構造一個3×3的過濾器,像這樣 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix}1 & 0 & -1\\1 & 0 & -1\\ 1 & 0 & -1\end{bmatrix} 111000111。在論文它有時候會被稱為核。對這個6×6的影像進行卷積運算,卷積運算用*來表示,用3×3的過濾器對其進行卷積。

關於符號表示: 有一些問題,在數學中“$$”就是卷積的標準標誌,但是在Python中,這個標識常常被用來表示乘法或者元素乘法。所以這個“$$”有多層含義,它是一個過載符號。

這個卷積運算的輸出將會是一個4×4的矩陣,你可以將它看成一個4×4的影像。下面來說明是如何計算得到這個4×4矩陣的。為了計算第一個元素,在4×4左上角的那個元素,使用3×3的過濾器,將其覆蓋在輸入影像,如下圖所示。然後進行元素乘法(element-wise products)運算,所以 [ 3 × 1 0 × 0 1 × ( 1 ) 1 × 1 5 × 0 8 × ( − 1 ) 2 × 1 7 × 0 2 × ( − 1 )   ] = [ 3 0 − 1 1 0 − 8 2 0 − 2 ] \begin{bmatrix} 3 \times 1 & 0 \times 0 & 1 \times \left(1 \right) \\ 1 \times 1 & 5 \times 0 & 8 \times \left( - 1 \right) \\ 2 \times1 & 7 \times 0 & 2 \times \left( - 1 \right) \ \end{bmatrix} = \begin{bmatrix}3 & 0 & - 1 \\ 1 & 0 & - 8 \\ 2 & 0 & - 2 \\ \end{bmatrix} 3×11×12×10×05×07×01×(1)8×(1)2×(1) =312000182,然後將該矩陣每個元素相加得到最左上角的元素,即 3 + 1 + 2 + 0 + 0 + 0 + ( − 1 ) + ( − 8 ) + ( − 2 ) = − 5 3+1+2+0+0 +0+(-1)+(-8) +(-2)=-5 3+1+2+0+0+0+(1)+(8)+(2)=5

在這裡插入圖片描述

接下來,為了弄明白第二個元素是什麼,你要把藍色的方塊,向右移動一步:

在這裡插入圖片描述

繼續做同樣的元素乘法,然後加起來,所以是 $0×1+5×1+7×1+1×0+8×0+2×0+2×(-1)+ 9×(-1)+5×(-1)=-4 $。

因此6×6矩陣和3×3矩陣進行卷積運算得到4×4矩陣。這些圖片和過濾器是不同維度的矩陣,但左邊矩陣容易被理解為一張圖片,中間的這個被理解為過濾器,右邊的圖片我們可以理解為另一張圖片。這個就是垂直邊緣檢測器,下一頁中你就會明白。

在往下講之前,多說一句,如果你要使用程式語言實現這個運算,不同的程式語言有不同的函式,而不是用“ ∗ * ”來表示卷積。所以在程式設計練習中,你會使用一個叫conv_forward的函式。如果在tensorflow下,這個函式叫tf.conv2d。在其他深度學習框架中,在後面的課程中,你將會看到Keras這個框架,在這個框架下用Conv2D實現卷積運算。所有的程式設計框架都有一些函式來實現卷積運算。

為什麼這個可以做垂直邊緣檢測呢?來看另外一個例子。
這是一個簡單的6×6影像,左邊的一半是10,右邊一般是0。如果你把它當成一個圖片,左邊那部分看起來是白色的,畫素值10是比較亮的畫素值,右邊畫素值比較暗,使用灰色來表示0。圖片裡,有一個特別明顯的垂直邊緣在影像中間,這條垂直線是從黑到白的過渡線.

在這裡插入圖片描述

所以,當用一個3×3過濾器進行卷積運算的時候,這個3×3的過濾器視覺化為在左邊有明亮的畫素,然後有一個過渡,0在中間,然後右邊是深色的。卷積運算後,你得到的是右邊的矩陣。 10 × 1 + 10 × 1 + 10 × 1 + 10 × 0 + 10 × 0 + 10 × 0 + 10 × ( − 1 ) + 10 × ( − 1 ) + 10 × ( − 1 ) = 0 10×1+10×1+10×1+10×0+10×0+10×0+10×(-1)+10×(-1)+10×(-1)=0 10×1+10×1+10×1+10×0+10×0+10×0+10×(1)+10×(1)+10×(1)=0

相反這個30是由這個

10 × 1 + 10 × 1 + 10 × 1 + 10 × 0 + 10 × 0 + 10 × 0 + 0 × ( − 1 ) + 0 × ( − 1 ) + 0 × ( − 1 ) = 30 10×1+10×1+10×1+10×0+10×0+10×0+0×(-1)+0×(-1)+ 0×(-1)=30 10×1+10×1+10×1+10×0+10×0+10×0+0×(1)+0×(1)+0×(1)=30

在這個例子中,在輸出影像中間的亮處,表示在影像中間有一個特別明顯的垂直邊緣。從垂直邊緣檢測中可以得到的啟發是,因為我們使用3×3的過濾器,所以垂直邊緣是一個3×3的區域,左邊是明亮的畫素,中間的並不需要考慮,右邊是深色畫素。在這個6×6影像的中間部分,明亮的畫素在左邊,深色的畫素在右邊,就被視為一個垂直邊緣,卷積運算提供了一個方便的方法來發現影像中的垂直邊緣。

在這裡插入圖片描述
這張6×6的圖片,左邊較亮,而右邊較暗,將它與垂直邊緣檢測濾波器進行卷積,檢測結果就顯示在了右邊這幅圖的中間部分。

在這裡插入圖片描述

現在這幅圖有什麼變化呢?它的顏色被翻轉了,變成了左邊比較暗,而右邊比較亮。現在亮度為10的點跑到了右邊,為0的點則跑到了左邊。如果你用它與相同的過濾器進行卷積,最後得到的圖中間會是-30,而不是30。如果你將矩陣轉換為圖片,就會是該矩陣下面圖片的樣子。現在中間的過渡部分被翻轉了,之前的30翻轉成了-30,表明是由暗向亮過渡,而不是由亮向暗過渡。

如果你不在乎這兩者的區別,你可以取出矩陣的絕對值。但這個特定的過濾器確實可以為我們區分這兩種明暗變化的區別。

再來看看更多的邊緣檢測的例子,右邊這個過濾器,它能讓你檢測出水平的邊緣。

在這裡插入圖片描述
在這裡插入圖片描述

我們現在所使用的都是相對很小的圖片,僅有6×6。但假如這個一個非常大的1000×1000的類似這樣棋盤風格的大圖,就不會出現這些亮度為10的過渡帶了,因為圖片尺寸很大,這些中間值就會變得非常小。

總而言之,通過使用不同的過濾器,可以找出垂直的或是水平的邊緣。

除了上面提到的這種簡單的Vertical、Horizontal濾波器之外,還有其它常用的filters,例如Sobel filter和Scharr filter。這兩種濾波器的特點是增加圖片中心區域的權重。

在深度學習中,如果我們想檢測圖片的各種邊緣特徵,而不僅限於垂直邊緣和水平邊緣,那麼filter的數值一般需要通過模型訓練得到,類似於標準神經網路中的權重W一樣由梯度下降演算法反覆迭代求得。CNN的主要目的就是計算出這些filter的數值。確定得到了這些filter後,CNN淺層網路也就實現了對圖片所有邊緣特徵的檢測。

Padding

我們在之前視訊中看到,如果你用一個3×3的過濾器卷積一個6×6的影像,你最後會得到一個4×4的輸出,也就是一個4×4矩陣。這背後的數學解釋是,如果我們有一個 n × n n×n n×n的影像,用 f × f f×f f×f的過濾器做卷積,那麼輸出的維度就是 ( n − f + 1 ) × ( n − f + 1 ) (n-f+1)×(n-f+1) (nf+1)×(nf+1)

這樣的話會有兩個缺點:

  • 每次做卷積操作,影像就會縮小。

  • 丟掉了影像邊緣位置的許多資訊。

為了解決這些問題,可以在卷積操作之前填充這幅影像。在這個案例中,你可以沿著影像邊緣再填充一層畫素。6×6的影像就被你填充成了一個8×8的影像。如果你用3×3的影像對這個8×8的影像卷積,你得到的輸出就是6×6的影像,一個尺寸和原始影像6×6的影像。

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

如果你想的話,也可以填充兩個畫素點,也就是說在這裡填充一層。實際上你還可以填充更多畫素。我這裡畫的這種情況,填充後 p = 2 p=2 p=2

在這裡插入圖片描述

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

Valid卷積意味著不填充。

Same卷積:那意味你填充後,輸出大小和輸入大小是一樣的。

習慣上,計算機視覺中, f f f通常是奇數,有兩個原因。

  • 其中一個可能是,如果 f f f是一個偶數,那麼你只能使用一些不對稱填充。只有 f f f是奇數的情況下,Same卷積才會有自然的填充,我們可以以同樣的數量填充四周,而不是左邊填充多一點,右邊填充少一點,這樣不對稱的填充。

  • 第二個原因是當你有一個奇數維過濾器,比如3×3或者5×5的,它就有一箇中心點。有時在計算機視覺裡,如果有一箇中心畫素點會更方便,便於指出過濾器的位置。

卷積步長(Strided convolutions)

在這裡插入圖片描述

如果你想用3×3的過濾器卷積這個7×7的影像,把步幅設定成了2,最後結果為91。

之前我們移動藍框的步長是1,現在移動的步長是2,我們讓過濾器跳過2個步長,注意一下左上角,這個點移動到其後兩格的點,跳過了一個位置。然後你還是將每個元素相乘並求和,你將會得到的結果是100。

現在我們繼續,將藍色框移動兩個步長,你將會得到83的結果。當你移動到下一行的時候,你也是使用步長2而不是步長1,所以我們將藍色框移動到這裡:

在這裡插入圖片描述

所以在這個例子中,我們用3×3的矩陣卷積一個7×7的矩陣,得到一個3×3的輸出。輸入和輸出的維度是由下面的公式決定的:

用一個 f × f f×f f×f的過濾器卷積一個 n × n n×n n×n的影像,padding為 p p p,步幅為 s s s,在這個例子中 s = 2 s=2 s=2,得到一個輸出 n + 2 p − f s + 1 × n + 2 p − f s + 1 \frac{n+2p - f}{s} + 1 \times \frac{n+2p - f}{s} + 1 sn+2pf+1×sn+2pf+1
在這裡插入圖片描述

在我們的這個例子裡, n = 7 n=7 n=7 p = 0 p=0 p=0 f = 3 f=3 f=3 s = 2 s=2 s=2   7 + 0 − 3 2 + 1 = 3 \ \frac{7 + 0 - 3}{2} + 1 =3  27+03+1=3,即3×3的輸出。

如果商不是一個整數怎麼辦?在這種情況下,我們向下取整。 ⌊ ⌋ ⌊ ⌋ 這是向下取整的符號,這也叫做對 z z z進行地板除(floor)。
這個原則實現的方式是,你只在藍框完全包括在影像或填充完的影像內部時,才對它進行運算。如果有任意一個藍框移動到了外面,那你就不要進行相乘操作。你的3×3的過濾器必須完全處於影像中或者填充之後的影像區域內才輸出相應結果。

總結一下維度情況,如果你有一個 n × n n×n n×n的矩陣或者 n × n n×n n×n的影像,與一個 f × f f×f f×f的矩陣卷積,或者說 f × f f×f f×f的過濾器。Padding是 p p p,步幅為 s s s沒輸出尺寸就是這樣:

在這裡插入圖片描述

可以選擇所有的數使結果是整數是挺不錯的,儘管一些時候,你不必這樣做,只要向下取整也就可以了。你也可以自己選擇一些 n n n f f f p p p s s s的值來驗證這個輸出尺寸的公式是對的。

其實,目前為止我們介紹的CNN卷積實際上計算的是相關係數,而不是數學意義上的卷積。但是,為了簡化計算,我們一般把CNN中的這種“相關係數”就稱作卷積運算。之所以可以這麼等效,是因為濾波器運算元一般是水平或垂直對稱的,180度旋轉影響不大;而且最終濾波器運算元需要通過CNN網路梯度下降演算法計算得到,旋轉部分可以看作是包含在CNN模型演算法中。總的來說,忽略旋轉運算可以大大提高CNN網路運算速度,而且不影響模型效能。

卷積運算服從結合律。

三維卷積(Convolutions over volumes)

現在看看如何執行卷積不僅僅在二維影像上,而是三維立體上。

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

在這裡插入圖片描述

給這些起個名字(原影像),這裡的第一個6代表影像高度,第二個6代表寬度,這個3代表通道的數目。同樣你的過濾器也有一個高,寬和通道數,並且影像的通道數必須和過濾器的通道數匹配。這個的輸出會是一個4×4的影像,注意是4×4×1,最後一個數不是3了。

我們研究下這背後的細節,首先先換一張好看的圖片。這個是6×6×3的影像,這個是3×3×3的過濾器,最後一個數字通道數必須和過濾器中的通道數相匹配。為了簡化這個3×3×3過濾器的影像,我們不把它畫成3個矩陣的堆疊,而畫成這樣,一個三維的立方體。

為了計算這個卷積操作的輸出,你要做的就是把這個3×3×3的過濾器先放到最左上角的位置,這個3×3×3的過濾器有27個數,27個引數就是3的立方。依次取這27個數,然後乘以相應的紅綠藍通道中的數字。先取紅色通道的前9個數字,然後是綠色通道,然後再是藍色通道,乘以左邊黃色立方體覆蓋的對應的27個數,然後把這些數都加起來,就得到了輸出的第一個數字。

如果要計算下一個輸出,你把這個立方體滑動一個單位,再與這27個數相乘,把它們都加起來,就得到了下一個輸出,以此類推。
在這裡插入圖片描述

舉個例子,這個過濾器是3×3×3的,如果你想檢測影像紅色通道的邊緣,那麼你可以將第一個過濾器設為 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\ \end{bmatrix} 111000111,和之前一樣,而綠色通道全為0, [ 0 0 0 0 0 0 0 0 0 ] \begin{bmatrix} 0& 0 & 0 \\ 0 &0 & 0 \\ 0 & 0 & 0 \\\end{bmatrix} 000000000,藍色也全為0。如果你把這三個堆疊在一起形成一個3×3×3的過濾器,那麼這就是一個檢測垂直邊界的過濾器,但只對紅色通道有用。

或者如果你不關心垂直邊界在哪個顏色通道里,那麼你可以用一個這樣的過濾器, [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\ \end{bmatrix} 111000111 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\ \end{bmatrix} 111000111 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix}1 & 0 & - 1 \\ 1 & 0 & - 1 \\ 1 & 0 & - 1 \\\end{bmatrix} 111000111,所有三個通道都是這樣。所以通過設定第二個過濾器引數,你就有了一個邊界檢測器,3×3×3的邊界檢測器,用來檢測任意顏色通道里的邊界。

按照計算機視覺的慣例,當你的輸入有特定的高寬和通道數時,你的過濾器可以有不同的高,不同的寬,但是必須一樣的通道數。理論上,我們的過濾器只關注紅色通道,或者只關注綠色或者藍色通道也是可行的。

再注意一下這個卷積立方體,一個6×6×6的輸入影像卷積上一個3×3×3的過濾器,得到一個4×4的二維輸出。

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

為了進行多個卷積運算,實現更多邊緣檢測,可以增加更多的濾波器組。例如設定第一個濾波器組實現垂直邊緣檢測,第二個濾波器組實現水平邊緣檢測。這樣,不同濾波器組卷積得到不同的輸出,個數由濾波器組決定。
在這裡插入圖片描述
若輸入圖片的尺寸為 n ∗ n ∗ n c n*n*n_c nnnc,filter尺寸為 f ∗ f ∗ n c f*f*n_c ffnc ,則卷積後的圖片尺寸為 ( n − f + 1 ) ∗ ( n − f + 1 ) ∗ n c ′ (n-f+1) *(n-f+1) *n_c' (nf+1)(nf+1)nc 。其中,$n_c $ 為圖片通道數目, n c ′ n_c' nc為濾波器組個數。

單層卷積網路(One layer of a convolutional network)

假設使用第一個過濾器進行卷積,得到第一個4×4矩陣。使用第二個過濾器進行卷積得到另外一個4×4矩陣。
在這裡插入圖片描述

最終各自形成一個卷積神經網路層,然後增加偏差,它是一個實數,通過Python的廣播機制。然後應用非線性函式ReLU,輸出結果是一個4×4矩陣。

對於第二個4×4矩陣,我們加上不同的偏差,它也是一個實數,16個數字都加上同一個實數,然後應用非線性啟用函式ReLU,最終得到另一個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]} z[1]=W[1]a[0]+b[1],其中 a [ 0 ] = x a^{[0]} =x a[0]=x,執行非線性函式 a [ 1 ] = g ( z [ 1 ] ) a^{[1]} = g(z^{[1]}) a[1]=g(z[1])。這裡的輸入是 a [ 0 ] a^{\left\lbrack 0\right\rbrack} a[0],也就是 x x x,這些過濾器用變數 W [ 1 ] W^{[1]} W[1]表示。在卷積過程中,我們對這27個數進行操作,其實是27×2,因為我們用了兩個過濾器,我們取這些數做乘法。實際執行了一個線性函式,得到一個4×4的矩陣。卷積操作的輸出結果是一個4×4的矩陣,它的作用類似於 W [ 1 ] a [ 0 ] W^{[1]}a^{[0]} W[1]a[0],也就是這兩個4×4矩陣的輸出結果,然後加上偏差。

這一部分(圖中藍色邊框標記的部分)就是應用啟用函式ReLU之前的值,它的作用類似於 z [ 1 ] z^{[1]} z[1],最後應用非線性函式,得到的這個4×4×2矩陣,成為神經網路的下一層,也就是啟用層。
在這裡插入圖片描述

這就是 a [ 0 ] a^{[0]} a[0] a [ 1 ] a^{[1]} a[1]的演變過程: 運用線性函式再加上偏差,然後應用啟用函式ReLU。這樣就通過神經網路的一層把一個6×6×3的維度 a [ 0 ] a^{[0]} a[0]演化為一個4×4×2維度的 a [ 1 ] a^{[1]} a[1],這就是卷積神經網路的一層。

示例中我們有兩個過濾器,也就是有兩個特徵,因此我們才最終得到一個4×4×2的輸出。但如果我們用了10個過濾器,而不是2個,我們最後會得到一個4×4×10維度的輸出影像.

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

在這裡插入圖片描述

這一層是卷積層,用 f [ l ] f^{[l]} f[l]表示過濾器大小,我們說過過濾器大小為 f × f f×f f×f,上標 [ l ] \lbrack l\rbrack [l]表示 l l l層中過濾器大小為 f × f f×f f×f。通常情況下,上標 [ l ] \lbrack l\rbrack [l]用來標記 l l l層。用 p [ l ] p^{[l]} p[l]來標記padding的數量,padding數量也可指定為一個valid卷積,即無padding。或是same卷積,即選定padding,如此一來,輸出和輸入圖片的高度和寬度就相同了。用 s [ l ] s^{[l]} s[l]標記步幅。

這一層的輸入會是某個維度的資料,表示為 n × n × n c n \times n \times n_{c} n×n×nc n c n_{c} nc某層上的顏色通道數。

增加上標 [ l − 1 ] \lbrack l -1\rbrack [l1],即 n [ l − 1 ] × n [ l − 1 ] × n c [ l − 1 ] n^{\left\lbrack l - 1 \right\rbrack} \times n^{\left\lbrack l -1 \right\rbrack} \times n_{c}^{\left\lbrack l - 1\right\rbrack} n[l1]×n[l1]×nc[l1],因為它是上一層的啟用值。

此例中,所用圖片的高度和寬度都一樣,但它們也有可能不同,所以分別用上下標 H H H W W W來標記,即 n H [ l − 1 ] × n W [ l − 1 ] × n c [ l − 1 ] 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} nH[l1]×nW[l1]×nc[l1]。那麼在第 l l l層,圖片大小為 n H [ l − 1 ] × n W [ l − 1 ] × n c [ l − 1 ] 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} nH[l1]×nW[l1]×nc[l1] l l l層的輸入就是上一層的輸出,因此上標要用 [ l − 1 ] \lbrack l - 1\rbrack [l1]。神經網路這一層中會有輸出,它本身會輸出影像。其大小為 n H [ l ] × n W [ l ] × n c [ l ] n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]} nH[l]×nW[l]×nc[l],這就是輸出影像的大小。

前面我們提到過,這個公式給出了輸出圖片的大小,至少給出了高度和寬度, ⌊ n + 2 p − f s + 1 ⌋ \lfloor\frac{n+2p - f}{s} + 1\rfloor sn+2pf+1(注意:( n + 2 p − f s + 1 ) \frac{n + 2p - f}{s} +1) sn+2pf+1)直接用這個運算結果,也可以向下取整)。在這個新表示式中, l l l層輸出影像的高度,即 n H [ l ] = ⌊ n H [ l − 1 ] + 2 p [ l ] − f [ l ] s [ l ] + 1 ⌋ n_{H}^{[l]} = \lfloor\frac{n_{H}^{\left\lbrack l - 1 \right\rbrack} +2p^{[l]} - f^{[l]}}{s^{[l]}} +1\rfloor nH[l]=s[l]nH[l1]+2p[l]f[l]+1,同樣我們可以計算出影像的寬度,用 W W W替換引數 H H H,即 n W [ l ] = ⌊ n W [ l − 1 ] + 2 p [ l ] − f [ l ] s [ l ] + 1 ⌋ n_{W}^{[l]} = \lfloor\frac{n_{W}^{\left\lbrack l - 1 \right\rbrack} +2p^{[l]} - f^{[l]}}{s^{[l]}} +1\rfloor nW[l]=s[l]nW[l1]+2p[l]f[l]+1,公式一樣,只要變化高度和寬度的引數我們便能計算輸出影像的高度或寬度。這就是由 n H [ l − 1 ] n_{H}^{\left\lbrack l - 1 \right\rbrack} nH[l1]推導 n H [ l ] n_{H}^{[l]} nH[l]以及 n W [ l − 1 ] n_{W}^{\left\lbrack l - 1\right\rbrack} nW[l1]推導 n W [ l ] n_{W}^{[l]} nW[l]的過程。

那麼通道數量又是什麼?這些數字從哪兒來的?輸出通道數量就是輸入通道數量,所以過濾器維度等於 f [ l ] × f [ l ] × n c [ l − 1 ] f^{[l]} \times f^{[l]} \times n_{c}^{\left\lbrack l - 1 \right\rbrack} f[l]×f[l]×nc[l1]

應用偏差和非線性函式之後,這一層的輸出等於它的啟用值 a [ l ] a^{[l]} a[l],也就是這個維度(輸出維度)。 a [ l ] a^{[l]} a[l]是一個三維體,即 n H [ l ] × n W [ l ] × n c [ l ] n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]} nH[l]×nW[l]×nc[l]。當你執行批量梯度下降或小批量梯度下降時,如果有 m m m個例子,就是有 m m m個啟用值的集合,那麼輸出 A [ l ] = m × n H [ l ] × n W [ l ] × n c [ l ] A^{[l]} = m \times n_{H}^{[l]} \times n_{W}^{[l]} \times n_{c}^{[l]} A[l]=m×nH[l]×nW[l]×nc[l]。如果採用批量梯度下降,變數的排列順序如下,首先是索引和訓練示例,然後是其它三個變數。

該如何確定權重引數,即引數W呢?過濾器的維度已知,為 f [ l ] × f [ l ] × n c [ l − 1 ] f^{[l]} \times f^{[l]} \times n_{c}^{[l - 1]} f[l]×f[l]×nc[l1],這只是一個過濾器的維度,有多少個過濾器,這( n c [ l ] n_{c}^{[l]} nc[l])是過濾器的數量,權重也就是所有過濾器的集合再乘以過濾器的總數量,即 f [ l ] × f [ l ] × n c [ l − 1 ] × n c [ l ] f^{[l]} \times f^{[l]} \times n_{c}^{[l - 1]} \times n_{c}^{[l]} f[l]×f[l]×nc[l1]×nc[l],損失數量L就是 l l l層中過濾器的個數。

最後我們看看偏差引數,每個過濾器都有一個偏差引數,它是一個實數。偏差包含了這些變數,它是該維度上的一個向量。為了方便,偏差在程式碼中表示為一個1×1×1× n c [ l ] n_{c}^{[l]} nc[l]的四維向量或四維張量。

在這裡插入圖片描述

池化層(Pooling layers)

除了卷積層,卷積網路也經常使用池化層來縮減模型的大小,提高計算速度,同時提高所提取特徵的魯棒性。
在這裡插入圖片描述

先舉一個池化層的例子,然後我們再討論池化層的必要性。假如輸入是一個4×4矩陣,用到的池化型別是最大池化(max pooling)。執行最大池化的樹池是一個2×2矩陣。

執行過程非常簡單,把4×4的輸入拆分成不同的區域,我把這個區域用不同顏色來標記。對於2×2的輸出,輸出的每個元素都是其對應顏色區域中的最大元素值。

因為我們使用的過濾器為2×2,最後輸出是9。然後向右移動2個步幅,計算出最大值2。然後是第二行,向下移動2步得到最大值6。最後向右移動3步,得到最大值3。這是一個2×2矩陣,即 f = 2 f=2 f=2,步幅是2,即 s = 2 s=2 s=2

最大化運算的實際作用就是,如果在過濾器中提取到某個特徵,那麼保留其最大值。如果沒有提取到這個特徵,可能在右上象限中不存在這個特徵,那麼其中的最大值也還是很小,這就是最大池化的直觀理解。

人們使用最大池化的主要原因是此方法在很多實驗中效果都很好。

其中一個有意思的特點就是,它有一組超引數,但並沒有引數需要學習。

另外還有一種型別的池化,平均池化,這種運算顧名思義,選取的不是每個過濾器的最大值,而是平均值。
在這裡插入圖片描述

目前來說,最大池化比平均池化更常用。

總結:
池化的超級引數包括過濾器大小 f f f和步幅 s s s,常用的引數值為 f = 2 f=2 f=2 s = 2 s=2 s=2,應用頻率非常高,其效果相當於高度和寬度縮減一半。
最大池化時,往往很少用到超引數padding. 輸入通道與輸出通道個數相同,因為我們對每個通道都做了池化。

池化過程中沒有需要學習的引數。執行反向傳播時,反向傳播沒有引數適用於最大池化。只有這些設定過的超引數,可能是手動設定的,也可能是通過交叉驗證設定的。

相關文章