經驗拾憶(純手工)=> CNN之kernel_size/strides/padding/same

前言

先強調一點:

涉及到參數,都是針對Tensorflow來講的。

本文主要說一些CNN最常用的幾個參數。
以及各種組合情況下卷積之後計算形狀的規律公式。

filters       (必填, 這個本文不說)
kernel_size  (必填)
strides         (選填, 默認爲 (1,1) )
padding         (選填,默認爲 valid)

這裏先提一下,通用公式: (寬高都用這個公式,我只列出了高度的)

h圖片輸出 = (h圖片輸入 - h卷積核 + 2padding) / strides + 1

也許你看起來沒什麼問題,但是Tensorflow中的API可不告訴你padding是幾。
而是提供給你2個可選參數:

padding='valid'     (默認參數)  # 代表不做padding,滑動不能越界,多餘就裁剪。
padding='same'                 # same我會在下面展開說明。

無same情況

strides = 1

你完全可以按照上面的通用公式計算,但是通常情況下我會用另一個簡便的公式:

h圖片輸出 = h圖片輸入 - h卷積核 + 1   

strides != 1

這個就得使用上面的通用公式了:

h圖片輸出 = (h圖片輸入 - h卷積核 + 2padding) / strides + 1

有same情況

加了same,情況就比較複雜一些了。
same 就是 讓你在不同的 strides滑動情況下,幫你把原圖片虛擬補全。
使得filter在圖片中完全滑動,(而不至於,最後剩下一點越界滑不到給無情的裁剪掉)。

strides = 1(重點)

strides=1的情況下,如果你使用了 same。
那麼same會幫你補充 padding, 使得你滑動後的特徵形狀與滑動之前的形狀 "保持一致"。
補充的padding大小爲: (敲黑板):

padding = h圖片輸入  %  h卷積核            # 看清楚,是取模運算        

舉個例子,驗證一下:

假如:
    圖片(輸入) = 7 x 7,
    kernel_size = (5,5), 
    strides = 1。
(通過我們上面給出的公式,你先求 padding = 7 % 5) ,很顯然是2。

我們再用最開始講的通用公式驗證一遍:
    h輸出長度 = (h輸入 - h卷積核 + 2 * padding) / 1 + 1 = 7-5 + 2*2 + 1 = 7
    巧了,我們的輸入長度也是 7。
    
所以綜上所述: padding = h圖片輸入  %  h卷積核。 
可以使得:輸入形狀 與卷積後的輸出形狀一致

strides != 1(重點)

當步長strides爲多步時,如果你使用了 same。
敲黑板:那麼same會幫你補充 padding, 並且卷積後的特徵圖縮小爲原來的 strides倍。
補充的padding大小爲: (敲黑板):

padding = h圖片輸入  %  h卷積核            # 看清楚,是取模運算

我爲了演示, 我突來靈感,隨便找了一個 五子棋棋盤(笑了), 見下圖。
image.png

小技巧(有無same都適用)

當你預期想要把特徵形狀卷積之後形狀大小"成倍縮小"時,你可以 "同時" 設置:

kernel_size == strides == (n,n)  # n就是縮小的倍數

說明,只要你把 kernel_size 和 strides 設置爲相等,設置爲n。那麼圖像一定會縮小n倍。

舉個栗子: n設爲3
    kernel_size = (3,3) 
    strides = (3,3)
    那麼: 你卷積出來的特徵尺寸,一定比上一層縮小3倍。

結束語(聊一下Pooling2D)

pooling的通用公式和 CNN中的是一模一樣的。
Tensorflow 中 xxxPooling API參數如下:

pool_size (選填,默認爲 (2, 2) )
strides   (選填,默認爲 None)   (這裏你會疑問,None是什麼鬼???)
    我也不知道,API參數也沒給說明。當我跳進源碼,我發現如下代碼,瞬間豁然開朗!
    if strides is None:
        strides = pool_size        (這應該就不用我解釋了吧~)
padding   (選填,默認爲 valid, 通常沒必要用 same )

我們上面說過小技巧:

卷積層中:     kernel_size == strides == (n,n)  # n就是縮小的倍數
池化層也同理: pool_size == strides == (n,n)    # n就是縮小的倍數

又因爲剛纔又說了 ,  池化層中 strides 默認值等於 pool_size 的長度。

所以: 我們只設置一個  pool_size = (n,n)。 即可直接讓原圖縮小n倍。

所以: 池化層通常用來做降採樣。  (起到變換形狀的作用,無權重參數更新)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章