卷积与转置卷积——输出特征图边长公式推导

目录

一、公式

1.卷积

2.转置卷积

二、公式推导

1.卷积公式推导

2.转置卷积公式推导

3.代码演示


一、公式

1.卷积

H_{out}=\frac{(H_{in}+2\times Padding-KernelSize)}{Stride}+1

W_{out}=\frac{(W_{in}+2\times Padding-KernelSize)}{Stride}+1

2.转置卷积

H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

W_{out}=(W_{in}-1)\times Stride-2\times Padding+KernelSize

Pytorch中,转置卷积层参数还含有output_padding,用于解决输出大小不唯一(歧义)的问题,因此转置卷积公式稍有变化:

H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize+OutputPadding

W_{out}=(W_{in}-1)\times Stride-2\times Padding+KernelSize+OutputPadding

二、公式推导

1.卷积公式推导

为了直观,这里选择3\times 3的卷积核,输入大小为5\times 5

(1)Stride1Padding0时,输出特征图边长H_{out}(H_{out}=W_{out})大小为

H_{out}=\frac{(H_{in}+2\times Padding-KernelSize)}{Stride}+1=\frac{(5+2\times 0-3)}{1}+1=3

具体过程如下

(2)Stride2Padding0时,输出特征图边长H_{out}(H_{out}=W_{out})大小为

H_{out}=\frac{(H_{in}+2\times Padding-KernelSize)}{Stride}+1=\frac{(5+2\times 0-3)}{2}+1=2

(3)那么到底如何得到真正的公式呢?

我们可以先观察一下卷积的过程,一行一行看,可以发现输出特征图的每个小方块都代表卷积核在原特征图上的卷积之后的结果,那么卷积核在每一行移动的距离原特征图边长减去卷积核边长,即:

D=H_{in}-KernelSize

那么卷积核移动的次数就是每一行移动的距离除以每一次移动的步长,即:

N=\frac{D}{Stride}=\frac{H_{in}-KernelSize}{Stride}

这个也就是除去第一个卷积核卷积结果输出特征图的边长减去1,即:

N=H_{out}-1

那么,输出特征图的边长就是:

H_{out}=\frac{H_{in}-KernelSize}{Stride}+1

如果考虑padding的情况,则卷积区域则不再是输入特征图,其边长为:

H_{newin}=H_{in}+2\times Padding

*为什么padding需要乘以2,是因为padding的时候是在卷积图上下左右进行一样的操作,横向看是左边和右边各加了padding。

那么最终的输出特征图的边长就是:

H_{out}=\frac{H_{in}+2\times Padding-KernelSize}{Stride}+1

2.转置卷积公式推导

即卷积公式的逆过程:

(H_{out}-1)\times Stride=H_{in}+2\times Padding-KernelSize

(H_{out}-1)\times Stride-2\times Padding+KernelSize=H_{in}

由于卷积输入是反卷积输出卷积输出是反卷积输入,因此在反卷积这里需要对调:

(H_{in}-1)\times Stride-2\times Padding+KernelSize=H_{out}

H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

注意,这里的StridePadding是来自卷积操作,因为本来就是由卷积输出边长公式推导而来。

3.代码演示

定义一个网络,里面只有一个转置卷积层,输入通道是3,输入通道也是3,输入特征图大小是2\times 2,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=2padding=0,输出为torch.Size([1, 3, 5, 5]),因此输出大小为5\times 5

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 2-2\times 0+3=2-0+3=5

(2)Stride=2padding=1,输出为torch.Size([1, 3, 3, 3]),因此输出大小为3\times 3

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 2-2\times 1+3=2-2+3=3

(3)Stride=2padding=2,输出为torch.Size([1, 3, 1, 1]),因此输出大小为1\times 1

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 2-2\times 2+3=2-4+3=1

(4)Stride=1padding=0,输出为torch.Size([1, 3, 4, 4]),因此输出大小为4\times 4

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 1-2\times 0+3=1-0+3=4

(5)Stride=1padding=1,输出为torch.Size([1, 3, 2, 2]),因此输出大小为2\times 2

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 1-2\times 1+3=1-2+3=2

(6)Stride=1padding=2,输出为torch.Size([1, 3, 0, 0]),因此输出大小为0\times 0,提示太小了报错

公式推导:H_{out}=(H_{in}-1)\times Stride-2\times Padding+KernelSize

(2-1)\times 1-2\times 2+3=1-4+3=0

RuntimeError: Given input size per channel: (2 x 2). Calculated output size per channel: (0 x 0). Output size is too small...

由此验证完毕

悲恋花丶无心之人 CSDN认证博客专家 深度学习 神经网络 Pytorch
计算机视觉在读研究生,熟悉Pytorch,MXNet,TensorFlow,Keras等深度学习框架,主要涉及的领域有目标检测,语义分割,超分辨率重建,行人重识别等。
个人GitHub网址为:https://github.com/nickhuang1996
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值