最全動畫詮釋各種卷積網絡及實現機制

3年前開發移動端卷積神經網絡SDK,使用GPU實現卷積神經網絡的各種算子,Android/iOS雙端都實現了,性能非常不錯,實時風格畫和實時摳圖接近50FPS,今天無意中翻到當初的筆記才發現好久沒碰AI了,於是彙總下當做記錄,也希望能對大家有所幫助。

卷積神經網絡

下面這個是LeNet, 最早的卷積神經網絡之一

卷積神經網絡其實和傳統神經網絡是一脈相承的,只不過多了很多元素,比如激勵層(非線性), 卷積層(提煉特徵)等等. 卷積網絡計算過程的動畫如下

卷積

原理

卷積有兩個部分,一個圖像一個是卷積核,卷積覈對圖像做平移卷積計算輸出新的圖像的過程就是卷積,我們來看下一個卷積過程的動畫。

其實圖像的卷積和信號系統中的卷積有類似性。我們知道信號系統中,卷積的定義如下

卷積的過程就是把其中一個函數翻轉後平移做乘法計算各個點的卷積值。那麼在圖像上卷積核就是g(x, y), 圖像是f(x, y), 理論上就需要對卷積核g(x,y)進行上下左右翻轉,但是我們在實際操作的時候爲啥沒有做翻轉的動作呢?這是因爲我們在training卷積神經網絡時,初始卷積核是一個隨機值/0值,卷積核的值是整個系統training的過程的產生的。既然初始值是隨機的,是否翻轉沒有意義,最後整個系統損失函數值最小時得到的卷積核本質上就是翻轉後的值的。從效果上說,卷積核可以看成是圖像濾波器。

卷積過程動畫

卷積神經網絡的卷積具體計算就是卷積核和圖像的值進行點積運算,得到相應的像素點的值。卷積相關的參數有padding, stride,卷積核大小,各種情況下的卷積過程如下動畫所示。

 

        

  • 單輸入單輸出通道卷積過程的動畫如下

  • 帶padding的單輸入單輸出通道卷積過程的動畫如下

  • 多輸入通道單輸出通道卷積

  • 多輸入通道多輸出通道卷積

  • 輸出圖片大小計算

 

卷積往往會降低圖片的大小,降維採集特徵,屬於下采樣的一種,輸出圖像大小和這些參數關係如下:

  • 輸入圖片大小W

  • 卷積核大小F

  • Padding大小P

  • Strides大小S

  • 輸出圖像大小

N = (W − F + 2P )/S+1

實踐中Padding往往是深度學習平臺自動算出來,比如Tensorflow提供了兩種Padding模式,valid和same模式。valid模式下padding=0, 可能會有部分像素不參與卷積,same模式下通過周圍補0來讓所有像素都能參與卷積,平臺會自動算出Padding值,這兩種模式下對應的輸出圖片大小如下:

  • Same模式

  • out_height = ceil(float(in_height) / float(strides[1]))

  • out_width = ceil(float(in_width) / float(strides[2]))

  • Valid模式

  • out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))

  • out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))

輸出圖片的通道數量

輸出圖片的通道數量等於卷積核的輸出通道量

  • 輸入圖片的shape: [inChannels, width, height] 

  • 卷積核的shape: [outChannels, inChannels, width, height]

  • 輸出圖片的shape: [outChannels, outWidth, outHeight]

池化

池化也是一種下采樣技術

反捲積

反捲積是一種上採樣技術, 用來升維還原作用,  比如摳圖需要還原出原始圖像大小的Mask。反捲積的計算過程和卷積差不多, 只不過它通過補零的方式擴大了原始圖像然後再卷積, 最終結果是輸出圖片變大, 執行動畫如下

Metal卷積代碼實現分析

Shape

下面的代碼會涉及到Shape,我們以一段代碼來同步我們這裏的shape的概念。

x = np.array([[1,2,5],[2,3,5],[3,4,5],[2,3,6]])
#輸出數組的行和列數
print x.shape  #結果: (4, 3)

Metal裏的圖片數據存儲結構

  • 一般圖像的數據內存結構對應的shape是[height, weight, channel], 比如RGB的圖片就是[height, weight, 3], RGBA就是[height, weight, 4]。當然爲了兼容,圖片數據的數據可以都維持爲[height, weight, 4],多餘的channel填充爲0即可。

  • 考慮到CNN網絡中的隱藏層的通道數量遠不4,可以進一步將channel分解爲4及slice(4的倍數), 形成這樣的shape: [height, weight, slices, 4],  通道總數=slices*4。

  •  由於Metal中的texture的一個像素單元可以定義爲float4類型數據,所以texture的實際維數爲3維:[height, weight, slices]。對於Metal texture來說,可以定義type2dArray,可以將slices這一維度放置到_numberOfImages,  當_numberOfImages大於1時就需要type2dArray類型的texture。

  • 具體一個像素的format可以根據像素的佔用的空間大小來確定,比如421格式可以定義爲rgba16float格式。

 

  • 對於卷積核weight來說,它的數據結構是[outChannels, height, width, slices, 4],其實爲了和輸入圖片一致,這個卷積核以[outChannels, slices, height, width, 4]方式組織更容易理解,但是考慮到卷積核數據導出維護角度, 暫時使用了[outChannels, height, width, slices, 4]這種shape。同時卷積核一般以buffer方式存儲和傳遞,而buffer裏的數據單元也可以定義爲float4, 因而卷積核在buffer中的存在維數是4維[outChannels, height, width, slices]。由卷積的具體算法可知,輸入數據[height, weight, slices]和卷積核[outChannels, height, width, slices]卷積得到的輸出圖片的shape是[outChannels, height, width],但由於輸出圖片一般保存在texture裏的,而texture的基本像素是float4, 因而真正的輸出shape應該是如此結構[outChannels/4, height, width, 4], 所以輸出texture的真正shape是[outSlices, height, width](outSlices= outChannels/4)。所以爲了方便計算,卷積核的邏輯shape可以看成是[outSlices, 4,  height, width, slices]。

代碼實現分析

 

下面我們來看下通過Metal的Compute Shader怎樣實現3x3卷積的


系列好文:
【深入理解iOS GPU加速框架Metal及MPS】

/**************************************************
* 本文來自CSDN博主"一點碼客",喜歡請頂部點擊關注
* 轉載請標明出處:http://blog.csdn.net/itchosen
***************************************************/

如需實時查看更多更新文章,請關注公衆號"一點碼客",一起探索技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章