關於Matconvnet中Conv-ReLU-Pool-NormBatch的總結與思考

最近一直在思考是出國還是找工作的事,和三年前一樣又到了做決定的時候。真的很心累,撿起了我的MatConvNet,重新看一了一下牛津派的編程藝術。只有沉浸式的工作,才能安靜下來吧。

1. vl_nncov - CNN的卷積操作

Y = VL_NNCONV(X, F, B)計算圖像X與濾波器組F/偏置B之間的卷積操作。如果B是一個空矩陣,就是沒有偏置參與;如果F是一個空矩陣,圖像並不進行卷積操作,但是仍然會執行添加偏置B、下采樣stride、以及邊緣補充padding。

  • X 圖像是一個四維數據結構 =  H x W x C x N。其中 (H,W) 是一個圖像通道的寬度和高度。 C 是特徵通道的數量, N是Batchsize中圖像的數量。
  • F 濾波器組是一個四維數據結構 = FW x FH x FC x K。其中 (FH,FW) 是濾波器的高度和寬度,  K是濾波器組中濾波器的個數. FC 是每個濾波器接收到特徵圖的數量,FC必須與圖像X中的特徵通道的數量相匹配。 Alternatively, FC can
  •                 divide* the C; in this case, filters are assumed to form G=C/FC
  •                 groups* of equal size (where G must divide K). Each group of filters works on a consecutive subset of feature channels of the input array X.

[DX, DF, DB] = VL_NNCONV(X, F, B, DY) 計算導數。DX, DF, DB, DY和 X, F, B, and Y具有相同的維度。 特別地,如果B是空矩陣,那麼DB也是空矩陣。

VL_NNCONV() 實現了一個特殊的全連接模式。

關於VL_NNCONV的可選項參數問題,主要指跨步卷積邊緣填充卷積核膨脹選項:

VL_NNCONV(..., 'option', value, ...)

  • 跨步卷積和默認值 = stride [1] 可以看成是降採樣步驟,stride=1表示沒有降採樣. 如果設置stride=2,意味着橫向和縱向都進行1/2採樣操作;如果設置stride=[2,4], 意味着水平進行了1/2的降採樣,垂直進行了1/4的降採樣。

  • 邊緣填充和默認值 = Pad [0]爲輸入圖像進行邊緣填充。該步驟在卷積操作之前執行,填充的值都是0。[TOP BOTTOM LEFT RIGHT]指爲上下左右填充不同數目的0. 如果指定 pad=1,意味着上下左右都填充單位爲1的0佔位。大多數情況下我是反對邊緣填充的。

  • 卷積核膨脹及默認值 = Dilate [1] 將卷積核進行膨脹運算,膨脹之後0佔位,具體如下所示。通過設置 dilate = [dilate_y, dilate_x]對卷積核不同方向進行膨脹。大多數情況下我也反對卷積核膨脹運算,雖然說大尺寸卷積核有着更好的感知域,但是14年YZ的研究表明,卷積核越小,深度模型擬合得越好。

 [1 3]     if dilate = 2;     [1 0 3]
 [2 4]                        [0 0 0]
                              [2 0 4]

卷積之後圖像尺寸的計算公式爲:

format for padding and stride:
   YH = floor((H + (PADTOP+PADBOTTOM) - FH)/STRIDEY) + 1
   YW = floor((W + (PADLEFT+PADRIGHT) - FW)/STRIDEX) + 1


format for padding , stride, and dilate:
   YH = floor((H + (PADTOP+PADBOTTOM) - FH*(DILATEY-1) -1)/STRIDEY) + 1
   YW = floor((W + (PADLEFT+PADRIGHT) - FW*(DILATEX-1) -1)/STRIDEX) + 1

2. vl_nnReLU - CNN的線性整流單元

Y = VL_NNRELU(X) 對數據X應用線性整流單元函數。X可以是人任意大小。

DZDX = VL_NNRELU(X, DZDY) 計算塊投影到DZDY上的導數. DZDX,DZDY 與 X , Y 具有相同的維度。

