演示反池化的操作

TensorFlow中目前还没有反池化操作的函数。对于最大池化层,也不支持输出最大激活值得位置,但是同样有个池化的反向传播函数tf.nn.max_pool_with_argmax()。该函数可以找出位置,需要开发者利用这个函数做一些改动,自己封装一个最大池化操作,然后再根据mask写出反池化函数。
def max_pool_with_argmax(net,stride):
'''
重定义一个最大池化函数,返回最大池化结果以及每个最大值的位置(是个索引,形状和池化结果一致)
args:
net:输入数据 形状为[batch,in_height,in_width,in_channels]
stride:步长,是一个int32类型,注意在最大池化操作中我们设置窗口大小和步长大小是一样的
'''
#使用mask保存每个最大值的位置 这个函数只支持GPU操作
_, mask = tf.nn.max_pool_with_argmax( net,ksize=[1, stride, stride, 1], strides=[1, stride, stride, 1],padding='SAME')
#将反向传播的mask梯度计算停止
mask = tf.stop_gradient(mask)
#计算最大池化操作
net = tf.nn.max_pool(net, ksize=[1, stride, stride, 1],strides=[1, stride, stride, 1], padding='SAME')
#将池化结果和mask返回
return net,mask



def un_max_pool(net,mask,stride):
'''
定义一个反最大池化的函数,找到mask最大的索引,将max的值填到指定位置
args:
net:最大池化后的输出,形状为[batch, height, width, in_channels]
mask:位置索引组数组,形状和net一样
stride:步长,是一个int32类型,这里就是max_pool_with_argmax传入的stride参数
'''
ksize = [1, stride, stride, 1]
input_shape = net.get_shape().as_list()
# calculation new shape
output_shape = (input_shape[0], input_shape[1] * ksize[1], input_shape[2] * ksize[2], input_shape[3])
# calculation indices for batch, height, width and feature maps
one_like_mask = tf.ones_like(mask)
batch_range = tf.reshape(tf.range(output_shape[0], dtype=tf.int64), shape=[input_shape[0], 1, 1, 1])
b = one_like_mask * batch_range
y = mask // (output_shape[2] * output_shape[3])
x = mask % (output_shape[2] * output_shape[3]) // output_shape[3]
feature_range = tf.range(output_shape[3], dtype=tf.int64)
f = one_like_mask * feature_range
# transpose indices & reshape update values to one dimension
updates_size = tf.size(net)
indices = tf.transpose(tf.reshape(tf.stack([b, y, x, f]), [4, updates_size]))
values = tf.reshape(net, [updates_size])
ret = tf.scatter_nd(indices, values, output_shape)
return ret

#定义一个形状为4x4x2的张量
img = 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]],
])
img = tf.reshape(img,[1,4,4,2])
#最大池化操作
pooling1 = tf.nn.max_pool(img,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#带有最大值位置的最大池化操作
pooling2,mask = max_pool_with_argmax(img,2)
#反最大池化
img2 = un_max_pool(pooling2,mask,2)
with tf.Session() as sess:
print('image:')
image = sess.run(img)
print(image)
#默认的最大池化输出
result = sess.run(pooling1)
print('max_pool:\n',result)
#带有最大值位置的最大池化输出
result,mask2 = sess.run([pooling2,mask])
print('max_pool_with_argmax:\n',result,mask2)
#反最大池化输出
result = sess.run(img2)
print('un_max_pool',result)
这里我们自己定义了两个函数,一个是带有最大值位置的最大池化函数,一个反最大池化函数,程序运行后,我们应该可以看到自己定义的最大池化与原来的版本输出是一样的,由于tf.nn.max_pool_with_argmax()函数只支持GPU操作,不能在CPU机器上运行,所以我没法运行这段程序。mask的值是将整个数组flat后的索引,并保持与池化结果一致的shape。
参考

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/80300529