CNN之池化層tf.nn.max_pool | tf.nn.avg_pool | tf.reduce_mean | padding的規則解釋


摘要:池化層的主要目的是降維,通過濾波器映射區域內取最大值、平均值等操作。

均值池化:tf.nn.avg_pool(input,ksize,strides,padding)

最大池化:tf.nn.max_pool(input,ksize,strides,padding)

input:通常情況下是卷積層輸出的featuremap,shape=[batch,height,width,channels]

                

  假定這個矩陣就是卷積層輸出的featuremap(2通道輸出)  他的shape=[1,4,4,2]

ksize:池化窗口大小    shape=[batch,height,width,channels]    比如[1,2,2,1]

strides: 窗口在每一個維度上的移動步長 shape=[batch,stride,stride,channel]  比如[1,2,2,1]

padding:“VALID”不填充  “SAME”填充0

返回:tensor        shape=[batch,height,width,channels]

上圖是采用的最大池化,取紅色框內最大的一個數。

import tensorflow as tf
feature_map = tf.constant([
    [[0.0,4.0],[0.0,4.0],[0.0,4.0],[0.0,4.0]],
    [[1.0,5.0],[1.0,5.0],[1.0,5.0],[1.0,5.0]],
    [[2.0,6.0],[2.0,6.0],[2.0,6.0],[2.0,6.0]] ,
    [[3.0,7.0],[3.0,7.0],[3.0,7.0],[3.0,7.0]]
    ])
feature_map = tf.reshape(feature_map,[1,4,4,2])##兩通道featuremap輸入

##定義池化層
pooling = tf.nn.max_pool(feature_map,[1,2,2,1],[1,2,2,1],padding='VALID')##池化窗口2*2,高寬方向步長都為2,不填充
pooling1 = tf.nn.max_pool(feature_map,[1,2,2,1],[1,1,1,1],padding='VALID')##池化窗口2*2,高寬方向步長都為1,不填充
pooling2 = tf.nn.avg_pool(feature_map,[1,4,4,1],[1,1,1,1],padding='SAME')##池化窗口4*4,高寬方向步長都為1,填充
pooling3 = tf.nn.avg_pool(feature_map,[1,4,4,1],[1,4,4,1],padding='SAME')##池化窗口4*4,高寬方向步長都為4,填充
##轉置變形(詳細解釋參考另一篇博文)
tran_reshape = tf.reshape(tf.transpose(feature_map),[-1,16])
pooling4 = tf.reduce_mean(tran_reshape,1)    ###對行值求平均
with tf.Session() as sess:
    print('featuremap:\n',sess.run(feature_map))
    print('*'*30)
    print('pooling:\n',sess.run(pooling))
    print('*'*30)
    print('pooling1:\n',sess.run(pooling1))
    print('*'*30)
    print('pooling2:\n',sess.run(pooling2))
    print('*'*30)
    print('pooling3:\n',sess.run(pooling3))
    print('*'*30)
    print('pooling4:\n',sess.run(pooling4))
'''
輸出結果:
featuremap:
 [[[[ 0.  4.]
   [ 0.  4.]
   [ 0.  4.]
   [ 0.  4.]]

  [[ 1.  5.]
   [ 1.  5.]
   [ 1.  5.]
   [ 1.  5.]]

  [[ 2.  6.]
   [ 2.  6.]
   [ 2.  6.]
   [ 2.  6.]]

  [[ 3.  7.]
   [ 3.  7.]
   [ 3.  7.]
   [ 3.  7.]]]]
******************************
pooling:
 [[[[ 1.  5.]
   [ 1.  5.]]

  [[ 3.  7.]
   [ 3.  7.]]]]
******************************
pooling1:
 [[[[ 1.  5.]
   [ 1.  5.]
   [ 1.  5.]]

  [[ 2.  6.]
   [ 2.  6.]
   [ 2.  6.]]

  [[ 3.  7.]
   [ 3.  7.]
   [ 3.  7.]]]]
******************************
pooling2:
 [[[[ 1.   5. ]
   [ 1.   5. ]
   [ 1.   5. ]
   [ 1.   5. ]]

  [[ 1.5  5.5]
   [ 1.5  5.5]
   [ 1.5  5.5]
   [ 1.5  5.5]]

  [[ 2.   6. ]
   [ 2.   6. ]
   [ 2.   6. ]
   [ 2.   6. ]]

  [[ 2.5  6.5]
   [ 2.5  6.5]
   [ 2.5  6.5]
   [ 2.5  6.5]]]]
******************************
pooling3:
 [[[[ 1.5  5.5]]]]
******************************
pooling4:
 [ 1.5  5.5]

'''
池化層常用函數及參數

現在我們對代碼中的內容加以解釋:

padding的規則

  •   padding=‘VALID’時,輸出的寬度和高度的計算公式(下圖gif為例)

          

    輸出寬度:output_width = (in_width-filter_width+1)/strides_width  =(5-3+1)/2=1.5【向上取整=2】

    輸出高度:output_height = (in_height-filter_height+1)/strides_height  =(5-3+1)/2=1.5【向上取整=2】

    輸出的形狀[1,2,2,1]

        

    
import tensorflow as tf
image = [0,1.0,1,2,2,0,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,2,0,1,0]
input = tf.Variable(tf.constant(image,shape=[1,5,5,1]))  ##1通道輸入
fil1 = [-1.0,0,1,-2,0,2,-1,0,1]
filter = tf.Variable(tf.constant(fil1,shape=[3,3,1,1]))  ##1個卷積核對應1個featuremap輸出

