深度學習-conv卷積


過濾器(卷積核)

傳統的圖像過濾器算子有以下幾種:

  • blur kernel:減少相鄰像素的差異,使圖像變平滑。
  • sobel:顯示相鄰元素在特定方向上的差異。
  • sharpen :強化相鄰像素的差異,使圖片看起來更生動。
  • outline:也稱為edge kernel,相鄰像素相似亮度的像素點設成黑,有較大差異的設為白。

更多可參考 image-kernels 在線演示不同的卷積過濾器。

CNN 卷積層

CNN做的事情不是提前決定好過濾器,而是把過濾器當成參數不斷調整學習,學出合適的過濾器。卷積網絡的第一層執行的通常都是邊緣檢測,后面的層得到的都是更抽象的特征。CNN 的卷積核可以看作是局部區域內的全連接. 卷積層的一個重要特性是權值共享.

權值共享: 不同的感受域共享同一權值,因此也稱為filter,能夠大大減少權重的數量(所占的內存),這通常是有效的,因為filter過濾某一特征與具體的空間位置無關.但無獨有偶,人臉圖片通常是中心化的,即人的腦袋比較靠近中間,如此可以看出位置信息是有用的.對於這種情形我們可以取消權值共享機制,此時稱這一層為Locally-Connected Layer.這在人臉識別的論文中比較常用.

參數量: C_in × C_out × kernel_h × kernel_w

誤區: 我之前誤認為卷積的參數量是 C_out × kernel_h × kernel_w, 如果將卷積層設計為輸入的所有channel的特征圖共享一個filter, 那么相當於將輸入的channel壓縮成1個(特征圖相加)再與C_out個filter卷積. 這種方式參數量和計算量比較小,但網絡性能可能較低.

有時候提到filter的長和寬大小而不提到深度,則深度是輸入數據的整個深度(因此1x1的卷積核也是有意義的).如前一層的輸入是 [16x16x20],感知域大小是3x3,那么卷積層中每個神經元將有3x3x20 = 180個到前一層的連接.

小卷積核

現在流行的網絡結構設計多遵循小卷積核的設計原則, 小卷積核的優勢:
3個3x3的卷積核的累加相當於1個7x7的卷積核,但是參數更少,計算量更小,有更多的非線性層計算.還可以通過加入1x1的"bottleneck"卷積核進一步減少計算(GoogLeNet等大量運用這種方式加深層次).如輸入HxWxC經過下列步驟輸出的維數不變:

\[\require{AMScd} \begin{CD} H\times W\times C @>{\text{Conv 1x1 x C/2}}>> H\times W\times C/2 \\ @. @V {\text{Conv 3x3 x C/2}} VV \\ H\times W\times C @< \text{Conv 1x1 x C} << H\times W\times C/2 \end{CD} \]

然而上述步驟中仍然使用了3x3卷積核,可以將其轉成1x3與3x1的連接.

輸入輸出尺度關系:

\[o=\lfloor{i+2p-k\over s}\rfloor+1 \]

孔洞卷積/膨脹卷積

deeplab 論文 Rethinking Atrous Convolution for Semantic Image Segmentation 中提到 "Atrous convolution, also known as dilated convolution".

Dilated/Atrous Convolution 或者是 Convolution with holes 從字面上就很好理解,是在標准的 convolution 中注入空洞,以此來增加感受野。相比沒有孔洞的卷積,dilated convolution 多了一個 dilation rate 超參數, 指的是 kernel 的間隙(無孔洞的卷積 dilation rate 是 1)。

