卷積運算
想像把一個小型模板(一格一格的權重網格)滑過一張影像。每停一格,你就把模板底下的數字乘上模板的權重、加總成一個數字、寫下來,再滑一格、重複。你寫出來的那張數字網格就是卷積運算的結果。模板很小(例如 3x3),但你在每個位置都重複使用它,因此它就像一個圖樣偵測器,在輸入的每一個位置都問同一個問題:「我的圖樣出現在這裡了嗎?」
具體而言,對一張 2D 輸入 I 與一個大小為 k 乘 k 的卷積核 K,位置 (i, j) 的輸出為 O[i,j] = 對 m、n 的總和 I[i+m, j+n] 乘以 K[m,n],總和範圍是卷積核所覆蓋的區域。因此每一個輸出值都是卷積核與它當下所覆蓋之輸入區塊之間的「局部加權和」,也就是一次內積(dot product)。對多通道輸入(例如一張照片的紅、綠、藍三個平面)而言,總和也會跨通道進行,所以單一卷積核其實是一個小型 3D 張量,並且仍然在每個空間位置產生一個純量。這個滑動內積是 CNN 內部重複次數最多的算術運算,這也是為何硬體(GPU、TPU 內的脈動陣列)會被設計成能高速執行它。
有兩個精確的性質讓卷積成為處理影像的正確工具。它是線性的,意思是輸出只是輸入的加權和、沒有任何彎曲——這正是為何之後要再套上像 ReLU 這樣的非線性函數,否則把多層卷積疊起來會塌縮成一個大的線性映射。它也是平移等變(shift-equivariant)的:把輸入圖樣移動,回應也會跟著移動,因為同一個卷積核被套用在每一個位置。若沒有非線性、也沒有深度,單純的卷積只是一個固定的局部濾波器;真正的威力來自學習這些權重並堆疊許多這樣的層。
把一個固定的 3x3 垂直邊緣卷積核 [ [-1,0,1],[-1,0,1],[-1,0,1]] 滑過照片:在「由暗到亮」的垂直邊緣處會得到很大的正值回應,在平坦區域接近零,在「由亮到暗」的邊緣處則得到很大的負值回應。
陷阱:深度學習框架所稱的「卷積」在數學上其實是互相關(cross-correlation)。真正的訊號處理卷積會先把卷積核翻轉(O[i,j] = I[i-m, j-n] K[m,n] 的總和)。由於權重是學出來的,翻轉與否在實務上沒有差別——網路只會學出翻轉後的卷積核——所以函式庫就省略了它。當教科書公式裡有負號、而你的程式碼沒有時,不要被搞混。