上采样、下采样以及Pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convTranspose2d)

1. 上采样与下采样

1.1 上采样

上采样(upsampling),又叫放大图像、图像插值(interpolating),主要目的是放大原图像,从而可以显示在更高分辨率的显示设备上。上采样有3种常见的方法:双线性插值(bilinear),反卷积(Transposed Convolution),反池化(Unpooling)。

  • 插值法:最近邻算法、双线性插值算法、双三次插值算法(bicubic)
  • 反卷积:又称为转置卷积
  • 反池化:平均池化的反池化是把池化后的平均数字结果分布到池化前图像上的每个像素格子上。 最大池化的反池化是把池化后的最大数字结果填充到池化前图像上对应的像素格子上,而其他格子则填充0。

1.2 下采样

下采样(subsampled)或降采样(downsampled)或者称为缩小图像,它的主要目的有两个:1、使得图像符合显示区域的大小;2、生成对应图像的缩略图。

下采样一般为池化操作。池化最直观的作用便是降维,常见的池化有最大池化、平均池化和随机池化;池化层不需要训练参数。

2. 卷积函数——Conv2d

2.1 卷积函数说明

卷积操作可以压缩整合图片特征,让[通道, 宽, 高]分别为 [ c , h , w ] [c,h,w] [c,h,w]的特征图片通过Conv2d。变为更多的通道(维度) c c c,更小的尺寸 [ h , w ] [h,w] [h,w]。也就是说,当输入为一组图片 [ n , c , h , w ] [n,c,h,w] [n,c,h,w]格式时,输出也为 [ n , c , h , w ] [n,c,h,w] [n,c,h,w]格式。

卷积函数Conv2d定义形式如下所示。

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, 
groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

卷积函数参数说明:

  • in_channels (int) – 输入信号通道数(channels);
  • out_channels (int) – 输出信号通道数(channels);
  • kernel_size (int or tuple) – 卷积核的大小;卷积核尺寸,尺寸越大‘感受野’越大,及处理的特征单位越大,同时计算量也越大
  • stride (int or tuple, optional) – 卷积步长(默认为1);卷积核移动的步数,默认1步,增大步数会忽略局部细节计算,适用于高分辨率的计算提升
  • padding (int, tuple or str, optional) – 输入信号四周的填充,默认填充0。就是填充的意思,通过padding,可以填充图片的边缘,让图片的边缘的特征得到更充分的计算(不至于被截断)
  • padding_mode (string, optional) – ‘zeros’, ‘reflect’, ‘replicate’ or ‘circular’. Default: ‘zeros’;
  • dilation (int or tuple, optional) – 卷积核元素之间的间距,默认为1,也就是常规的卷积方式;
  • groups (int, optional) – 从输入通道到输出通道的阻塞连接数,默认为1;
  • bias (bool, optional) – 如果bias=True,添加偏置,默认为True;

卷积操作的输入与输出尺寸之间的关系如下所示。注意下列除法为 向下取正。简化版为: H o = ( H i + 2 p − d ∗ ( k − 1 ) − 1 ) / s + 1 H_o=(H_i+2p-d*(k-1) - 1)/s +1 Ho=(Hi+2pd(k1)1)/s+1
在这里插入图片描述

2.2 卷积操作可视化与举例

(1)举例一:padding=0,stride=1,kernel_size=3

假设padding=0,stride=1,kernel_size=3。下图中,蓝色为输入[4,4],蓝色上的阴影为卷积核[3,3],绿色为输出[2,2],蓝色边缘的白色框为padding。可视化效果如下。

在这里插入图片描述
代码表示形式如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,4,4) # [n,c,h,w]
l = nn.Conv2d(1,1,3)#Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1),padding=0)
y = l(x)

print(y.shape) # torch.Size([1, 1, 2, 2])

(2)举例二:padding=2,stride=1,kernel_size=4

假设padding=2,stride=1,kernel_size=4。下图中,蓝色为输入[5,5],蓝色上的阴影为卷积核[4,4],绿色为输出[6,6],蓝色边缘的白色框为padding[2,2]。可视化效果如下。
在这里插入图片描述
代码表示形式如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,5,5) # [n,c,h,w]
l = nn.Conv2d(1,1,4,padding=2)#Conv2d(1, 1, kernel_size=4,stride=1,padding=2)
y = l(x)

