ConvTranspose2d(逆卷积)的原理和计算

简介: ConvTranspose2d(逆卷积)的原理和计算


原理


计算公式


Keras中的Conv2DTranspose详解


实例


pytorch中的ConvTranspose2d参数详解


实例


缺点


原理

解释什么是逆卷积,先得明白什么是卷积。

先说卷积:对于一个图片A,设定它的高度和宽度分别为Height,Width,通道数为Channels。 然后我们用卷积核(kernel * kernel)去做卷积,(这里设定卷积核为正方形,实际长方形也可以类推,相信我,不会很难),步长为stride(同样的,不区分高宽方向),做padding。卷积后得到B。


重复上面的话就是利用一个卷积操作将A变成B。


那么,在这个前提下,逆卷积就是将B变成A。


那么怎么规定卷积核这些参数呢,这些又是什么意思?


对于卷积操作,我不多说了,这里不做解释。而且我们应该比较清楚如何从输入的图片大小格式等得到新的图片大小,或许有的人熟悉用特征图来代替图片。

对于逆卷积操作,卷积核的设置就是和卷积操作相同。如:给定一个特征图x,并输入卷积核设置。我们就是想得到一个特征图y经过输入的卷积核进行卷积,然后得到特征图x,这里我们要求的就是特征图y。


写到这里大家应该比较理解我为什么把它翻译成逆卷积了吧。

如果不懂,也没事,可以看下面的例子。


举个例子:

tt.png

上面这个是一个卷积操作。

我们输入的特征图为:x: 44channels_in,channels_in表示通道数

卷积核设置:无padding, kernel size为3*3, 步长stride 为1,

输出的特征图为y,2 * 2 * channels_out,channels_out也是通道数。


逆卷积操作的输入就是特征图y, 卷积核设置同上。要求上面的特征图x。


这里先给出这个对应逆卷积的说明图。后面给出泛化的说明。


tt.png

tt.png

计算公式

shape:

输入: (N,C_in,H_in,W_in)

输出: (N,C_out,H_out,W_out)


H_{out}=(H_{in}-1)*stride[0]-2*padding[0]+kernel_size[0]+output_padding[0]


W_{out}=(W_{in}-1)*stride[1]-2*padding[1]+kernel_size[1]+output_padding[1]


输入特征图:3 × 3

输入卷积核参数:kernel为3 × 3 , stride为2, padding为1,output_padding为1

新的特征图A’: (3-1)×2-2+3+1=6 。


所以输出的特征图大小:6×6


这样就实现了将特征图放大一倍。


Keras中的Conv2DTranspose详解

tf.keras.layers.Conv2DTranspose(
    filters, kernel_size, strides=(1, 1), padding='valid',
    output_padding=None, data_format=None, dilation_rate=(1, 1), activation=None,
    use_bias=True, kernel_initializer='glorot_uniform',
    bias_initializer='zeros', kernel_regularizer=None,
    bias_regularizer=None, activity_regularizer=None, kernel_constraint=None,
    bias_constraint=None, **kwargs
)

数:


filters:整数,输出空间的维数(即卷积中的滤波器数).

kernel_size:一个元组或2个正整数的列表,指定过滤器的空间维度;可以是单个整数,以指定所有空间维度的相同值.

strides:一个元组或2个正整数的列表,指定卷积的步幅;可以是单个整数,以指定所有空间维度的相同值.

padding:可以是一个"valid"或"same"(不区分大小写).

output_padding:一个由2个整数组成的整数或元组/列表,指定沿输出张量的高度和宽度填充的数量。可以是单个整数,为所有空间维度指定相同的值。给定维度上的输出填充量必须低于同一维度上的步长。如果设置为None(默认),输出形状将被推断。

data_format:一个字符串,可以是一个channels_last(默认)或channels_first,表示输入中维度的顺序.channels_last对应于具有形状(batch, height, width, channels)的输入,而channels_first对应于具有形状(batch, channels, height, width)的输入.

dilation_rate:一个由2个整数组成的整数或元组/列表,指定用于膨胀卷积的膨胀率。可以是单个整数,为所有空间维度指定相同的值。目前,指定任何dilation_rate值!= 1与指定任何stride值!= 1是不兼容的。

activation:激活功能,将其设置为“None”以保持线性激活.

use_bias:Boolean,表示该层是否使用偏差.

kernel_initializer:卷积内核的初始化程序.

