zoukankan      html  css  js  c++  java
  • pytorch中的上采样(上采样,转置卷积,上池化,PixelShuffle)

    Upsample(上采样,插值)

    Upsample

    torch.nn.Upsample(size=Nonescale_factor=Nonemode='nearest'align_corners=None)

     Upsamples a given multi-channel 1D (temporal), 2D (spatial) or 3D (volumetric) data.

    对给定的多通道1D(时间)、2D(空间)或3D(容量)数据进行上采样。

    The input data is assumed to be of the form minibatch x channels x [optional depth] x [optional height] x width. Hence, for spatial inputs, we expect a 4D Tensor and for volumetric inputs, we expect a 5D Tensor.

    输入格式:

    一维数据 [N, C, W]

    二维数据 [N, C, H, W]

    三维数据 [N, C, D,  H, W]

    The algorithms available for upsampling are nearest neighbor and linear, bilinear, bicubic and trilinear for 3D, 4D and 5D input Tensor, respectively.

    Upsample可用的算法是最近邻和线性,双线性,双三次和三线性插值算法。

    One can either give a scale_factor or the target output size to calculate the output size. (You cannot give both, as it is ambiguous)

    可以给出scale_factor或目标输出大小来计算输出大小(不能同时给出两者)。 

    参数说明:

    size: (int or Tuple[int] or Tuple[intint] or Tuple[intintint]optional) – output spatial sizes

    scale_factor :(float or Tuple[float] or Tuple[floatfloat] or Tuple[floatfloatfloat],optional) – multiplier for spatial size. Has to match input size if it is a tuple.

    输出尺寸可以指定size,也可以通过缩放的倍数指定。

    mode: (stroptional) – the upsampling algorithm: one of 'nearest''linear''bilinear''bicubic' and 'trilinear'. Default: 'nearest'

    align_corners (booloptional) – if True, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. This only has effect when mode is 'linear''bilinear', or 'trilinear'. Default: False

    输入输出形状:

     注意:

    在align_corners = True的情况下,线性插值模式(线性,双线性,双三次和三线性)不会按比例对齐输出像素和输入像素,因此输出值可能取决于输入大小。 这是这些模式(0.3.1版之前)的默认行为。 从那时起,默认行为是align_corners = False。 有关如何影响输出的具体示例,请参见下文。

    关于align_corners的解释参考知乎这篇文章

    输入为:

      对它上采样两倍后,得到下图:

      首先介绍 align_corners=False,它是 pytorch 中 interpolate 的默认选项。这种设定下,我们认定像素值位于像素块的中心。首先观察绿色框内的像素,我们会发现它们严格遵守了 bilinear 的定义。而对于角上的四个点,其像素值保持了原图的值。边上的点则根据角点的值,进行了 bilinear 插值。所以,我们从全局来看,内部和边缘处采用了比较不同的规则。

     在 align_corners=True世界观里,像素值位于网格上,如上图所示:

     

      这里仔细的读者会发现,3*3 的图像上采两倍后,变成了 5*5。更广泛地来讲,对于输入尺寸是 (2x+1) * (2x+1) 的图片,其经过 align_corners=True 的上采样后,尺寸变为 (4x+1) * (4x+1)。所以虽然内容上整齐了,外在的数目上,却没了那种 2 的整数次幂的美感。(注:这里指定了输出为5x5)

    具体区别呢?
    查找pytorch论坛得图:

    • 当**align_corners = True**时,像素被视为网格的格子上的点,拐角处的像素对齐.可知是点之间是等间距的
    • 当**align_corners = False**时, 像素被视为网格的交叉线上的点, 拐角处的点依然是原图像的拐角像素,但是插值的点间却按照上图的取法取,导致点与点之间是不等距的

    如果要下采样/常规调整大小,则应使用interpolate()。

    UpsamplingNearest2d

    torch.nn.UpsamplingNearest2d(size=Nonescale_factor=None)

    UpsamplingBilinear2d

    torch.nn.UpsamplingBilinear2d(size=Nonescale_factor=None)

    ConvTranspose(转置卷积)

    torch.nn.ConvTranspose1d

    torch.nn.ConvTranspose1d(in_channelsout_channelskernel_sizestride=1padding=0output_padding=0groups=1bias=Truedilation=1padding_mode='zeros')

    对由多个输入平面组成的输入图像应用1D转置卷积算子。

    这个模块可以看作是相对于其输入的Conv1d的梯度。它也被称为分数步卷积或反卷积、去卷积(尽管它不是一个实际的数学上的反卷积操作)。

    Parameters:

    in_channels (int) – Number of channels in the input image

    out_channels (int) – Number of channels produced by the convolution

    kernel_size (int or tuple) – Size of the convolving kernel

    stride (int or tupleoptional) – Stride of the convolution. Default: 1 控制交叉相关的步幅。

    padding (int or tupleoptional) – dilation (kernel_size 1) padding zero-padding will be added to both sides of the input. Default: 0 控制两侧的隐式零填充量dilation (kernel_size 1) padding。 有关详细信息,请参见下面的注释。

    output_padding (int or tupleoptional) – Additional size added to one side of the output shape. Default: 0 控制添加到输出形状一侧的附加大小。详情请参阅下面的说明。

    groups (intoptional) – Number of blocked connections from input channels to output channels. Default: 1 控制输入和输出之间的连接。 in_channels和out_channels必须都可以被groups整除。

    bias (booloptional) – If True, adds a learnable bias to the output. Default: True

    dilation (int or tupleoptional) – Spacing between kernel elements. Default: 1 controls the spacing between the kernel points; also known as the à trous algorithm. It is harder to describe, but this link has a nice visualization of what dilation does. 控制卷积核核点之间的间隔,也被称为à trous算法。这很难描述,但是这个链接很好地展示了膨胀的作用。

    注意: 

    Depending of the size of your kernel, several (of the last) columns of the input might be lost, because it is a valid cross-correlation, and not a full cross-correlation. It is up to the user to add proper padding.

    根据卷积核的大小,输入的(最后一列)几列可能会丢失,因为它是有效的互相关,而不是完整的互相关。 用户可以自行添加适当的填充。

    The padding argument effectively adds dilation * (kernel_size - 1) - padding amount of zero padding to both sides of the input. This is set so that when a Conv1d and a ConvTranspose1d are initialized with same parameters, they are inverses of each other in regard to the input and output shapes. However, when stride > 1, Conv1d maps multiple input shapes to the same output shape. output_padding is provided to resolve this ambiguity by effectively increasing the calculated output shape on one side. Note that output_padding is only used to find output shape, but does not actually add zero-padding to output.

    padding参数有效地将diation *(kernel_size-1)-padding个零填充的填充量添加到输入的两侧。 进行设置是为了使Conv1d和ConvTranspose1d用相同的参数初始化时,它们在输入和输出形状方面彼此相反。 但是,当stride> 1时,Conv1d会将多个输入形状映射到相同的输出形状。 提供output_padding可以通过有效地增加一侧的计算输出形状来解决这种歧义。 请注意,output_padding仅用于查找输出形状,但实际上并未向输出添加零填充。

    In some circumstances when using the CUDA backend with CuDNN, this operator may select a nondeterministic algorithm to increase performance. If this is undesirable, you can try to make the operation deterministic (potentially at a performance cost) by setting torch.backends.cudnn.deterministic True. Please see the notes on Reproducibility for background.

    在某些情况下,将CUDA后端与CuDNN一起使用时,该运算符可能会选择不确定的算法来提高性能。 如果不希望这样做,则可以通过将torch.backends.cudnn.deterministic = True设置为确定性操作(可能以性能为代价)。 请参阅有关可重现性的说明作为背景。

    输入输出形状:

    Input: (N, Cin, Lin)

    Output: (N,Cout,Lout) where

    Lout=(Lin−1)×stride−2×padding+dilation×(kernel_size−1)+output_padding+1

    Variables

    ConvTranspose1d.weight (Tensor)

    ConvTranspose1d.bias (Tensor)

    torch.nn.ConvTranspose2d

    torch.nn.ConvTranspose2d(in_channelsout_channelskernel_sizestride=1padding=0output_padding=0groups=1bias=Truedilation=1padding_mode='zeros')

    The parameters kernel_sizestridepaddingoutput_padding can either be:

    • a single int – in which case the same value is used for the height and width dimensions 高宽两个方向参数相同

    • tuple of two ints – in which case, the first int is used for the height dimension, and the second int for the width dimension分别为高宽两个方向指定参数

    Shape:

    • Input: (N,Cin​,Hin​,Win​)
    • Output: (N,Cout​,Hout​,Wout​) where

    Hout=(Hin​−1)×stride[0]−2×padding[0]+dilation[0]×(kernel_size[0]−1)+output_padding[0]+1

    Hout=(Hin​−1)×stride[0]−2×padding[0]+dilation[0]×(kernel_size[0]−1)+output_padding[0]+1

    torch.nn.ConvTranspose3d

    torch.nn.ConvTranspose3d(in_channelsout_channelskernel_sizestride=1padding=0output_padding=0groups=1bias=Truedilation=1padding_mode='zeros')

    ConvTranspose2d原理,深度网络如何进行上采样?

     

    unpooling(上池化)

    另一种上采样的方法是,参考代码:segnet_pytorch

            # Stage 5
            x51 = F.relu(self.bn51(self.conv51(x4p)))
            x52 = F.relu(self.bn52(self.conv52(x51)))
            x53 = F.relu(self.bn53(self.conv53(x52)))
            #这个id5记录的是池化操作时最大值的index,其要设置参数return_indices为True
            x5p, id5 = F.max_pool2d(x53,kernel_size=2, stride=2,return_indices=True)
     
     
            # Stage 5d
            #这个是进行最大值上采样的函数,其是根据id5来把值放到什么位置,其它位置没有值的地方
            #补0
            x5d = F.max_unpool2d(x5p, id5, kernel_size=2, stride=2)
            x53d = F.relu(self.bn53d(self.conv53d(x5d)))
            x52d = F.relu(self.bn52d(self.conv52d(x53d)))
            x51d = F.relu(self.bn51d(self.conv51d(x52d)))

    测试:

    #测试上采样
    m=nn.MaxPool2d((3,3),stride=(1,1),return_indices=True)
    upm=nn.MaxUnpool2d((3,3),stride=(1,1))
    data4=torch.randn(1,1,3,3)
    output5,indices=m(data4)
    output6=upm(output5,indices)
     
    print('
    data4:',data4,
          '
    maxPool2d',output5,
          '
    indices:',indices,
          '
    output6:',output6)

    其输出为:

    data4: tensor([[[[ 2.3151, -1.0391,  0.1074],
              [ 1.9360,  0.2524,  2.3735],
              [-0.1151,  0.4684, -1.8800]]]]) 
    maxPool2d tensor([[[[2.3735]]]]) 
    indices: tensor([[[[5]]]]) 
    output6: tensor([[[[0.0000, 0.0000, 0.0000],
              [0.0000, 0.0000, 2.3735],
              [0.0000, 0.0000, 0.0000]]]])

    通过转置卷积或upsample+卷积的方式上采样:

    def upconv2x2(in_channels, out_channels, mode='transpose'):
        if mode == 'transpose':
            # 这个上采用需要设置其输入通道,输出通道.其中kernel_size、stride
            # 大小要跟对应下采样设置的值一样大小。这样才可恢复到相同的wh。这里时反卷积 
            # 操作。
            return nn.ConvTranspose2d(
                in_channels,
                out_channels,
                kernel_size=2,
                stride=2)
        else:
            # out_channels is always going to be the same
            # as in_channels
            # 这里不会改变通道数,其中scale_factor是上采用的放大因子,其是相对于当前的
            # 输入大小的倍数
            return nn.Sequential(
                nn.Upsample(mode='bilinear', scale_factor=2, align_corners=True))
            # 这里的代码是在这里设置多一个卷积,这样子就起到了可以修改其输出通道的功能 
            # 了。
            # 相当于功能跟ConvTranspose2d()差不多,只是上采样的方法不同
            conv1x1((in_channels, out_channels))
     
     
    def conv1x1(in_channels, out_channels, groups=1):
        return nn.Sequential(nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size=1,
            groups=groups,
            stride=1),
        nn.BatchNorm2d(out_channels))

     PixelShuffle

    在PyTorch中,上采样的层被封装在torch.nn中的Vision Layers里面,一共有4种:

    • ① PixelShuffle
    • ② Upsample
    • ③ UpsamplingNearest2d
    • ④ UpsamplingBilinear2d

    该类定义如下:

    class torch.nn.PixleShuffle(upscale_factor)

    这里的upscale_factor就是放大的倍数,数据类型为int。

    以四维输入(N,C,H,W)为例,Pixelshuffle会将为(∗,r2C,H,W)的Tensor给reshape成(∗,C,rH,rW)的Tensor。形式化地说,它的输入输出的shape如下:

    输入:(N,C x upscale_factor2,H,W)

    输出:(N,C ,Hx upscale_factor,Wx upscale_factor)

    相当于将特征图转化为图片像素。

    >>> ps = nn.PixelShuffle(3)
    >>> input = torch.tensor(1, 9, 4, 4)
    >>> output = ps(input)
    >>> print(output.size())
    torch.Size([1, 1, 12, 12])
  • 相关阅读:
    pandas高效实现条件逻辑
    Python教程:文件、异常处理和其他
    最终初学者指南,以数据科学用例赢得分类黑客马拉松
    用Nvidia Jetson Nano 2GB和Python构建一个价值60美元的人脸识别系统
    一幅图像能顶16x16字!——用于大规模图像缩放识别的变压器(对ICLR 2021年论文的简要回顾)
    接缝雕刻算法:一种看似不可能的图像大小调整方法
    apache与nginx的优缺点的比较
    php5与php7的区别
    git基本的命令大全
    redis和membercache的区别
  • 原文地址:https://www.cnblogs.com/jiangkejie/p/12919155.html
Copyright © 2011-2022 走看看