tf.nn.avg_pool采用SAME padding时为何未将填充像素纳入平均计算?
理解tf.nn.avg_pool的SAME padding与平均计算逻辑
你遇到的问题核心在于TensorFlow中tf.nn.avg_pool在padding='SAME'模式下的有效元素计数规则,以及SAME padding的具体填充方式。我们一步步拆解你的例子:
1. 先明确输入与池化参数的维度
你的输入img实际会被自动扩展为[1,4,4,2]的4D张量(添加batch维度):
- batch=1,height=4,width=4,channels=2(每个位置的
[0,4]对应通道0的0和通道1的4) - 池化窗口
ksize=[1,4,4,1]:对height和width维度做4x4的窗口池化,stride=1,padding='SAME'
2. SAME padding的填充计算
对于SAME padding,输出的height/width等于ceil(input_size / stride),这里输入height=4,stride=1,所以输出height=4。接下来计算需要填充的像素数:
- 总填充高度:
((output_height-1)*stride + ksize_height - input_height) = (3*1 +4-4)=3 - 顶部填充1行,底部填充2行(对称填充规则:当总填充数为奇数时,底部/右侧多填1行/列)
- width维度同理:左侧填充1列,右侧填充2列
填充后的输入height变为4+1+2=7,width变为4+1+2=7,超出原输入的区域填充0。
3. 第一个输出元素的计算逻辑
输出的第一个位置(对应原输入左上角)对应的池化窗口是填充后输入的行0-3,列0-3:
- 这个窗口里,只有填充后的行1-3(对应原输入行0-2)、列1-3(对应原输入列0-2)是原输入的有效元素,共
3x3=9个,其余位置都是填充的0。 - 通道0的有效元素总和:
0*3(原行0的列0-2) +1*3(原行1的列0-2) +2*3(原行2的列0-2)= 0+3+6=9 - 关键:这里平均计算时只除以有效元素的数量9,而不是窗口总大小16,因此结果是
9/9=1.0。
4. 为什么第一行全是1.0?
因为你的原输入中,每一行的width维度值都是相同的(比如原行0的所有width位置通道0都是0),所以width方向每个窗口的有效元素总和都是9,平均后都是1.0,因此第一行全为1.0。
关于"为什么不是除以16"的疑问
这是因为tf.nn.avg_pool有一个count_include_pad参数:
- 当
count_include_pad=True(TensorFlow 1.4+默认):会把填充的0计入总和,除以窗口总大小16,此时第一个元素会是(0*7 +9)/16=0.5625 - 当
count_include_pad=False(旧版本默认):只计算原输入的有效元素,除以有效元素数9,得到你看到的1.0
你的运行结果说明当前环境中这个参数默认是False,或者你可能在代码中隐式设置了这个参数。
内容的提问来源于stack exchange,提问作者NeoZoom.lua
相关产品推荐
相关产品推荐