VL_NNRELU(...,'OPT',VALUE,...) 具有以下選項:

  • 泄露因子 = leak [0] 設置泄露因子,他是一個非負數. 如果X大於等於0,那麼Y=X; 否則, Y=X*leak. 默認情況下,我們使用leak=0就夠了。

3. vl_nnpool - CNN的池化處理

Y = VL_NNPOOL(X, POOL) 對數據的所有通道施加池化操作。X是四維的數據結構 H x W x D x N,其中 (H,W) 是一層的寬度和高度,D是圖像深度,可以理解爲特徵通道數。N是圖像數目。

Y = VL_NNPOOL(X, [POOLY, POOLX]) 使用矩形窗進行池化,矩形窗的尺寸爲[pool_y, pool_x].

DZDX = VL_NNPOOL(X, POOL, DZDY)計算模塊在DZDY方向上的偏導數。 DZDX,DZDY和 X,Y各自維度對齊。

VL_NNPOOL(..., 'option', value, ...)具有下面的選項參數:

  • 跨步池化 = stride [1] 降採樣操作.可以設置爲同質的標量 stride = [2,2]; 也可以設置爲異質的矢量stride = [2,3].

  • 邊緣填充 = pad [0]:和卷積裏面的操作一樣的

  • 池化方法 = method ['max']: 指定池化的方法。可以選擇最大池化 'method' = 'max'; 也可以選擇平局池化 ‘method’ = ‘avg’

4. vl_nnnormalize - CNN局部響應歸一化

LRN是一種提高深度學習準確度的技術方法。LRN一般是在激活、池化函數後的一種方法。 在ALexNet中,提出了LRN層,對局部神經元的活動創建競爭機制,使其中響應比較大對值變得相對更大,並抑制其他反饋較小的神經元,增強了模型的泛化能力。

在2012的Alexnet網絡中具體計算公式如下:

但是,這個是也很有爭議,2015年針對更深更大的圖像識別模型,有研究學者報道LRN並沒啥用...反而增加了內存的消耗,還浪費時間....

dagnn.LRN('param',[5 1 0.0001/5 0.75]) ;

5. vl_nnbnorm - CNN批歸一化

BatchNorm也是一種旨在提高深度學習精度的方法。與LRN相比,BatchNorm具有容易理解的數學意義。

Y = VL_NNBNORM(X,G,B) 對輸入數據X執行批歸一化操作。批歸一化定義如下:

Y(i,j,k,t) = G(k) * (X(i,j,k,t) - mu(k)) / sigma(k) + B(k)
% where:
mu(k) = mean_ijt X(i,j,k,t)                  % 均值
sigma2(k) = mean_ijt (X(i,j,k,t) - mu(k))^2  % 方差
sigma(k) = sqrt(sigma2(k) + EPSILON)         % 標準差

G(k) 和B(k)分別相乘因子和相加因子,用於處理各通道中的尺度問題,實際中可以設置他們爲常數。

均值和方差通過所有的4D張量X逐漸累積。 常數EPSILON用於正則化sigma(k)和避免零除情況。

[DZDX,DZDG,DZDB] = VL_NNBNORM(X,G,B,DZDY) computes the derviatives of the block projected onto DZDY. DZDX, DZDG, DZDB and DZDY have the same dimensions as X, G, B, and Y respectivey.

VL_NNBNROM(..., 'Option', value)的可選項設置:

  • 微量 = epsilon [1e-4] 指定微量值小一點就好.

  • 動量匹配 = moments [unspecified]:爲了匹配mu和sigma,這是一個很有用的技巧在測試階段,用於禁止批歸一化

  • CuDNN [specified] 如果指定,使用CuDNN. 默認情況下,CuDNN都是開啓的

  • NoCuDNN [not specified] 如果指定,批歸一化就不採用CuDNN.

具體的BatchNorm的原理細節需要單獨再弄一下。

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