首页 > 解决方案 > Tensorflow:具有“相同”填充的 tf.nn.avg_pool() 不会平均填充像素

问题描述

我试图理解tf.nn.avg_pool()。我不知道结果的第一行如何[1.0, 1.0, 1.0, 1.0]

img = tf.constant([
    [[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]]
], dtype=tf.float32)

pooling2 = tf.nn.avg_pool(img, ksize=[1,4,4,1], strides=[1,1,1,1], padding='SAME')

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    print('pooling2.shape: {}'.format(sess.run(pooling2).shape))
    print('pooling2:\n{}'.format(
        sess.run(pooling2).transpose([0,3,1,2]).reshape([2,4,4])             ))

打印的结果是

pooling2.shape: (1, 4, 4, 2)
pooling2:
[[[1.  1.  1.  1. ]
  [1.5 1.5 1.5 1.5]
  [2.  2.  2.  2. ]
  [2.5 2.5 2.5 2.5]]

 [[5.  5.  5.  5. ]
  [5.5 5.5 5.5 5.5]
  [6.  6.  6.  6. ]
  [6.5 6.5 6.5 6.5]]]

似乎它在顶部填充了一行,在左侧填充了一列,在右侧和底部填充了两行和两列,然后将 4x4 窗口/内核应用于与左上角对齐的填充结果:

_ _ _ _ _ _ _
_ 0 0 0 0 _ _
_ 1 1 1 1 _ _
_ 2 2 2 2 _ _
_ 3 3 3 3 _ _
_ _ _ _ _ _ _
_ _ _ _ _ _ _

放大到左上角

_ _ _ _
_ 0 0 0
_ 1 1 1
_ 2 2 2

为什么它看起来像重塑pooling2[0, 0, 0],它1来自

(0+0+0 + 1+1+1 + 2+2+2) / 9,

为什么不/ 16呢?

标签: pythontensorflow

解决方案


是的,平均不考虑填充的像素。因此,通过4x4池化,在图像中间计算的结果平均超过 16 个值,但角落中的值只能使用9填充两个边缘的值。

例如,您可以在有关调用 CuDNN的源代码中CUDNN_POOLING_AVERAGE_COUNT_EXCLUDE_PADDING看到它,其中选择了用于平均填充的选项。CuDNN 还提出了CUDNN_POOLING_AVERAGE_COUNT_INCLUDE_PADDING,这将考虑平均填充像素,但 tensorflow 没有公开此选项。

这可能是平均池的行为与(跨步)卷积不同的一种方式,尤其是对于空间范围较小的层。

请注意,情况与最大池相似:填充像素被忽略(或等效地,虚拟设置为 的值-inf)。

import tensorflow as tf

x = -tf.ones((1, 4, 4, 1))
max_pool = tf.nn.max_pool(x, (1, 4, 4, 1), (1, 1, 1, 1), 'SAME')
sess = tf.InteractiveSession()
print(max_pool.eval().squeeze())
# [[-1. -1. -1. -1.]
#  [-1. -1. -1. -1.]
#  [-1. -1. -1. -1.]
#  [-1. -1. -1. -1.]]

显然,文档可以更明确地说明它。


推荐阅读