print(y.shape) # torch.Size([1, 1, 6, 6])

3. 反卷积(转置卷积)——convTranspose2d

反卷积(Deconvolution)的概念第一次出现是Zeiler在2010年发表的论文Deconvolutional networks中,但是并没有指定反卷积这个名字,反卷积这个术语正式的使用是在其之后的工作中。

转置卷积,也称为反卷积(deconvlution)和分部卷积(fractionally-strided convolution)。为卷积的逆操作,即把特征的维度压缩,但尺寸放大。注意它 不是真正意义上 的卷积的逆操作。通过反卷积,只能恢复原矩阵的大小,但并不能完全恢复原矩阵的数值

3.1 反卷积原理

所谓的反卷积,就是卷积的逆操作,反卷积就可以看成通过卷积核透视。如下图所示:

在这里插入图片描述
比如左上角的图,拿55举例,它的输出为[[55,110,55],[110,55,110],[55,55,110]]。我们将得到的四张特征图进行叠加(重合的地方其值相加),可以得到下图:
在这里插入图片描述

3.2 反卷积函数说明

该模块可视为Conv2d相对于其输入的梯度。卷积函数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', device=None, dtype=None)

反卷积参数说明如下,stride、padding和output_padding参数需要单独理解,其他大部分参数与卷积相似。

  • in_channels(int) – 输入信号的通道数;
  • out_channels(int) – 卷积产生的通道数;
  • kerner_size(int or tuple) - 卷积核的大小;
  • stride(int or tuple,optional) - 输入层之间的间隔,默认为1

stride=1时,输入层元素之间没有间隔,当stride=2时,输入层元素之间间隔为1,stride=3时,输入层元素之间间隔为2,以此类推。

  • padding(int or tuple, optional) - 卷积核与输入层相交的最少像素参数,默认为0,也就是说最少要相交1个点;

padding=0时,卷积核和输入层相交一个像素,当padding=1时,卷积核和输入层相交2个像素,依此类推;

  • output_padding(int or tuple, optional) - 输出数据每条边的填充0的个数,默认为0;

output_padding=0表示不进行填补,output_padding=1表示进行填补一圈0,等于2表示进行填补2圈0.

  • dilation(int or tuple, optional) – 卷积核元素之间的间距
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  • bias(bool, optional) - 如果bias=True,添加偏置,默认为True

反卷积操作的输入与输出尺寸之间的关系如下所示。从公式可以看出,它是卷积的反求关系,简化版: H o = H i ∗ 2 − 2 p + d ∗ ( k − 1 ) + o u t p u t _ p a d d i n g + 1 H_o=H_i *2-2p +d*(k-1)+output\_padding+1 Ho=Hi22p+d(k1)+output_padding+1

在这里插入图片描述

H o u t = ( H i n − 1 ) × s t r i d e [ 0 ] − 2 × p a d d i n g [ 0 ] + d i l a t i o n [ 0 ] × ( k e r n e l _ s i z e [ 0 ] − 1 ) + o u t p u t _ p a d d i n g [ 0 ] + 1 H_{out} =(H_{in} −1)×stride[0]−2×padding[0]+dilation[0]×(kernel\_size[0]−1)+output\_padding[0]+1 Hout=(Hin1)×stride[0]2×padding[0]+dilation[0]×(kernel_size[0]1)+output_padding[0]+1
W o u t = ( W i n − 1 ) × s t r i d e [ 1 ] − 2 × p a d d i n g [ 1 ] + d i l a t i o n [ 1 ] × ( k e r n e l _ s i z e [ 1 ] − 1 ) + o u t p u t _ p a d d i n g [ 1 ] + 1 W_{out}=(W_{in}−1)×stride[1]−2×padding[1]+dilation[1]×(kernel\_size[1]−1)+output\_padding[1]+1 Wout=(Win1)×stride[1]2×padding[1]+dilation[1]×(kernel_size[1]1)+output_padding[1]+1

