1. 程式人生 > >詳解CNN中的stride 和 padding 到底是怎麼計算的

詳解CNN中的stride 和 padding 到底是怎麼計算的

平時不注意的細節,別人一問的時候就會很懵逼,所以認真對待每一個引數。

先看一下 tensorflow中自帶的卷積操作是什麼樣子的呢?

https://tensorflow.google.cn/api_docs/python/tf/nn/conv2d

tf.nn.conv2d(
    input,
    filter,
    strides,
    padding,
    use_cudnn_on_gpu=True,
    data_format='NHWC',
    dilations=[1, 1, 1, 1],
    name=None
)

其中data_format這個引數我們很少了解,其實它是固定你input的格式,NHWC對應著你的輸入資料的維度時[batch_size,Heigth,Width,Channel],NCHW對應[batch_size,Channel,Heigth,Width]。

其實strides裡面的引數和這個data_format是一一對應的,什麼意思呢?就是說,如果我們採用NHWC的方式和strides=[a,b,c,d]的情況下,計算卷積核移動過程是怎麼樣的呢?它會在batch的維度上按照 step=a的大小進行移動計算,同理,分別在HWC的維度上移動的step為b c d。因為我們需要對每一個batch和channel都需要進行計算,所以這裡 a,d 的值為1。b c的值可以根據實際情況進行改變,他們的值直接關係到輸出的feature map 的維度。

在來看一下在padding 等於 same 和valid 兩個引數下的計算方式。

可以參考:https://www.jianshu.com/p/05c4f1621c7e

假設,我們輸入的影象的大小為:W*H

         kernel size的大小為: k_h*k_w

        在 H 方向的stride為 h, 在W方向 的stride為 w

        來求我們新輸出的特徵圖的大小,n_h 和 n_w

如果是 valid 模式,他是隻在原圖進行修改

      則 n_h =( H-k_h)/ h 向上取整後加 1 ;

          n_w = (W-k_w)/ h 向上取整後加 1 ;

如果是 SAME 模式,他會在填充的時候自動補0(在必要的時候)。

那麼什麼是必要的時候呢?它是先根據公式 n_h = H/h 向上取整

n_w=W/w 向上取整 得到最終的輸出n_h和n_w,在根據得需要輸出的 n_h 和 n_w 反向推到那些地方需要補 0 。

在 H 方向 pad_need_H = (n_h -1 ) * h +K_h - H

在矩陣每一行的上方需要新增的畫素數為:

pad_need_H/2 取整 

在矩陣每一行的下方需要新增的畫素數為

pad_need_H - pad_need_H/2

同理可得在W方向,

原始碼如下。

例如輸入的是feature map 是4*4 ,kernel size 為1*1,strides 1,1

則它需要補充後的圖為

這裡畫斜槓的為填充的0

加入輸入的feature map 為 2*5 kernel size 為2*2 , strides 為【1,2,1,1】

則它需要填充後的圖為

最後一列為需要填充的0值,最後輸出的feature map 為1*5

歡迎指正和補充。