zoukankan      html  css  js  c++  java
  • nn.ConvTranspose2d 逆卷积 反卷积

    本文转摘于如下链接:
    逆卷积的详细解释ConvTranspose2d(fractionally-strided convolutions) https://www.cnblogs.com/wanghui-garcia/p/10791328.html
    pytorch官方手册:https://pytorch.org/docs/stable/nn.html?highlight=convtranspose#torch.nn.ConvTranspose2d
    ConvTranspose2d

    torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
    

    output_padding参数作用:https://www.cnblogs.com/wanghui-garcia/p/10791778.html


    1.首先先定义进行卷积的参数:

    输入特征图为高宽一样的Hin*Hin大小的x
    卷积核大小kernel_size
    步长stride
    padding填充数(填充0)
    输出特征图为Hout*Hout大小的y
    

    计算式子为:

    Hout = floor( Hin + 2*padding - kernel_size / stride) + 1

    2.然后实现上面的卷积的转置卷积

    定义其参数为:

    输入特征图为高宽一样的Hout*Hout大小的y
    卷积核大小kernel_size
    步长stride
    paddingnew 填充数(填充0)
    输出特征图为Hin*Hin大小的x
    

    逆卷积的过程主要分两步:

    对输入的特征图y进行变换,得到新的特征图ynew
    
    内部变换,与卷积时设置的stride相关
    外部变换,与卷积时设置的padding相关
    
    根据得到的特征图进行卷积即可
    

    1)对输入的特征图y进行变换,得到新的特征图ynew

    1》内部变换

    当卷积时设置的stride>1时,将对输入的特征图y进行插值操作(interpolation)。

    即需要在输入的特征图y的每个相邻值之间插入(stride-1)行和列0,因为特征图中能够插入的相邻位置有(height-1)个位置,所以此时得到的特征图的大小由HoutHout(Hout即height) 变为新的 Hout_newHout_new,即[Hout + (stride-1) * (Hout-1)] * [Hout + (stride-1) * (Hout-1)]

    2》外部变换

    为了实现由HoutHout大小的y逆卷积得到HinHin大小的x,还需要设置paddingnew的值为(kernel_size - padding - 1),这里的padding是卷积操作时设置的padding值

    所以计算式子变为:

    Hin = floor( [Hout_new + 2*paddingnew - kernel_size] / stride') + 1

    ⚠️该式子变换后,定义向下取整的分母stride'值为定值1

    Hout_new和paddingnew的值代入上面的式子,即变为:

    Hin = floor( Hout + (stride-1) * (Hout-1) + 2*(kernel_size - padding - 1) - kernel_size) + 1

    化简为:

    Hin = floor( (Hout - 1) * stride - 2*padding + kernel_size - 1) + 1

     = (Hout - 1) * stride - 2*padding + kernel_size
    

    这样式子使的卷积Conv2d和逆卷积ConvTranspose2d在初始化时具有相同的参数,而在输入和输出形状方面互为倒数。

    所以这个式子其实就是官网给出的式子:

    可见这里没考虑output_padding

    output_padding的作用:可见nn.ConvTranspose2d的参数output_padding的作用

    3.下面举例说明

    https://github.com/vdumoulin/conv_arithmetic#convolution-arithmetic

    1)当stride=1时,就不会进行插值操作,只会进行padding,举例说明:

    卷积操作为:

    蓝色为输入特征图HinHin=44,绿色为输出特征图HoutHout=22,卷积核kernel_size=3, stride=1

    根据式子Hout = floor( Hin + 2*padding - kernel_size / stride) + 1

    可得padding=0

    其对应的逆卷积操作为:

    蓝色为输入特征图HoutHout=22,绿色为输出特征图HinHin=44,卷积核kernel_size=3, stride=1

    卷积时的padding=0

    将这些值代入上面的式子Hin = (Hout - 1) * stride - 2*padding + kernel_size

    果然输入HoutHout=22能得到输出HinHin=44

    变形过程为:

    paddingnew = kernel_size - padding -1 = 3 -0 -1 = 2

    所以可见下方的蓝色最后的大小为77 = Hout + 2paddingnew = 2 + 2*2 = 6

    ⚠️这里可见是有padding的,为什么定义是为no padding呢?

    这是因为它对应的卷积操作的padding=0

    1)当stride=2时,进行插值和padding操作,举例说明:

    卷积操作为:

    蓝色为输入特征图HinHin=55,绿色为输出特征图HoutHout=33,卷积核kernel_size=3, stride=2

    根据式子Hout = floor( Hin + 2*padding - kernel_size / stride) + 1

    可得padding=1

    其对应的逆卷积操作为:

    蓝色为输入特征图HoutHout=33,绿色为输出特征图HinHin=55,卷积核kernel_size=3,stride=2

    卷积时的padding=1

    将这些值代入上面的式子Hin = (Hout - 1) * stride - 2*padding + kernel_size

    果然输入HoutHout=33能得到输出HinHin=55

    变形操作为:

    Hout_new = Hout + (stride-1) * (Hout-1) = 3 + (2-1)*(3-1) = 5

    paddingnew = kernel_size - padding -1 = 3 -1 -1 = 1

    所以可见下方的蓝色最后的大小为77 = Hout_new + 2paddingnew = 5 + 2*1 = 7

    ⚠️因为这里的逆卷积对应的卷积操作的padding= 1,所以这里不是no padding,而是padding

    output_padding参数######################################################################################################################
    output_padding参数######################################################################################################################
    output_padding参数######################################################################################################################

    使用前提:stride > 1

    补充:same卷积操作

    是通过padding使得卷积之后输出的特征图大小保持不变(相对于输入特征图),不代表得到的输出特征图的大小与输入特征图的大小完全相同,而是他们之间的比例保持为 输入特征图大小/输出特征图大小 = stride

    举例:

    比如输入特征图为66,stride=2, kernel_size = 3, 所以进行same卷机操作得输出特征图为33 (6/2 = 3)

    如果输入特征图为55,stride=2,kernel_size = 3,这时候设置padding = 1,那么也会得到输出特征图为33

    那么这样的情况就会导致在逆卷积时出现一个问题。

    问题:

    问题就是,不同大小的图片经过卷积运算能得到相同尺寸的输出,那么作为逆运算,同样的一张输入图像经过反卷积是否会有不同尺寸的合法输出?这样的话就存在争议了

    上面还只是进行same卷积的情况,如果考虑valid卷积,stride=2, kernel_size = 3,padding=0时,输入特征图为77和88的结果也是3*3

    解决争议的办法就是使用output_padding参数

    output_padding的作用是:

    当stride > 1时,Conv2d将多个输入形状映射到相同的输出形状。output_padding通过在一边有效地增加计算出的输出形状来解决这种模糊性。

    首先我们要认同一个前提:

    大多数情况下我们都希望经过卷积/反卷积处理后的图像尺寸比例与步长相等,即输入特征图大小/输出特征图大小 = stride,也就是same模式。

    所以我们只要通过添加output_padding这一参数来使得结果满足这一前提,那么输出的图片的大小就能够保证为输入图片*stride的大小,而不是任意可能的大小

    实现办法:

    因为pytorch将参数padding(注意与output_padding区别)建议设置为(kernel_size - 1)/2,由式子padding= kernel - 1 - padding转换而来

    那么根据式子:

    当我们希望得到输入特征图大小/输出特征图大小 = stride的话,代入上面的式子能够得到结果:

    padding = (kernel_size - stride + output_padding )/2

    所以为了让padding = (kernel_size - 1)/2,则output_padding应该取值为stride - 1,这样就能够满足输入特征图大小/输出特征图大小 = stride

    当然,你可以取别的值,这并不会影响到逆卷积的计算,但是在后面进行有关大小的操作时就很可能出现问题,因为输出的图片的大小并不能保证是 输入图片stride的大小,可能是任意正确的大小,如上面举的例子,可能是77或8*8等

  • 相关阅读:
    pdf.js-----后端返回utf-8数据流,前端处理数据展示pdf
    正则表达式之去除前后空格
    ng之邮箱校验
    ng-校验重复并提示具体重复内容
    input 数值框处理
    逻辑之不重复
    ng -----监听变化($scope.$watch())
    js中document的用法
    php中12个魔术方法
    php 中const和 define的区别
  • 原文地址:https://www.cnblogs.com/yanghailin/p/12331588.html
Copyright © 2011-2022 走看看