1. 程式人生 > >Tensorflow中兩種Padding運算方式

Tensorflow中兩種Padding運算方式

邊界補充問題

原始圖片尺寸為7*7,卷積核的大小為3*3,當卷積核沿著圖片滑動後只能滑動出一個5*5的圖片出來,這就造成了卷積後的圖片和卷積前的圖片尺寸不一致,這顯然不是我們想要的結果,所以為了避免這種情況,需要先對原始圖片做邊界填充處理。在上面的情況中,我們需要先把原始影象填充為9*9的尺寸。 
常用的區域填充方法包括: 
用3*3定義原始影象的尺寸,補充為9*9的尺寸,圖片上的顏色只為方便觀看,並沒有任何其他含義。 
原始影象:

這裡寫圖片描述

(1)補零 
這裡寫圖片描述 
(2)邊界複製 
這裡寫圖片描述 
(3)映象 
這裡寫圖片描述 
(4)塊複製 
這裡寫圖片描述

卷積操作有兩個問題: 
1. 影象越來越小; 
2. 影象邊界資訊丟失,即有些影象角落和邊界的資訊發揮作用較少。因此需要padding。

卷積核大小通常為奇數 
一方面是為了方便same卷積padding對稱填充,左右兩邊對稱補零; 
n+2p-f+1=n 
p=(f-1)/2 
另一方面,奇數過濾器有中心畫素,便於確定過濾器的位置。

padding的方式:

這裡寫圖片描述

備註

"VALID" only ever drops the right-most columns (or bottom-most rows).
    "SAME" tries to pad evenly left and right, but if the amount of columns to be added is odd, it will add the extra column to the right, as is the case in this example (the same logic applies vertically: there may be an extra row of zeros at the bottom).
不同的padding方式,VALID是採用丟棄的方式,
比如上述的input_width=13,只允許滑動2次,多餘的元素全部丟掉

Tensorflow中的定義

The TensorFlow Convolution example gives an overview about the difference between SAME and VALID :
    For the SAME padding, the output height and width are computed as:
    out_height = ceil(float(in_height) / float(strides[1]))
    out_width = ceil(float(in_width) / float(strides[2]))
And
    For the VALID padding, the output height and width are computed as:
    out_height = ceil(float(in_height - filter_height + 1) / float(strides1))
    out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))

備註

#SAME 向上取整
#VALID 向下取整
輸入:n*c0*w0*h0
輸出:n*c1*w1*h1
其中,c1就是引數中的num_output,生成的特徵圖個數
 w1=floor((w0+2*pad-kernel_size)/stride)+1;向下取整
 h1=floor((h0+2*pad-kernel_size)/stride)+1;向下取整
如果設定stride為1,前後兩次卷積部分存在重疊。如果設定pad=(kernel_size-1)/2,則運算後,寬度和高度不變。
由pad, kernel_size和stride三者共同決定。
x = tf.constant([[1., 2., 3.],
                 [4., 5., 6.]])

x = tf.reshape(x, [1, 2, 3, 1])  # give a shape accepted by tf.nn.max_pool

valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

valid_pad.get_shape() == [1, 1, 1, 1]  # valid_pad is [5.]
same_pad.get_shape() == [1, 1, 2, 1]   # same_pad is  [5., 6.]

參考文獻: