一、环境
TensorFlow API r1.12
CUDA 9.2 V9.2.148
cudnn64_7.dll
Python 3.6.3
Windows 10
二、官方说明
对输入张量 value 执行平均池化操作
输出的每个条目为输入张量 value 中 ksize 大小的窗口所有值的平均值
https://www.tensorflow.org/api_docs/python/tf/nn/avg_pool
tf.nn.avg_pool(
value,
ksize,
strides,
padding,
data_format='NHWC',
name=None
)
输入:
(1)value:四维张量 [batch, height, width, channels],数值类型为:float32,float64, qint8, quint8,qint32
(2)ksize:四个整型值 int 的列表或元组,输入张量 value 的每个维度上的滑动窗口的尺寸大小
(3)strides:四个整型值 int 的列表或元组,输入张量 value 的每个维度上的滑动窗口的步幅长度
(4)padding:字符型参数,“VALID” 或 “SAME”,填充算法,参照 tf.nn.convolution
(5)data_format:字符型参数,“NHWC” 或 “NCHW”,分别代表 [batch, height, width, channels] 和 [batch, height, channels , width]
(6)name:可选参数,操作的名称
返回结果:
(1)对输入张量 value 执行平均池化操作后的输出张量,类型和输入张量 value 相同
三、实例
输入(input):batch_size, height, width, channels 的维度分别为 [1, 28, 28, 1]
卷积核(filter):filter_height, filter_width, in_channels, out_channels 的维度分别为 [5, 5, 1, 32]
卷积步幅(strides): batch_size, height, width, channels 的步幅分别为 [1, 1, 1, 1]
平均池化核(avg_filter):batch, height, width, channels 的维度分别为 [1, 2, 2, 1]
平均池化步幅(strides): batch_size, height, width, channels 的步幅分别为 [1, 2, 2, 1]
(1)padding 为 "VALID"
输出维度计算(ceil为取上整数):
output_h = ceil (( input_h - filter_h + 1 ) / strides_h )
output_w = ceil (( input_w - filter_w + 1 ) / strides_w )
通常输入的数据为方形,即 height = width,output_size = ceil (( input_s - filter_s + 1 ) / strides_s )
本例维度计算过程:
卷积输出维度计算为:(28 - 5 + 1) / 1 取上整值为 24,所以卷积操作输出的长、宽都是 24 ,batch_size 保持不变为 1 ,输出的通道由卷积核的输出通道数 32 决定,即下面代码中 output_tensor 的维度为:(1, 24, 24, 32)
池化输出维度计算为:(28 - 2 + 1) / 2 得 13.5 取上整值为 14,所以池化操作输出的长、宽都是 14 ,batch_size 保持不变为 1 ,需要注意的是池化操作不会改变输入数据的通道数,所以输出的通道仍是 32,即下面代码中 output_tensor 的维度为:(1, 14, 14, 32)
>>> import tensorflow as tf
>>> import numpy as np
# 通过 numpy 来构建形状为 (1,28,28,1) 的张量
>>> input_data = [i+1 for i in range(784)]
>>> input_data = np.asarray(input_data)
>>> input_data = input_data.reshape(1,28,28,1)
>>> input_data = input_data.astype(np.float32)
>>> input_tensor = tf.constant(input_data, dtype=tf.float32)
>>> input_tensor
<tf.Tensor 'Const:0' shape=(1, 28, 28, 1) dtype=float32>
# 定义卷积核
>>> filter_tensor = tf.get_variable(name="filter", shape=[5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.02))
>>> filter_tensor
<tf.Variable 'filter:0' shape=(5, 5, 1, 32) dtype=float32_ref>
# 定义平均池化的核
>>> avg_tensor = [1, 2, 2, 1]
# 定义卷积操作和平均池化操作的步长
>>> conv_strides = [1, 1, 1, 1]
>>> avg_strides = [1, 2, 2, 1]
# 定义填充方式
>>> padding_str = "VALID"
# 卷积操作
>>> conv_out = tf.nn.conv2d(input=input_tensor, filter=filter_tensor, strides=conv_strides, padding=padding_str)
>>> conv_out
<tf.Tensor 'Conv2D:0' shape=(1, 28, 28, 32) dtype=float32>
# 池化操作
>>> avg_out = tf.nn.avg_pool(value=conv_out, ksize=avg_tensor, strides=avg_strides, padding="SAME")
>>> avg_out
<tf.Tensor 'AvgPool:0' shape=(1, 14, 14, 32) dtype=float32>
# 初始化所有变量操作
>>> init_op = tf.global_variables_initializer()
# 构建会话来执行相关操作
>>> with tf.Session() as sess:
... sess.run(init_op)
... conv_result, avg_result = sess.run([conv_out,avg_out])
... print(conv_result.shape)
... print(avg_result.shape)
...
# (1, 24, 24, 32)
# (1, 12, 12, 32)
(2)padding 为 "SAME"
输出维度计算:
output_h = ceil ( input_h / strides_h )
output_w = ceil ( input_w / strides_w )
通常输入的数据为方形,即 height = width,output_size = ceil ( input / strides)
本例维度计算过程:
卷积输出维度计算为:28 / 1 取上整值为 28,所以卷积操作输出的长、宽都是 28 ,batch_size 保持不变为 1 ,输出的通道由卷积核的输出通道数 32 决定,即下面代码中 output_tensor 的维度为:(1, 28, 28, 32)
池化输出维度计算为:28 / 2 取上整值为 14,所以池化操作输出的长、宽都是 28 ,batch_size 保持不变为 1 ,需要注意的是池化操作不会改变输入数据的通道数,所以输出的通道仍是 32,即下面代码中 output_tensor 的维度为:(1, 14, 14, 32)
>>> import tensorflow as tf
>>> import numpy as np
# 通过 numpy 来构建形状为 (1,28,28,1) 的张量
>>> input_data = [i+1 for i in range(784)]
>>> input_data = np.asarray(input_data)
>>> input_data = input_data.reshape(1,28,28,1)
>>> input_data = input_data.astype(np.float32)
>>> input_tensor = tf.constant(input_data, dtype=tf.float32)
>>> input_tensor
<tf.Tensor 'Const:0' shape=(1, 28, 28, 1) dtype=float32>
# 定义卷积核
>>> filter_tensor = tf.get_variable(name="filter", shape=[5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.02))
>>> filter_tensor
<tf.Variable 'filter:0' shape=(5, 5, 1, 32) dtype=float32_ref>
# 定义平均池化的核
>>> avg_tensor = [1, 2, 2, 1]
# 定义卷积操作和平均池化操作的步长
>>> conv_strides = [1, 1, 1, 1]
>>> avg_strides = [1, 2, 2, 1]
# 定义填充方式
>>> padding_str = "SAME"
# 卷积操作
>>> conv_out = tf.nn.conv2d(input=input_tensor, filter=filter_tensor, strides=conv_strides, padding=padding_str)
>>> conv_out
<tf.Tensor 'Conv2D:0' shape=(1, 28, 28, 32) dtype=float32>
# 池化操作
>>> avg_out = tf.nn.avg_pool(value=conv_out, ksize=avg_tensor, strides=avg_strides, padding="SAME")
>>> avg_out
<tf.Tensor 'AvgPool:0' shape=(1, 14, 14, 32) dtype=float32>
# 初始化所有变量操作
>>> init_op = tf.global_variables_initializer()
# 构建会话来执行相关操作
>>> with tf.Session() as sess:
... sess.run(init_op)
... conv_result, avg_result = sess.run([conv_out,avg_out])
... print(conv_result.shape)
... print(avg_result.shape)
...
# (1, 28, 28, 32)
# (1, 14, 14, 32)