目录
一、公式
1.卷积
2.转置卷积
在Pytorch中,转置卷积层参数还含有output_padding,用于解决输出大小不唯一(歧义)的问题,因此转置卷积公式稍有变化:
二、公式推导
1.卷积公式推导
为了直观,这里选择的卷积核,输入大小为
(1)Stride为1,Padding为0时,输出特征图边长大小为
具体过程如下
(2)Stride为2,Padding为0时,输出特征图边长大小为
(3)那么到底如何得到真正的公式呢?
我们可以先观察一下卷积的过程,一行一行看,可以发现输出特征图的每个小方块都代表卷积核在原特征图上的卷积之后的结果,那么卷积核在每一行移动的距离是原特征图边长减去卷积核边长,即:
那么卷积核移动的次数就是每一行移动的距离除以每一次移动的步长,即:
这个也就是除去第一个卷积核卷积结果后输出特征图的边长再减去1,即:
那么,输出特征图的边长就是:
如果考虑padding的情况,则卷积区域则不再是输入特征图,其边长为:
*为什么padding需要乘以2,是因为padding的时候是在卷积图上下左右进行一样的操作,横向看是左边和右边各加了padding。
那么最终的输出特征图的边长就是:
2.转置卷积公式推导
即卷积公式的逆过程:
由于卷积输入是反卷积输出,卷积输出是反卷积输入,因此在反卷积这里需要对调:
注意,这里的Stride和Padding是来自卷积操作,因为本来就是由卷积输出边长公式推导而来。
3.代码演示
定义一个网络,里面只有一个转置卷积层,输入通道是3,输入通道也是3,输入特征图大小是,3通道,1张,因此Size是(1,3,2,2)
import torch
from torch.nn import Module
from torch import nn
class Net(Module):
def __init__(self):
super(Net, self).__init__()
# outsize=(2-1)*2-2*1+3=3
# outsize=(2-1)*1-2*1+3=2
# outsize=(2-1)*1-2*0+3=4
# outsize=(2-1)*2-2*0+3=5
self.trans_conv = nn.ConvTranspose2d(
in_channels=3,
out_channels=3,
kernel_size=3,
stride=2,
padding=0)
def forward(self, x):
x = self.trans_conv(x)
return x
model = Net()
x = torch.ones((1, 3, 2, 2))
print(model(x).size())
验证:
(1)Stride=2,padding=0,输出为torch.Size([1, 3, 5, 5]),因此输出大小为
公式推导:
(2)Stride=2,padding=1,输出为torch.Size([1, 3, 3, 3]),因此输出大小为
公式推导:
(3)Stride=2,padding=2,输出为torch.Size([1, 3, 1, 1]),因此输出大小为
公式推导:
(4)Stride=1,padding=0,输出为torch.Size([1, 3, 4, 4]),因此输出大小为
公式推导:
(5)Stride=1,padding=1,输出为torch.Size([1, 3, 2, 2]),因此输出大小为
公式推导:
(6)Stride=1,padding=2,输出为torch.Size([1, 3, 0, 0]),因此输出大小为,提示太小了报错
公式推导:
RuntimeError: Given input size per channel: (2 x 2). Calculated output size per channel: (0 x 0). Output size is too small...
由此验证完毕