TensorFlow中的反卷积,反池化操作

原文地址:https://www.cnblogs.com/zyly/p/8991412.html

另参考博客:https://buptldy.github.io/2016/10/29/2016-10-29-deconv/

  • 反卷积是指,通过测量输出和已知输入重构未知输入的过程。在神经网络中,反卷积过程并不具备学习的能力,仅仅是用于可视化一个已经训练好的卷积神经网络,没有学习训练的过程。反卷积有着许多特别的应用,一般可以用于信道均衡、图像恢复、语音识别、地震学、无损探伤等未知输入估计和过程辨识方面的问题。
  • 在神经网络的研究中,反卷积更多的是充当可视化的作用,对于一个复杂的深度卷积网络,通过每层若干个卷积核的变换,我们无法知道每个卷积核关注的是什么,变换后的特征是什么样子。通过反卷积的还原,可以对这些问题有个清晰的可视化,以各层得到的特征图作为输入,进行反卷积得到反卷积结果,以验证显示各层提取到的特征图。

一 反卷积原理

  • 反卷积可以理解为卷积操作的逆操作,这里千万不要当成反卷积操作可以复原卷积操作的输入值,反卷积并没有那个功能,它仅仅是将卷积变换过程中的步骤反向变换一次而已,通过将卷积核转置,与卷积后的结果再做一遍卷积,所以它还有一个名字叫做转置卷积。
  • 举个例子:假如你想要查看Alexnet 的conv5提取到了什么东西,我们就用conv5的特征图后面接一个反卷积网络,然后通过:反池化、反激活、反卷积,这样的一个过程,把本来一张13*13大小的特征图(conv5大小为13*13),放大回去,最后得到一张与原始输入图片一样大小的图片(227*227)。
  • 虽然它不能还原出原来卷积的样子,但是在作用上有类似的效果,你可以将带有小部分缺失的信息最大化的恢复,也可以用来恢复被卷积生成后的原始输入。
  • 反卷积的具体操作比较复杂,这里不介绍如何具体实现反卷积,在tensorflow中反卷积的是通过函数tf.nn.conv2d_transpose()来实现的:
def conv2d_transpose(value,
                     filter,
                     output_shape,
                     strides,
                     padding="SAME",
                     data_format="NHWC",
                     name=None):
  • 具体参数说明如下:
  1. value:代表通过卷积操作之后的张量,一般用NHWC类型。如果是NHWC类型,形状[batch, height, width, in_channels],如果是NCHW类型,形状为[batch, in_channels, height, width]。
  2. filter:代表卷积核,形状为[height, width, output_channels, in_channels]。
  3. output_shape:反卷积输出的张量形状,它必须是能够生成value参数的原数据的形状,如果输出形状不对,函数会报错。
  4. strides:代表原数据生成value时使用的步长。
  5. padding:代表原数据生成value时使用的填充方式,是用来检查输入形状和输出形状是否合规的。
  6. data_format: 'NHWC' and 'NCHW' 类型。
  7. name:名称。
  • 返回反卷积后的形状,按照output_shape指定的形状。
  • 查看该函数的实现代码,我们可以看到反卷积的操作其实是使用了gen_nn_ops.conv2d_backprop_input()函数来实现的,相当于在TensorFlow中利用了卷积操作在反向传播的处理函数中做反卷积操作,即卷积操作的反向传播就是反卷积操作。

注意:在使用反卷积的网络中,定义占位符中不能存在None,必须指定具体的数,不然会报错。

二 反卷积实例

  • 我们通过对模拟数据进行卷积和反卷积的操作,来比较卷积与反卷积中padding在SAME和VALID下的变化。先定义一个[1,4,4,1]的矩阵,矩阵里的元素值都为1,与滤波器大小为2x2,步长为2x2,分别使用padding为SAME和VALID两种情况生成卷积数据,然后将结果再进行反卷积运算,打印输出的结果
'''
一 反卷积实例
'''
import tensorflow as tf
import numpy as np

#模拟数据
img = tf.Variable(tf.constant(1.0,shape=[1,4,4,1]))

kernel =tf.Variable(tf.constant([1.0,0,-1,-2],shape=[2,2,1,1]))

#分别进行VALID和SAME操作
conv =  tf.nn.conv2d(img,kernel,strides=[1,2,2,1],padding='VALID')
cons =  tf.nn.conv2d(img,kernel,strides=[1,2,2,1],padding='SAME')

#VALID填充计算方式 (n - f + 1)/s向上取整
print(conv.shape)
#SAME填充计算方式 n/s向上取整
print(cons.shape)

#在进行反卷积操作
contv = tf.nn.conv2d_transpose(conv,kernel,[1,4,4,1],strides=[1,2,2,1],padding='VALID')
conts = tf.nn.conv2d_transpose(cons,kernel,[1,4,4,1],strides=[1,2,2,1],padding='SAME')

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    print('kernel:\n',sess.run(kernel))
    print('conv:\n',sess.run(conv))
    print('cons:\n',sess.run(cons))
    print('contv:\n',sess.run(contv))
    print('conts:\n',sess.run(conts))

 

  • 我们可以把padding为VALID方式时的卷积核反卷积操作绘制出来,如下图:

 

三 反池化原理

  • 反池化属于池化的逆操作,是无法通过池化的结果还原出全部的原始数据,因为池化的过程只保留主要信息,舍去部分信息。如果想从池化后的这些主要信息恢复出全部信息,由于存在着信息缺失,这时只能通过补位来实现最大程度的信息完整。
  • 池化层常用的有最大池化和平均池化,其反池化也需要与其对应。
  • 平均池化比较简单。首先还原成原来的大小,然后将池化结果中的每个值都填入其对应于原始数据区域中的相应位置即可。如下图:
  •  

  • 最大池化的反池化会复杂一些。要求在池化过程中记录最大激活池的坐标位置,然后在反池化时,只把池化过程中最大激活值所在位置坐标的值激活,其它位置为0.当然,这个过程只是一种近似,因为在池化的过程中,除了最大值所在的位置,其他的值也是不为0的。如下图:
  •  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值