op = tf.nn.conv2d(input,filter,strides=[1,2,2,1],padding='VALID')  ##步長2,VALID不補0操作

init = tf.global_variables_initializer()

with tf.Session() as  sess:
    sess.run(init)
    # print('input:\n', sess.run(input))
    # print('filter:\n', sess.run(filter))
    print('op:\n',sess.run(op))

##輸出結果
'''
 [[[[ 2.]
   [-1.]]

  [[-1.]
   [ 0.]]]]
'''
tensorflow中實現(步長2)

    如果strides=[1,3,3,1]的情況又是如何呢?   

    輸出寬度:output_width  = (in_width-filter_width+1)/strides_width  =(5-3+1)/3=1

    輸出高度:output_height = (in_height-filter_height+1)/strides_height  =(5-3+1)/3=1

    輸出的形狀[1,1,1,1],因此輸出的結果只有一個

    

    
import tensorflow as tf
image = [0,1.0,1,2,2,0,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,2,0,1,0]
input = tf.Variable(tf.constant(image,shape=[1,5,5,1]))  ##1通道輸入
fil1 = [-1.0,0,1,-2,0,2,-1,0,1]
filter = tf.Variable(tf.constant(fil1,shape=[3,3,1,1]))  ##1個卷積核對應1個featuremap輸出

op = tf.nn.conv2d(input,filter,strides=[1,3,3,1],padding='VALID')  ##步長2,VALID不補0操作

init = tf.global_variables_initializer()

with tf.Session() as  sess:
    sess.run(init)
    # print('input:\n', sess.run(input))
    # print('filter:\n', sess.run(filter))
    print('op:\n',sess.run(op))

##輸出結果
'''
op:
 [[[[ 2.]]]]
'''
tensorflow中實現(步長3)

     padding=‘SAME’時,輸出的寬度和高度的計算公式(下圖gif為例)

    

    輸出寬度:output_width  = in_width/strides_width=5/2=2.5【向上取整3】

    輸出高度:output_height = in_height/strides_height=5/2=2.5【向上取整3】

    則輸出的形狀:[1,3,3,1]

    那么padding補0的規則又是如何的呢?【先確定輸出形狀,再計算補多少0】

    pad_width = max((out_width-1)*strides_width+filter_width-in_width,0)=max((3-1)*2+3-5,0)=2

    pad_height = max((out_height-1)*strides_height+filter_height-in_height,0)=max((3-1)*2+3-5,0)=2

    pad_top = pad_height/2=1

    pad_bottom = pad_height-pad_top=1

    pad_left = pad_width/2=1

    pad_right = pad_width-pad_left=1

    

    
import tensorflow as tf
image = [0,1.0,1,2,2,0,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,2,0,1,0]
input = tf.Variable(tf.constant(image,shape=[1,5,5,1]))  ##1通道輸入
fil1 = [-1.0,0,1,-2,0,2,-1,0,1]
filter = tf.Variable(tf.constant(fil1,shape=[3,3,1,1]))  ##1個卷積核對應1個featuremap輸出

op = tf.nn.conv2d(input,filter,strides=[1,2,2,1],padding='SAME')  ##步長2,VALID不補0操作

init = tf.global_variables_initializer()

with tf.Session() as  sess:
    sess.run(init)
    # print('input:\n', sess.run(input))
    # print('filter:\n', sess.run(filter))
    print('op:\n',sess.run(op))

##輸出結果
'''
op:
 [[[[ 3.]
   [ 1.]
   [-4.]]

  [[ 3.]
   [ 0.]
   [-3.]]

  [[ 4.]
   [-1.]
   [-3.]]]]
'''
SAME步長2

    如果步長為3呢?補0的規則又如何?

    輸出寬度:output_width  = in_width/strides_width=5/3=2

    輸出高度:output_height = in_height/strides_height=5/3=2

    則輸出的形狀:[1,2,2,1]

    那么padding補0的規則又是如何的呢?【先確定輸出形狀,再計算補多少0】

    pad_width = max((out_width-1)*strides_width+filter_width-in_width,0)=max((2-1)*3+3-5,0)=1

    pad_height = max((out_height-1)*strides_height+filter_height-in_height,0)=max((2-1)*3+3-5,0)=1

    pad_top = pad_height/2=0【向下取整】

    pad_bottom = pad_height-pad_top=1

    pad_left = pad_width/2=0【向下取整】

    pad_right = pad_width-pad_left=1

        

    
import tensorflow as tf
print(3/2)
image = [0,1.0,1,2,2,0,1,1,0,0,1,1,0,1,0,1,0,1,1,1,0,2,0,1,0]
input = tf.Variable(tf.constant(image,shape=[1,5,5,1]))  ##1通道輸入
fil1 = [-1.0,0,1,-2,0,2,-1,0,1]
filter = tf.Variable(tf.constant(fil1,shape=[3,3,1,1]))  ##1個卷積核對應1個featuremap輸出

op = tf.nn.conv2d(input,filter,strides=[1,3,3,1],padding='SAME')  ##步長2,VALID不補0操作

init = tf.global_variables_initializer()

with tf.Session() as  sess:
    sess.run(init)
    # print('input:\n', sess.run(input))
    # print('filter:\n', sess.run(filter))
    print('op:\n',sess.run(op))

##輸出結果
'''
op:
 [[[[ 2.]
   [-3.]]

  [[ 0.]
   [-3.]]]]
'''
SAME步長3

    這里借用的卷積中的padding規則,在池化層中的padding規則與卷積中的padding規則一致   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM