上采用、反卷积、上池化区别

对于Unet网络中的上采样,主要有三种实现形式:上采用、反卷积、上池化,通常情况应用的是反卷积。

1、Upsampling(上采样)

在FCN、U-net等网络结构中,涉及到了上采样:

上采样指的是: 任何可以让    图像变成更高分辨率    的技术(上池化、反卷积、插值等)

可以是  重采样、插值 :将输入图片进行 rescale 到一个想要的尺寸,而且计算每个点的像素点,使用如 双线性插值,等插值方法 对其余点进行插值来完成上采样过程。
 
 

2、上池化

Unpooling是在CNN中常用的来表示max pooling的逆操作。这是论文《Visualizing and Understanding Convolutional Networks》中产生的思想,如下图所示:

 

两者区别:

Unsampling 阶段没有使用Max Pooling的位置信息,复制最大值扩充Feature Map

UnPooling 阶段是在Max pooling的时候保留最大值的位置信息,用 0 扩充Feature Map

 

3、反卷积

卷积:                                                                                   反卷积:

                                                                               

 

卷积、反卷积的输入输出关系正好相反

如果不考虑通道以卷积运算的反向运算来计算反卷积运算的话,还可以通过离散卷积的方法来求反卷积。

反卷积 又被称为Transposed(转置) Convolution

卷积层的前向传播过程就是反卷积层的反向传播过程,

卷积层的反向传播过程就是反卷积层的前向传播过程。

因为卷积层的前向反向计算分别为乘 C和 CT,而反卷积层的前向反向计算分别为乘 CT和(CT)T ,所以它们的前向传播和反向传播刚好交换过来。

  1. 使用反卷积可以进行上采样

  2. 反卷积具有可供学习的参数,不需要利用插值方法

 
最大的区别在于反卷积过程是有 参数要进行学习 的(类似卷积过程), 理论上反卷积可以实现UnPooling和unSampling
(狭义的,见参考文献 https://blog.csdn.net/A_a_ron/article/details/79181108 ),只要卷积核的参数设置的合理。
广义的上采样:由于上采样是指将图像 上采样到更高分辨率的任何技术 ,因此我们可以讲:通过反卷积、UnPooling进行上采样
 
 

反卷积:

仅仅是将卷积变换过程中的步骤反向变换一次而已,通过将卷积核转置,与卷积后的结果再做一遍卷积,所以它还有一个名字叫做转置卷积。

代码示例:

'''
一 反卷积实例
'''
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))

反池化(上池化):

属于池化的逆操作,是无法通过池化的结果还原出全部的原始数据,因此池化的过程只保留主要信息,舍去部分信息。如果想从池化后的这些主要信息恢复出全部信息,由于存在着信息缺失,这时只能通过补位来实现最大程度的信息完整。

代码示例:

'''
二 反池化操作
'''


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)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值