前言
先強調一點:
涉及到參數,都是針對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卷積核 # 看清楚,是取模運算
我爲了演示, 我突來靈感,隨便找了一個 五子棋棋盤(笑了), 見下圖。
小技巧(有無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倍。
所以: 池化層通常用來做降採樣。 (起到變換形狀的作用,無權重參數更新)