(https://pic2.zhimg.com/50/v2-4959201e816888c6648f2e78cccfd253_hd.gif)

孔洞卷積輸入輸出尺度關系:

\[o=\lfloor{i+2p-[(k-1)d+1] \over s}\rfloor+1 \]

d是 dilation rate, 在kernel中加入了d-1個孔,相當於擴大了卷積核的覆蓋面積,k'=k+(k-1)(d-1).

孔洞卷積應用

在 R-FCN 和 SSD 等目標檢測網絡中也用到了 atrous conv, R-FCN 將原本的ImageNet的預訓練模型的某層stride=2的卷積改為stride=1使得輸出尺度不進行縮小,由於stride=1的感受野較小,因此使用atrous來增大感受野. 同時能夠繼續使用ImageNet預訓練分類模型.SSD將全連接層fc6和fc7改成了卷積層,並從fc6和fc7參數中下采樣.將pool5從2x2-s2改成3x3-s1,同樣使用atrous conv來填充孔洞,增加感受野.

atrous conv 能夠使用原來的參數初始化是因為 atrous conv 的神經元連接和原來的仍然一樣,如下圖所示[1], 紅色的輸出神經元對應的輸入(第一層)的神經元在(a)(b)中相同:

atrous conv

卷積實現

卷積有三種主流的計算方式:轉化為矩陣乘,winograd,和FFT。

三種計算方式在 CuDNN 中均做了實現[2]
CuDNN-Conv

在現代的 DL 框架中對卷積計算通常采用矩陣乘法的方式,使用im2col操作將輸入數據與權重展開成二維矩陣(使得圖像矩陣和卷積核能夠直接相乘, 轉換的反向操作為col2im),運用 BLAS API進行高效計算,缺點是占用許多內存.這種思想也可以用在pooling操作中.

沒有廣泛使用FFT的原因:
FFT 在卷積核比較大的時候有明顯速度優勢, 但是FFT卷積沒有被廣泛應用。因為通用平台上有更合適的Winograd卷積的存在,而專用平台上直接降低運算精度是更合適的方案。而且,隨着CNN里面越來越多的1×1卷積和depthwise卷積被加入,Winograd卷積的價值也越來越小了。CNN的卷積核一般都小於5,所以深度學習中一般不用FFT。[3]

下邊簡單介紹下快速傅里葉變換.

卷積定理(convolution theorem) [4][5]

快速傅里葉變換被稱為20世紀最重要的算法之一, 一個因素就是卷積定理.
傅里葉變換可以看作是對圖像或者音頻等數據的重新組織,它將時域和空域上的復雜卷積對應到了頻域中的元素間簡單的乘積。
一維連續域上兩個連續函數的卷積:

\[h(x)=f\bigotimes g=\int_{-\infty}^\infty f(x-u)g(u)du=\mathcal F^{-1}(\sqrt{2\pi}\mathcal F[f]\mathcal F[g]) \]

由卷積定理可以知道,兩個矩陣卷積的結果等價於兩個矩陣經過傅里葉變換(\(\mathcal F\)),進行元素級別相乘,再經過傅里葉逆變換(\(\mathcal F^{-1}\)). \(\sqrt{2\pi}\)是一個normalizer.

二維離散域(圖像)上的卷積:

\[\begin{align} \text{feature map}=&\text{intput}\bigotimes\text{kernel} \\ =&\sum_{y=0}^M \sum_{x=0}^N \text{intput}(x-a,y-b)\cdot \text{kernel}(x,y) \\ =&\mathcal F^{-1}(\sqrt{2\pi}\mathcal F[\text{intput}]\mathcal F[\text{kernel}]) \end{align} \]

快速傅里葉變換是一種將時域和空域中的數據轉換到頻域上去的算法。傅里葉變換用一些正弦和余弦波的和來表示原函數。必須注意的是,傅里葉變換一般涉及到復數,也就是說一個實數被變換為一個具有實部和虛部的復數。通常虛部只在一部分領域有用,比如將頻域變換回到時域和空域上.

傅里葉變換圖示[6]
fft

從傅里葉變換中可以看出方向信息:
FFT-orientation
Images by Fisher & Koryllos (1998). Source

caffe中的卷積實現

卷積操作示意圖如下,輸入圖片的維數為[c0,h0,w0];卷積核的維數為[c1,c0,hk,wk],其中c0在圖中沒有表示出來,一個卷積核可以看成由c1個維數為[c0,hk,wk]的三維濾波器組成,輸出特征的維數為[c1,h1,w1], 其中(h1,w1)根據輸入尺寸(h0,w0)及卷積核尺寸(hk,wk),卷積核步長stride計算得出.

conv

轉成二維矩陣乘法的高效計算:
im2col

更詳細的im2col圖示:
im2col-detail

卷積-反向傳播

卷積層的反向傳播依然可以用到卷積.[7]
設卷積層為 \(Y=X\odot W\), im2col 的形式是 \(Y=X'\odot W'\) , 那么

\[\begin{align} {\partial L\over \partial W} &=X\odot{\partial L\over \partial Y} \\ {\partial L\over \partial X} &=\rm{Full Conv}(180^\circ\text{rotated W},{\partial L\over \partial Y}) \\ {\partial L\over \partial X'} &={\partial L\over \partial Y}\odot W' \\ {\partial L\over \partial X} &=\text{col2im}({\partial L\over \partial X'}) \end{align} \]


  1. 孔洞卷積: https://blog.csdn.net/z1102252970/article/details/70548412 ↩︎

  2. http://www.telesens.co/2018/04/09/initializing-weights-for-the-convolutional-and-fully-connected-layers/ ↩︎

  3. https://www.zhihu.com/question/264307400 ↩︎

  4. http://www.hankcs.com/ml/understanding-the-convolution-in-deep-learning.html ↩︎

  5. http://timdettmers.com/2015/03/26/convolution-deep-learning/ ↩︎

  6. http://commons.wikimedia.org/wiki/File:Fourier_transform_time_and_frequency_domains.gif ↩︎

  7. https://medium.com/@pavisj/convolutions-and-backpropagations-46026a8f5d2c ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM