我正在尝试理解 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
为什么看起来像 reshape 的pooling2[0, 0, 0],即1来自
(0+0+0 + 1+1+1 + 2+2+2) / 9,
为什么不是 /16?
请您参考如下方法:
是的,被填充的像素不被计算在平均值中。因此,对于 4x4 池化,在图像中间计算的结果是 16 个值的平均值,但如果填充了两个边缘,则角落中的值只能使用 9 值。
例如你可以看到它here in the source关于对 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.]]
显然文档可以更明确地说明它。
