转置卷积¶
Note
在语义分割中,我们期望输入和输出的空间维度相同,这样输出像素各通道可以保有输入像素同一位置上的分类结果。
但是卷积层和pooling层会使得高和宽越来越小,为了使空间维度增加,我们可以使用转置卷积。
基本操作¶
假设步幅为1且没有填充,那么 \(n_{h}\times{n_{w}}\) 的输入和 \(k_{h}\times{k_{w}}\) 的卷积核经过转置卷积后会产生 \((n_{h} + k_{h} - 1)\times(n_{w} + k_{w} - 1)\) 的输出。
如上图所示,转置卷积就是input中各数与kernel相乘,结果嵌入到相应的位置,最后相加。
import torch
from torch import nn
X = torch.tensor([[0., 1.], [2., 3.]]).reshape(1, 1, 2, 2)
K = torch.tensor([[0., 1.], [2., 3.]]).reshape(1, 1, 2, 2)
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, bias=False)
tconv.weight.data = K
tconv(X)
tensor([[[[ 0., 0., 1.],
[ 0., 4., 6.],
[ 4., 12., 9.]]]], grad_fn=<SlowConvTranspose2DBackward>)
填充和步幅¶
与常规卷积不同,填充被用于输出,如将高宽两侧填充指定为1时,转置卷积的输出中将删去第一和最后的行和列
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, padding=1, bias=False)
tconv.weight.data = K
tconv(X)
tensor([[[[4.]]]], grad_fn=<SlowConvTranspose2DBackward>)
步幅作用于输出,步幅的增加会导致输出高和宽的增加:
tconv = nn.ConvTranspose2d(1, 1, kernel_size=2, stride=2, bias=False)
tconv.weight.data = K
tconv(X)
tensor([[[[0., 0., 0., 1.],
[0., 0., 2., 3.],
[0., 2., 0., 3.],
[4., 6., 6., 9.]]]], grad_fn=<SlowConvTranspose2DBackward>)