bias_initializer:偏置向量的初始化器,如果为None,将使用默认初始值设定项.

kernel_regularizer:卷积内核的可选正则化器.

bias_regularizer:偏置矢量的可选正则化器.

activity_regularizer:输出的可选正则化函数.

kernel_constraint:由Optimizer更新后应用于内核的可选投影函数(例如,用于实现层权重的范数约束或值约束);该函数必须将未投影的变量作为输入,并且必须返回投影变量(必须具有相同的形状);在进行异步分布式培训时,使用约束是不安全的.

bias_constraint:由Optimizer更新后应用于偏差的可选投影函数.

实例


def get_model():
    inputs = Input(shape=(64, 64, 3))
    conv_1 = Conv2D(1, (3, 3), strides=(1, 1), padding='same')(inputs)
    act_1 = Activation('relu')(conv_1)
    conv_2 = Conv2D(64, (3, 3), strides=(1, 1), padding='same')(act_1)
    act_2 = Activation('relu')(conv_2)
    deconv_1 = Conv2DTranspose(64, (3, 3), strides=(1, 1), padding='same')(act_2)
    act_3 = Activation('relu')(deconv_1)
    merge_1 = concatenate([act_3, act_1], axis=3)
    deconv_2 = Conv2DTranspose(1, (3, 3), strides=(1, 1), padding='same')(merge_1)
    act_4 = Activation('relu')(deconv_2)
    model = Model(inputs=[inputs], outputs=[act_4])
    model.compile(optimizer='adadelta', loss=dice_coef_loss, metrics=[dice_coef])
    return model

pytorch中的ConvTranspose2d参数详解

class torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)


说明


stride: 控制相关系数的计算步长

dilation: 用于控制内核点之间的距离,详细描述在这里

groups: 控制输入和输出之间的连接: group=1,输出是所有的输入的卷积;group=2,此时相当于有并排的两个卷积层,每个卷积层计算输入通道的一半,并且产生的输出是输出通道的一半,随后将这两个输出连接起来。


参数kernel_size,stride,padding,dilation数据类型: 可以是一个int类型的数据,此时卷积height和width值相同; 也可以是一个tuple数组(包含来两个int类型的数据),第一个int数据表示height的数值,第二个int类型的数据表示width的数值。


注意


由于内核的大小,输入的最后的一些列的数据可能会丢失。因为输入和输出是不是完全的互相关。因此,用户可以进行适当的填充(padding操作)。


参数:


in_channels(int) – 输入信号的通道数

out_channels(int) – 卷积产生的通道数

kerner_size(int or tuple) - 卷积核的大小

stride(int or tuple,optional) - 卷积步长

padding(int or tuple, optional) - 输入的每一条边补充0的层数

output_padding(int or tuple, optional) - 输出的每一条边补充0的层数

dilation(int or tuple, optional) – 卷积核元素之间的间距

groups(int, optional) – 从输入通道到输出通道的阻塞连接数

bias(bool, optional) - 如果bias=True,添加偏置


实例

ConvTranspose2d在UNet的应用:


import torch.nn as nn

import torch

import torch.nn as nn
import torch
from torch import autograd
#把常用的2个卷积操作简单封装下
class DoubleConv(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(DoubleConv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_ch, out_ch, 3, padding=1),
            nn.BatchNorm2d(out_ch), #添加了BN层
            nn.ReLU(inplace=True),
            nn.Conv2d(out_ch, out_ch, 3, padding=1),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(inplace=True)
        )
    def forward(self, input):
        return self.conv(input)