3.3 反卷积操作可视化与举例

(1)举例一:padding=0,kernel_size=3,stride=1

padding = 0,表示蓝色的输入[2,2]与卷积核最少有(1,1)个像素相交,stride = 1,表示输入输入数据没有间隔。具体动态图视如下:
在这里插入图片描述
代码表示形式如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,2,2)
l = nn.ConvTranspose2d(1,1,3)#Conv2d(1, 1, kernel_size=3,stride=1,padding=0)
y = l(x) 

print(y.shape) # torch.Size([1, 1, 4, 4])

(2)举例二:padding=2,kernel_size=4,stride=1

padding = 2表示蓝色输入数据[6,6]与卷积核函最少交(3,3)个像素,stride=1表示输入数据没有间隔。具体动态图视如下:

在这里插入图片描述
代码表示如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,6,6)
l = nn.ConvTranspose2d(1,1,4,padding=2)#Conv2d(1, 1, kernel_size=4,stride=1,padding=2)
y = l(x)

print(y.shape) # torch.Size([1, 1, 5, 5])

(3)举例三:padding=2,kernel_size=3,stride=1

padding = 2表示蓝色输入数据[7,7]与卷积核函最少交(3,3)个像素,stride=1表示输入数据没有间隔。具体动态图视如下:

在这里插入图片描述

代码表示如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,7,7)
l = nn.ConvTranspose2d(1,1,3,padding=2)#Conv2d(1, 1, kernel_size=3,stride=1,padding=2)
y = l(x) 

print(y.shape) # torch.Size([1, 1, 5, 5])

(4)举例4:padding=0,kernel_size=3,stride=2

padding = 0表示蓝色输入数据[2,2]与卷积核函最少交(1,1)个像素,stride=2表示输入数据间隔1个像素就填充0值。具体动态图视如下:

在这里插入图片描述
代码表示如下:

import torch
import torch.nn as nn

x = torch.randn(1,1,2,2)
l = nn.ConvTranspose2d(1,1,3,stride=2,padding=0)#Conv2d(1, 1, kernel_size=3,stride=2,padding=0)
y = l(x) 

print(y.shape) # torch.Size([1, 1, 5, 5])

Conv2d参考链接:https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html?highlight=conv2d#torch.nn.Conv2d
ConvTranspose2d参考链接:https://pytorch.org/docs/1.11/generated/torch.nn.ConvTranspose2d.html?highlight=convtranspose2d#torch.nn.ConvTranspose2d

反卷积网络论文:https://www.matthewzeiler.com/mattzeiler/deconvolutionalnetworks.pdf

卷积动态图:https://github.com/vdumoulin/conv_arithmetic

PyTorch卷积采样convolutional downsampling)通常通过使用池化层(pooling layer)来实现。池化层可以减小特征图的空间尺寸,从而实现下采样的效果。以下是一个示例代码,演示如何在PyTorch使用池化层进行卷积采样: ```python import torch import torch.nn as nn # 定义一个简单的卷积神经网络 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1) self.pool = nn.MaxPool2d(kernel_size=2, stride=2) def forward(self, x): x = self.conv1(x) x = self.pool(x) return x # 创建网络实例 net = Net() # 创建一个随机输入张量,大小为[batch_size, channels, height, width] input_tensor = torch.randn(1, 3, 32, 32) # 将输入张量传递给网络进行前向计算 output_tensor = net(input_tensor) # 打印输出张量的尺寸 print(output_tensor.size()) ``` 在上面的示例,我们定义了一个简单的卷积神经网络(`Net`),其包含一个卷积层(`conv1`)和一个池化层(`pool`)。在前向计算过程,输入张量经过卷积层后,通过池化层进行采样操作。最后,我们打印输出张量的尺寸,可以看到在空间维度上进行了下采样。 需要注意的是,池化层的参数`kernel_size`和`stride`可以根据具体需求进行调整,它们分别指定了池化窗口的大小和滑动步长。在示例,我们使用了最大池化(`MaxPool2d`),还可以使用平均池化(`AvgPool2d`)等其他类型的池化层。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非晚非晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值