如何将3D卷积编码器层改为反卷积层以匹配编码器空间尺寸变化率?
我有一个由编码器和解码器组成的3D卷积网络,想在解码器部分把编码器用的卷积层改成反卷积层,让反卷积层按编码器的逆速率增大特征图空间尺寸,同时减少通道数。
编码器里的卷积层序列如下:
Conv_layer = nn.Sequential( BasicConv3d(64, 64, kernel_size=1, stride=1), SepConv3d(64, 192, kernel_size=3, stride=1, padding=1), nn.MaxPool3d(kernel_size=(1,3,3), stride=(1,2,2), padding=(0,1,1)), )
用到的卷积层定义:
class BasicConv3d(nn.Module): def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0): super(BasicConv3d, self).__init__() self.conv = nn.Conv3d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding, bias=False) self.bn = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu = nn.ReLU() def forward(self, x): x = self.conv(x) x = self.bn(x) x = self.relu(x) return x class SepConv3d(nn.Module): def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0): super(SepConv3d, self).__init__() self.conv_s = nn.Conv3d(in_planes, out_planes, kernel_size=(1,kernel_size,kernel_size), stride=(1,stride,stride), padding=(0,padding,padding), bias=False) self.bn_s = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu_s = nn.ReLU() self.conv_t = nn.Conv3d(out_planes, out_planes, kernel_size=(kernel_size,1,1), stride=(stride,1,1), padding=(padding,0,0), bias=False) self.bn_t = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu_t = nn.ReLU() def forward(self, x): x = self.conv_s(x) x = self.bn_s(x) x = self.relu_s(x) x = self.conv_t(x) x = self.bn_t(x) x = self.relu_t(x) return x
请问怎么修改上述层的kernel_size、stride和padding参数,改成反卷积层,实现和编码器逆速率一致的特征图空间尺寸增大?
要实现编码器的逆过程,核心是让反卷积的输出尺寸匹配编码器的输入尺寸,同时通道数反向调整(编码器升通道,解码器降通道)。以下是具体修改方案:
1. 替换卷积层为反卷积层
把原代码中的nn.Conv3d替换为nn.ConvTranspose3d,同时根据逆过程调整参数。反卷积的stride对应编码器下采样的步长,kernel_size和padding配合保证尺寸精准匹配。
(1)重构BasicConv3d为BasicDeconv3d
编码器中该层仅调整通道(无尺寸变化),解码器中需反转通道方向,参数保持不变即可:
class BasicDeconv3d(nn.Module): def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0, output_padding=0): super(BasicDeconv3d, self).__init__() self.deconv = nn.ConvTranspose3d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding, output_padding=output_padding, bias=False) self.bn = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu = nn.ReLU() def forward(self, x): x = self.deconv(x) x = self.bn(x) x = self.relu(x) return x
解码器中调用:BasicDeconv3d(64, 64, kernel_size=1, stride=1)
(2)重构SepConv3d为SepDeconv3d
编码器中该层仅升通道(无尺寸变化),解码器中反转通道方向,参数保持stride=1、padding=1:
class SepDeconv3d(nn.Module): def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0, output_padding=0): super(SepDeconv3d, self).__init__() # 空间维度反卷积:对应编码器的conv_s self.deconv_s = nn.ConvTranspose3d(in_planes, out_planes, kernel_size=(1,kernel_size,kernel_size), stride=(1,stride,stride), padding=(0,padding,padding), output_padding=(0,output_padding,output_padding), bias=False) self.bn_s = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu_s = nn.ReLU() # 时间维度反卷积:对应编码器的conv_t self.deconv_t = nn.ConvTranspose3d(out_planes, out_planes, kernel_size=(kernel_size,1,1), stride=(stride,1,1), padding=(padding,0,0), output_padding=(output_padding,0,0), bias=False) self.bn_t = nn.BatchNorm3d(out_planes, eps=1e-3, momentum=0.001, affine=True) self.relu_t = nn.ReLU() def forward(self, x): x = self.deconv_s(x) x = self.bn_s(x) x = self.relu_s(x) x = self.deconv_t(x) x = self.bn_t(x) x = self.relu_t(x) return x
解码器中调用:SepDeconv3d(64, 64, kernel_size=3, stride=1, padding=1)
(3)替换MaxPool3d为反卷积(实现上采样)
编码器的MaxPool3d是下采样操作(时间维度尺寸不变,空间维度缩小为1/2),解码器需用反卷积实现逆过程:
kernel_size、stride、padding直接复用原池化层参数- 通道数从192降至64
output_padding设为(0,0,0)(因输入是偶数倍下采样,无需额外补边)
2. 解码器完整序列
按编码器的逆顺序组合层(编码器:Conv→SepConv→MaxPool,解码器:MaxPool逆→SepDeconv→BasicDeconv):
Deconv_layer = nn.Sequential( # 对应MaxPool3d的逆上采样:通道192→64,空间维度放大2倍 nn.ConvTranspose3d(192, 64, kernel_size=(1,3,3), stride=(1,2,2), padding=(0,1,1), output_padding=(0,0,0), bias=False), nn.BatchNorm3d(64), nn.ReLU(), # 对应SepConv3d的逆:通道64→64,尺寸不变 SepDeconv3d(64, 64, kernel_size=3, stride=1, padding=1), # 对应BasicConv3d的逆:通道64→64,尺寸不变 BasicDeconv3d(64, 64, kernel_size=1, stride=1), )
关键参数匹配原则
stride:必须等于对应编码器下采样层的步长,保证尺寸放大倍数与下采样倍数一致kernel_size&padding:参考原卷积/池化层参数,使反卷积输出尺寸满足公式:output_size = (input_size - 1)*stride - 2*padding + kernel_size- 通道数:编码器是
输入通道→输出通道,解码器需改为输出通道→输入通道
内容的提问来源于stack exchange,提问作者dtr43

