转置卷积是在卷积之后,对输出特征图进行卷积使恢复到原图大小。
首先看卷积操作:对于一个输入大小为5x5,卷积核大小为3x3,步长为1,padding为0,我们需要进行9次操作(input长 - kernel长+1)x(input宽 - kernel宽+1),输出大小为3x3。
如何用矩阵相乘表示呢?
首先我们把输入图像拉成25x1的向量,接着我们把3x3卷积核填充到5x5大小,填充的部分用0表示,如何填充呢?就是将卷积核未覆盖的区域全部填充为0,那么把卷积核拉伸成1x25大小,再将9个全部拼接成1个矩阵,这样就形成了9x25大小的矩阵,与一个25x1大小的输入图进行矩阵乘法。输出的结果为9x1,进行reshape为3x3。
而转置卷积,就是将9x25大小的卷积矩阵进行转置,变成了25x9,然后对输出的特征图9x1进行相乘,就变成了25x1,然后reshape,变成了5x5。即恢复到原来的大小。
看一下官方代码:
in_channels(int) – 输入通道数
out_channels(int) – 卷积产生的通道数
kerner_size(int or tuple) - 卷积核的大小
stride(int or tuple,optional) - 卷积步长,即要将输入扩大的倍数,默认为1
padding(int or tuple, optional) - 上下左右填充0的层数,默认为0
output_padding(int or tuple, optional) - 输出边补充0的层数,高宽都增加padding
groups(int, optional) – 从输入通道到输出通道的阻塞连接数
bias(bool, optional) - 如果bias=True,添加偏置
dilation(int or tuple, optional) – 卷积核元素之间的间距,默认为1
>>> input = torch.randn(1, 16, 12, 12)
>>> downsample = nn.Conv2d(16, 16, 3, stride=2, padding=1)
>>> upsample = nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1)
>>> h = downsample(input)
>>> h.size()
torch.Size([1, 16, 6, 6])
>>> output = upsample(h, output_size=input.size())
>>> output.size()
torch.Size([1, 16, 12, 12])
官方输出长和宽计算公式:
H out=(H in−1)×stride[0]−2×padding[0]+dilation[0]×(kernel_size[0]−1)+output_padding[0]+1
W out=(W in−1)×stride[1]−2×padding[1]+dilation[1]×(kernel_size[1]−1)+output_padding[1]+1