class Unet(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(Unet, self).__init__()
        self.conv1 = DoubleConv(in_ch, 64)
        self.pool1 = nn.MaxPool2d(2)
        self.conv2 = DoubleConv(64, 128)
        self.pool2 = nn.MaxPool2d(2)
        self.conv3 = DoubleConv(128, 256)
        self.pool3 = nn.MaxPool2d(2)
        self.conv4 = DoubleConv(256, 512)
        self.pool4 = nn.MaxPool2d(2)
        self.conv5 = DoubleConv(512, 1024)
        # 逆卷积,也可以使用上采样(保证k=stride,stride即上采样倍数)
        self.up6 = nn.ConvTranspose2d(1024, 512, 2, stride=2)
        self.conv6 = DoubleConv(1024, 512)
        self.up7 = nn.ConvTranspose2d(512, 256, 2, stride=2)
        self.conv7 = DoubleConv(512, 256)
        self.up8 = nn.ConvTranspose2d(256, 128, 2, stride=2)
        self.conv8 = DoubleConv(256, 128)
        self.up9 = nn.ConvTranspose2d(128, 64, 2, stride=2)
        self.conv9 = DoubleConv(128, 64)
        self.conv10 = nn.Conv2d(64, out_ch, 1)
    def forward(self, x):
        c1 = self.conv1(x)
        p1 = self.pool1(c1)
        c2 = self.conv2(p1)
        p2 = self.pool2(c2)
        c3 = self.conv3(p2)
        p3 = self.pool3(c3)
        c4 = self.conv4(p3)
        p4 = self.pool4(c4)
        c5 = self.conv5(p4)
        up_6 = self.up6(c5)
        merge6 = torch.cat([up_6, c4], dim=1)
        c6 = self.conv6(merge6)
        up_7 = self.up7(c6)
        merge7 = torch.cat([up_7, c3], dim=1)
        c7 = self.conv7(merge7)
        up_8 = self.up8(c7)
        merge8 = torch.cat([up_8, c2], dim=1)
        c8 = self.conv8(merge8)
        up_9 = self.up9(c8)
        merge9 = torch.cat([up_9, c1], dim=1)
        c9 = self.conv9(merge9)
        c10 = self.conv10(c9)
        out = nn.Sigmoid()(c10)
        return out

缺点

在基于CNN的超分辨率中,经常在最后一层使用stride>1的deconv layer,而这会造成棋盘格噪声。如下图所示


tt.png

具体产生原因

上面的黑格子是表示原始图像中的某一个像素点,白色的表示转置卷积中的stride,一般是用0去填充。下面一层就是deconv生成的图像。可以看到stride不能整除size的时候,就会出现棋盘格效应(当然,就算整除也不能完全消除)。

 

tt.png


tt.png

如何避免呢?

采用一般的插值算法(NN或bilinear)先把图像放大到目标分辨率,再用普通的conv去做计算,替代deconv layer。

 

最后效果tt.png

目录
相关文章
|
机器学习/深度学习
普通卷积、分组卷积和深度分离卷积概念以及参数量计算
普通卷积、分组卷积和深度分离卷积概念以及参数量计算
1038 0
普通卷积、分组卷积和深度分离卷积概念以及参数量计算
|
1月前
|
机器学习/深度学习 存储 缓存
窥探向量乘矩阵的存内计算原理—基于向量乘矩阵的存内计算
窥探向量乘矩阵的存内计算原理—基于向量乘矩阵的存内计算
27 0
|
1月前
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
78 1
|
8月前
|
机器学习/深度学习 传感器 缓存
可分离高斯神经网络:结构、分析和函数逼近
可分离高斯神经网络:结构、分析和函数逼近
106 0
|
机器学习/深度学习 存储 编解码
深度学习基础入门篇[9.3]:卷积算子:空洞卷积、分组卷积、可分离卷积、可变性卷积等详细讲解以及应用场景和应用实例剖析
深度学习基础入门篇[9.3]:卷积算子:空洞卷积、分组卷积、可分离卷积、可变性卷积等详细讲解以及应用场景和应用实例剖析
154 0
|
机器学习/深度学习 编解码 数据可视化
深度学习基础入门篇[9.2]:卷积之1*1 卷积(残差网络)、2D/3D卷积、转置卷积数学推导、应用实例
深度学习基础入门篇[9.2]:卷积之1*1 卷积(残差网络)、2D/3D卷积、转置卷积数学推导、应用实例
深度学习基础入门篇[9.2]:卷积之1*1 卷积(残差网络)、2D/3D卷积、转置卷积数学推导、应用实例
|
编解码 C++ 计算机视觉
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(二)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
212 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(二)
|
编解码 计算机视觉 C++
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(一)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
154 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(一)
|
编解码 计算机视觉 C++
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(三)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
1266 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(三)
|
机器学习/深度学习 存储 算法
PyTorch中的傅立叶卷积:通过FFT有效计算大核卷积的数学原理和代码实现
PyTorch中的傅立叶卷积:通过FFT有效计算大核卷积的数学原理和代码实现
369 0
PyTorch中的傅立叶卷积:通过FFT有效计算大核卷积的数学原理和代码实现

热门文章

最新文章