Pytorch中的卷积与反卷积详解(conv2d和convTranspose2d)

卷积和反卷积是图片像素等矩阵计算在深度学习中常用的下采样(降维、压缩、提取特征)和上采样(升维、解压缩、扩充特征)操作。相比其他采样操作,卷积层可以通过学习更小规模的参数(卷积核)拟合图像特征(通过梯度反向传递即BP),效率远高于前一代神经网络(全链接即多层感知机)。

另外作为特征提取的常用操作,卷积在计算中可以改变图片计算后的通道,把参数压缩为数量更少的卷积核。相比上一代的全连接操作,能降低计算量的同时,充分整合图像的局部特征。

在torchn.nn中,卷积操作是一个函数,输入为一组图片或特征变量[n,c,w,h],输出也为一组变量[n,c,w,h].变量类型为tensor.

1.卷积-Conv2d

卷积可以压缩整合图片特征,让通道/宽/高分别为:[c,w,h]的特征图片通过Conv2d。变为更多的通道(维度)c,更小的尺寸W/H.

这里有几个参数比较重要:

  • padding

就是填充的意思,通过padding,可以填充图片的边缘,让图片的边缘的特征得到更充分的计算(不至于被截断)

  • kernel_size

卷积核尺寸,尺寸越大‘感受野’越大,及处理的特征单位越大,同时计算量也越大

  • stide

卷积核移动的步数,默认1步,增大步数会忽略局部细节计算,适用于高分辨率的计算提升

1.2 卷积操作及可视化

蓝色为输入,蓝色上的阴影为卷积核(kernel),绿色为输出,蓝色边缘的白色框为padding

  • padding=0,stride=1,kernel_size=3

image

尺寸从[4,4]->[2,2]

import torch
import torch.nn as nn

x = torch.randn(1,1,4,4)
l = nn.Conv2d(1,1,3)#Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1),padding=0)
y = l(x) # y.shape:[1,1,2,2]
  • padding=2,stride=1,kernel_size=4

image

尺寸从[5,5]->[6,6]

import torch
import torch.nn as nn

x = torch.randn(1,1,5,5)
l = nn.Conv2d(1,1,4,padding=2)#Conv2d(1, 1, kernel_size=4,stride=1,padding=2)
y = l(x) # y.shape:[1,1,6,6]

2.反卷积-ConvTranspose2d

转置卷积,也称为反卷积(deconvlution)和分部卷积(fractionally-strided convolution)。为卷积的一种逆操作,即把特征的维度解压缩。因此,输出向量的尺寸会放大。

函数形式如下:

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’)

2.1 操作及可视化

这里需要注意的是padding和stride和conv2d不同,padding不是蓝色的留白,是kernel像图像中心移动的单位。如下当padding=0时,卷积核刚好和输入边缘相交一个单位。因此pandding可以理解为卷积核向中心移动的步数。 同时stride也不再是kernel移动的步数,变为输入单元彼此散开的步数。

  • padding=0,kernel_size=3,stride=1

J66KbV.gif

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) # y.shape:[1,1,4,4]
  • padding=2,kernel_size=4,stride=1

J66UDx.gif

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) # y.shape:[1,1,5,5]
  • padding=2,kernel_size=3,stride=1

注意这个kernel也是向中心内移了2(对比padding=0),所以padding为2
在这里插入图片描述
图片

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) # y.shape:[1,1,5,5]
  • padding=0,kernel_size=3,stride=2

J6ceiD.gif

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) # y.shape:[1,1,5,5]
  • padding=1,kernel_size=3,stride=2

J6c8df.gif

import torch
import torch.nn as nn

x = torch.randn(1,1,3,3)
l = nn.ConvTranspose2d(1,1,3,stride=2,padding=1)#Conv2d(1, 1, kernel_size=3,stride=2,padding=1)
y = l(x) # y.shape:[1,1,5,5]

参考

https://pytorch.org/docs/master/nn.html#torch.nn.ConvTranspose2d
https://github.com/vdumoulin/conv_arithmetic

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