卷積的動作只有一個:把 3×3 的 kernel(也叫 filter)蓋在圖上某個位置,9 個像素各乘上 kernel 對應的數字,加起來,寫進輸出的那一格。然後往右移一格,再做一次。整張圖做完,得到一張新的圖,叫 feature map。kernel 長什麼樣,feature map 就把什麼樣的圖案「點亮」。電腦視覺很早就用手寫的 kernel 找邊緣,例如 Sobel。下面這張 48×48 的圖是程式畫的:有直線、一條「\」方向的細斜線、斜邊、圓、格紋。
找影像特徵 = convolution filter:講義用 Sobel edge filter 說明「一個 filter 可以看成一個 pattern」,接著問:filter 能不能自動學?這就是深度學習的切入點。
講義的 6×6 例子:一張 0 和 1 的 6×6 圖,Filter 1 是對角線為 1、其他為 −1 的 3×3。stride 1 時,左上角第一格算出 3(對角線三個 1 全對上),往右一格是 −1。整張圖做完得到 4×4 的 feature map。Filter 2(中間一直行為 1)再做一次,得到第二張 4×4。每個 filter 各產生一張 feature map,疊在一起就是新圖的 channel。上面的「講義 Filter 1」鈕就是這個 kernel,可以看它只在右上那條「\」方向的細斜線上最亮。
Translation equivariance:先平移再卷積,等於先卷積再平移,Conv(Translate(X)) = Translate(Conv(X))。圖案搬到哪裡,feature map 上的反應就跟著搬到哪裡。講義提醒:卷積只對平移有這個性質,旋轉和縮放要靠別的機制,講義舉的例子是 pooling。
為什麼叫「卷積」:數學上的 convolution 會把 kernel 先翻轉再乘;深度學習框架實際做的是不翻轉的 cross-correlation。kernel 是學出來的,翻不翻沒有差別,所以大家都叫它卷積。
講義算過一筆帳:一張 300×300 的彩色圖拉直是 270,000 個數字,只接到 100 個神經元,就要 27 × 106 個權重。卷積只看一小塊(sparse connection),而且同一組權重到處用(shared weights),所以權重數量和圖多大無關,只和 kernel 大小、輸入輸出的 channel 數有關。下面拉滑桿,看輸出尺寸公式和參數量怎麼變。
全連接的兩個問題:一是權重太多,訓練時間太長;300×300×3 接 100 個神經元就是 27 × 106。二是它不利用空間結構:拉直之後,相鄰像素和相距很遠的像素地位一樣,左上角的圖形跟右下角的圖形被當成一樣有關係。物體移動或縮放之後,同一個物體落到不同的權重上,等於要重新學一次。
講義的總結:卷積用三個想法改善學習。Sparse interactions:kernel 比輸入小,參數和計算都少。Parameter sharing:同一個 kernel 用在每個位置;推論時間不會因此變短,但記憶體只要存 K 個 filter。Equivariant representation:輸入平移,輸出跟著平移。另外,卷積可以吃不同大小的輸入,全連接的輸入大小是固定的。
彩色影像:kernel 永遠延伸到輸入的整個深度。32×32×3 的圖配 5×5×3 的 filter,每個位置是一次 5·5·3 = 75 維的內積再加 bias。一個 filter 產生一張 feature map;10 個 filter 就是 10 個 channel。所以參數量是 k·k·C_in·C_out + C_out。
1×1 conv:k = 1 時,卷積在空間上什麼都不混,只在 depth 方向運算:每個位置把 C_in 個數字做一次內積,變成 C_out 個。它是在每個像素上各跑一個小的全連接層,常用來改 channel 數。
FC-conv:卷積層是全連接層的特例(把沒連到的權重設成 0、共享的權重綁在一起)。反過來,全連接層也能寫成卷積,講義給兩種寫法:用和輸入 feature map 一樣大的 kernel,或先攤平再用多個 channel 的 1×1 conv。這讓整個網路可以只用卷積寫成,吃任意大小的圖。
第一層的一格只看得到 3×3。第二層的一格看的是第一層的 3×3,而第一層每格又看 3×3,所以回推到原圖是 5×5。這個「影響輸出值的輸入範圍」叫 receptive field。講義的公式:兩層 3×3 是 (3 − 1) + (3 − 1) + 1 = 5。下面的格子是原圖,橘框是理論範圍,顏色是每個輸入像素有幾條路徑通到中心那一格輸出。
為什麼重要:在語意分割和光流這類「每個像素都要輸出答案」的任務,每個輸出格最好能看到整個相關物體;在物件偵測,太小的感受野認不出大物體,所以常用多尺度的做法。講義引用的觀察:分類準確率和感受野大小呈對數關係,大的感受野是高階辨識的必要條件,但報酬遞減。
Effective receptive field(Luo et al. 2016):感受野裡每個像素的貢獻不一樣。forward 時,中心像素有很多條路徑把資訊送到輸出,外圍只有很少;backward 時,中心像素拿到的梯度也大得多。沒有非線性時,分佈就是一個 2D 高斯;加了 ReLU 會偏離高斯。講義的重點:ERF 長得比理論慢很多;訓練之後 ERF 會變大一些。Pooling 和 dilated convolution 是快速放大的有效方法。
Dilated convolution:不是在滑動時跳格,而是在 kernel 的格子之間留空。1D 例子:一般是 w[0]x[0] + w[1]x[1] + w[2]x[2];中間空一格就變成 w[0]x[0] + w[1]x[2] + w[2]x[4]。等效 kernel 大小 k′ = d(k − 1) + 1,3×3 配 d = 2 的範圍等於 5×5,只用 9 個權重。逐層 1、2、4 疊三層,範圍是 3、7、15,指數長大但參數線性長大,而且不像 pooling 那樣把 feature map 縮小、丟掉資訊,所以適合語意分割。缺點:計算量高;全部用同一個 dilation 會有 gridding effect,常見的修法是用沒有公因數的鋸齒狀 dilation,例如 1, 2, 5。
對回原圖:第一層的感受野就是 kernel 大小;更深層取決於前面所有層的 kernel 和 stride。feature map 上一格對應到原圖並不唯一,SPP-net 的做法是對到感受野的中心。
CNN 的基本骨架是「卷積 → pooling → 卷積 → pooling → 攤平 → 全連接」,可以重複很多次。Pooling 沒有權重:把 feature map 切成 2×2 的小塊,每塊只留一個數。Max pooling 留最大的,average pooling 留平均。結果是一張比較小的新圖,channel 數不變。改下面 4×4 的數字(0 到 9),或按「只有一個亮點」再按「整塊右移一格」,看位置偏一點時輸出變不變。
Max vs average:講義備註整理了一個解釋。特徵提取的誤差主要有兩種:鄰域太小造成的估計變異變大,和卷積參數誤差造成的平均值偏移。Average pooling 減少第一種,保留比較多背景資訊;max pooling 減少第二種,保留比較多紋理資訊。講義的結論:max pooling 表現比較好,比較常用。Pooling 的目的也不只是減少特徵和參數,而是保持某種不變性(平移、小幅縮放)。
All convolutional network(Striving for Simplicity,講義用 CIFAR-10 的結果說明):把 pooling 換成 stride 2 的卷積,讓「縮小」這件事也變成可以學的。結果不比有 pooling 的網路差,整個網路只剩卷積。
Global average pooling:每個 channel 的整張 feature map 平均成一個數,C 個 channel 就變成長度 C 的向量,直接接分類器。講義的重點是它省下大部分參數:攤平後接全連接的權重數會乘上 feature map 的面積,GAP 不會。它也讓網路吃任意大小的圖。
CNN 學到什麼:線性分類器是「每類一張模板」(A1),MLP 是「一堆整張圖的模板」,而卷積的第一層是局部的小模板,常常學成方向不同的邊緣和相反的顏色對比;講義的例子是 AlexNet 第一層 64 個 3×11×11 的 filter。越往後越抽象,是一層一層組合起來的 hierarchical feature representation。至於「越深越好嗎」,那是 C2 的題目。
這個模組最常被講錯的幾句話。