【導讀】在計算機神經視覺技術的發展過程中,卷積神經網絡成為了其中的重要組成部分,本文對卷積神經網絡的數學原理進行了介紹。
文章包括四個主要内容:卷積、卷積層、池化層以及卷積神經網絡中的反向傳播原理。在卷積部分的介紹中,作者介紹了卷積的定義、有效卷積和相同卷積、跨步卷積、3D卷積。
在卷積層部分,作者闡述了連接配接切割和參數共享對降低網絡參數學習量的作用。在池化層部分,作者介紹了池化的含義以及掩膜的使用。

自動駕駛、智能醫療、智能零售,這些曾被認為不可能實作的事情,在計算機視覺技術的幫助下,終于在最近成為了現實。今天,自動駕駛和自動雜貨店的夢想不再像以前那樣遙不可及。
事實上,每天我們都在使用計算機視覺技術幫助我們用人臉解鎖手機,或者對即将釋出到社交媒體上的照片進行自動修飾。
在計算機視覺技術應用這一巨大成功的背後,卷積神經網絡(CNN)可能是其中最重要的組成部分。
在本文中,我們将逐漸了解,神經網絡是如何與 CNN 特有的思想協作的。本文章包含了相當複雜的數學方程式,但如果您對線性代數和微積分不熟悉,請不要氣餒。
我的目标不是讓您記住那些公式,而是讓您從直覺上去了解這些公式背後隐藏的意義。
01
前言
在之前的系列中,我們學習了密集連接配接的神經網絡(densely connected neural networks)。
這些網絡的神經元被分成組,形成連續的層,相鄰的兩個層之間的神經元互相連接配接。下圖展示了一個密集連接配接的神經網絡的示例。
Figure 1. Densely connected neural network architecture
當我們解決分類問題時,如果我們的特征是一組有限的并有明确定義的特征,這種方法是很有效的——例如,根據足球運動員在比賽期間所記錄的統計資料,預測該運動員的位置。
但是,當使用照片來進行預測時,情況會變得更加複雜。我們當然可以将每個像素的亮度視為一個單獨的特征,并将其作為輸入傳遞給我們的密集網絡(dense network)。
不幸的是,為了使神經網絡能夠處理典型的智能手機照片,該網絡必須包含數千萬甚至數億個神經元。
我們也可以通過縮小照片的尺寸來進行處理手機照片,但是這樣做會使我們丢失很多有價值的資訊。
可以發現,這種傳統政策的性能很差,是以我們需要一種新的、更加聰明的方法來盡可能多地使用資料,并同時減少必要的計算和參數的數量。CNN 閃亮登場的時候到了。
02
數字圖像的資料結構
首先花一點時間來解釋一下數字圖像的存儲方式。數字圖像實際上是巨大的數字矩陣。矩陣中的每個數字對應于其像素的亮度。
在 RGB 模型中,彩色圖像由三個矩陣組成,分别對應三個顔色通道——紅,綠,藍。而在黑白圖像中,我們隻需要一個矩陣。
矩陣中的每個數字的取值區間都是 0 到 255。該範圍是存儲圖像資訊的效率(256個值剛好适合1個位元組)與人眼的靈敏度(我們區分同種顔色的灰階級别的數量極限)之間的折衷。
Figure 2. Data structure behind digital images
03
卷積
核卷積(kernel convolution)不僅僅用于 CNN,它還是許多其他計算機視覺算法的關鍵要素。
核卷積就是将一個小數字矩陣(濾波器,也稱作 kernel 或 filter)在圖像上進行滑動,并根據 kernel 的值,對圖像矩陣的值進行轉換的過程。對圖像經過卷積操作後得到的輸出稱為特征映射(feature map)。
特征映射的值的計算公式如下,其中 f 代表輸入圖像,h 代表濾波器 。結果矩陣的行數和列數分别用 m 和 n 表示。
Figure 3. Kernel convolution example
将 kernel 放在標明的像素上後,我們從 kernel 中依次取出每個值,并将它們成對地與圖像中的相應值相乘。
最後,我們将每個核運算後的結果元素相加,并将求和結果放在輸出特征圖中的正确位置上。
上圖從微觀角度詳細地展示了這一運算的過程,但在完整圖像上實施該運算的結果可能更加有趣。圖4展示了使用幾個不同 kernel 的卷積結果。
Figure 4. Finding edges with kernel convolution
04
有效卷積&相同卷積(Valid and Same Convolution)
正如我們在圖3中看到的,當我們使用 3x3 的 kernel 對 6x6 圖像執行卷積時,我們得到 4x4 的特征映射。
這是因為在這個圖像中,隻有16個位置可以将 kerenl 完整地放在這張圖像中。由于每次執行卷積時我們的圖像都會縮小,是以在我們的圖像完全消失之前,我們隻能進行有限次數的卷積。
另外,如果對 kernel 在圖像中移動的過程進行觀察,我們就會發現圖像外圍像素的影響遠小于圖像中心像素的影響。
這樣會導緻我們失去圖像中包含的一些資訊。下圖展示了像素位置的改變對特征圖的影響。
Figure 5. Impact of pixel position
為了解決這兩個問題,我們可以使用額外的邊框來填充圖像(padding)。例如,如果使用 1像素進行填充,我們将圖像的大小增加到 8x8,是以使用 3x3 的 kernel 的卷積,其輸出尺寸将為 6x6 。
在實踐中,我們通常用零值來填充額外的邊界。根據是否使用填充,我們将處理兩種類型的卷積—— Valid 和 Same。
Valid —— 使用原始圖像,Same —— 使用原始圖像并使用它周圍的邊框,以便使輸入和輸出的圖像大小相同。
在第二種情況下,填充寬度應滿足以下等式,其中 p 是填充尺寸,f 是 kernel 尺寸(通常是奇數)。
05
跨步卷積(Strided Convolution)
Figure 6. Example of strided convolution
在前面的例子中,我們總是每次将 kernel 移動一個像素,即步長為1。步長也可以視為卷積層的超參數之一。
圖 6 展示了使用更大步長時的卷積運算。在設計 CNN 架構時,如果希望感覺域重疊較少,或者希望讓特征圖的空間次元更小,我們可以增加步長。
輸出矩陣的尺寸(考慮填充和步長時)可以使用以下公式計算。
06
過渡到第三個次元
體積卷積(Convolution over volume)是一個非常重要的概念,這不僅使我們能夠處理彩色圖像,而且更為重要的是,我們能夠在單層網絡中使用多個 kernel 。
第一個規則是 kernel 和圖像必須具有相同數量的通道。一般而言,圖像的處理過程和圖3的示例非常相似,但是這次我們是将三維空間中的值對相乘。
如果想在同一個圖像上使用多個 kernel,首先我們要分别對每個 kernel 執行卷積,然後将結果從頂層向下進行疊加,最後将它們組合成一個整體。
輸出張量的尺寸(可以稱為3D矩陣)滿足以下等式,其中:n - 圖像大小,f - 濾波器大小,nc - 圖像中的通道數,p - 填充大小,s - 步幅大小,nf - kernel 的數量。
Figure 7. Convolution over volume
07
卷積層
接下來我們将用前面學到的知識來建構 CNN 的一個層。我們将要用到的方法幾乎與建構密集神經網絡時用到的相同,唯一有差別的地方是,我們不再使用簡單的矩陣乘法,而是使用卷積。
前向傳播包括兩個步驟。第一步是計算中間值 Z:首先将前一層的輸入資料與張量 W(包含濾波器)進行卷積,然後将運算後的結果加上偏差 b 。
第二步是将中間值 Z 輸入到非線性激活函數中(使用 g 表示該激活函數)。下面展示了矩陣形式的數學公式。
如果您對公式中的任何部分不太清楚,我強烈推薦您去閱讀一下我之前的文章,文中詳細讨論了密集連接配接的神經網絡的具體内容。
下文的插圖很好地展示了公式中各張量的維數,以助于了解。
Figure 8. Tensors dimensions
連接配接切割和參數共享(Connections Cutting and Parameters Sharing)
在本文的開頭曾提到,由于需要學習大量的參數,密集連接配接的神經網絡在處理圖像方面的能力很差,而卷積卻為該問題提供了一種解決方案,下面我們一起來看看卷積是如何優化圖像處理的計算的。
在下圖中,我們用一種略微不同的方式對 2D 卷積進行了可視化——用數字 1-9 标記的神經元構成輸入層,用于接收輸入圖像的像素亮度,單元 A-D 表示經過卷積計算後得到的特征映射。
最後,I-IV 表示來自 kernel 的後續值,這些值是需要網絡進行學習的。
Figure 9. Connections cutting and parameters sharing
現在,讓我們關注卷積層的兩個非常重要的屬性。第一,從圖中可以看到,并非兩個相鄰層中的所有神經元都互相連接配接。
例如,神經元 1 僅影響 A 的值。第二,我們可以發現一些神經元使用了相同的權重。這兩個屬性意味着在 CNN 中我們需要學習的參數要少得多。
值得一提的是,kernel 中的任一單值都會影響輸出特征映射的每一個元素——這在反向傳播的過程中是至關重要的。
08
卷積層的反向傳播(Convolutional Layer Backpropagation)
任何曾經試圖從頭開始編寫神經網絡的人都知道,前向傳播還不到最終成功的一半。當你開始向回推算時,真正的樂趣才剛剛開始。
如今,我們不需要為反向傳播而煩惱——因為深度學習架構已經為我們做好了,但是我覺得有必要弄明白它背後發生的事情。
就像在密集連接配接的神經網絡中一樣,我們的目标是計算導數,然後在梯度下降的過程中,用這些導數去更新我們的參數值。
在下面的計算中,我們将用到鍊式法則 —— 這在我之前的文章中提到過。我們想要評估參數的變化對結果特征映射的影響,以及随之對最終結果的影響。
在開始詳細讨論之前,我們需要将數學符号統一 —— 為了表示友善,我不會使用偏導數的完整符号,而是用下面提到的縮符号。
但是請記住,當我使用這種表示法時,這将始終代表着成本函數的偏導。
Figure 10. Input and output data for a single convolution layer in forward and backward propagation
我們的任務是計算 dW [1] 和 db [l] (它們是與目前層參數相關的導數),以及 dA[l-1](它将被傳遞給前一層)。
如圖10所示,dA[l] 作為輸入,張量 dW 和 W,db 和 b 以及 dA 和 A 的次元分别相同。第一步是求激活函數關于輸入張量的導數,将其結果記為 dZ [1] 。根據鍊式法則,該運算的結果将在後面用到。
現在,我們需要處理卷積自身的反向傳播。為了實作這個目标,我們将利用一個稱為全卷積的矩陣運算,該運算的可視化解釋如下圖所示。
請注意,在此過程中我們要使用 kernel,而我們之前用到的 kernel 是該 kernel 旋轉了180度所得到的。
該操作可以用以下公式表示,其中 kernel 由 W 表示,dZ[m,n] 是一個标量,該标量屬于從前一層所獲得的偏導數。
Figure 11. Full convolution
09
池化層(Pooling Layers)
除了卷積層之外,CNN 經常使用一個稱為池化層的網絡層,它們主要用于減小張量的大小并加快計算速度。
這個層的結構很簡單,我們隻需要将圖像劃分成不同的區域,然後對每個部分執行一些操作即可。
例如,對于最大池化層(Max Pool Layer),我們從每個區域中選擇一個最大值,并将其放在輸出中的相應位置即可。
與卷積層的情況一樣,我們有兩個超參數——kernel 的尺寸和步長。
最後值得一提是,如果要為多通道圖像執行池化操作,則每個通道都應該分别執行池化操作。
Figure 12. Max pooling example
10
池化層的反向傳播(Pooling Layers Backpropagation)
在本文中,我們僅讨論最大池化的反向傳播(max pooling backpropagation),但是通過将該方法稍作調整,便可運用到其他所有類型的池化層。
由于在池化層這種類型的層中,我們不用更新任何參數,我們的任務隻是适度地配置設定梯度值。
前文講到,在最大池化的前向傳播中,我們從每個區域中選擇最大值并将它們傳輸到下一層。
是以很明顯,在反向傳播期間,梯度不會影響未在前向傳播中使用的矩陣元素。
在實際操作中,該過程是通過建立一個掩膜(mask)來實作的,該掩膜會記住在前向傳播中所使用的元素的位置,随後我們就可以用該掩膜來傳遞梯度。
Figure 13. Max pooling backward pass
文章轉載至:https://blog.csdn.net/guleileo/article/details/89484970