PyTorch实现的卷积自编码器输出图像出现网格纹应如何解决?
卷积自编码器输出网格伪影解决方案
你遇到的网格纹路是转置卷积(ConvTranspose2d)的典型问题,叫做棋盘伪影,本质是转置卷积的核大小无法被步长整除时,卷积核在输出特征图上的重叠区域不均匀,导致出现周期性的网格状高亮/暗纹,和激活函数关系不大,因此更换激活函数无法解决问题。
可参考以下方案解决:
- 替换转置卷积为「上采样+普通卷积」组合
这是行业内最通用的解决方法,可从根源上避免转置卷积固有的重叠问题。示例修改后的解码器代码如下:
class Model_CAE(nn.Module): def __init__(self): super(Model_CAE, self).__init__() self.act = nn.Hardtanh() # 上采样层可复用,也可以为每一层单独定义 self.upsample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=False) # ENCODER 保持原结构不变 self.e1 = nn.Conv2d(3, 16, kernel_size=5, stride=2, padding=0) self.e2 = nn.Conv2d(16, 32, kernel_size=2, stride=2, padding=2) self.e3 = nn.Conv2d(32, 64, kernel_size=2, stride=2, padding=0) # DECODER 修改为上采样+普通卷积 self.d1 = nn.Conv2d(64, 32, kernel_size=3, stride=1, padding=1) self.d2 = nn.Conv2d(32, 16, kernel_size=3, stride=1, padding=1) # 最后一层可调整padding/核大小保证输出尺寸和输入匹配 self.d3 = nn.Conv2d(16, 3, kernel_size=5, stride=1, padding=2) def forward(self, x): e1 = self.act(self.e1(x)) e2 = self.act(self.e2(e1)) e3 = self.act(self.e3(e2)) d1 = self.act(self.d1(self.upsample(e3))) d2 = self.act(self.d2(self.upsample(d1))) # 最后一层根据实际尺寸需要可以再加一次上采样,或调整前面层的上采样倍率 out = self.act(self.d3(self.upsample(d2))) return out def name(self): return "CAE"
你可以根据实际输入输出尺寸调整上采样的scale_factor和卷积的padding参数,保证输出尺寸和原图一致。
- 调整转置卷积参数(若保留
ConvTranspose2d)
将转置卷积的核大小设置为步长的整数倍,比如步长为2时核大小取4,同时调整padding参数保证尺寸对齐,避免不均匀重叠。 - 增加正则化损失项
在原有的MSE重建损失基础上,增加总变分损失(TV Loss)惩罚输出的高频噪声,也可以加入预训练网络的感知损失,引导模型输出更平滑自然的图像,抑制网格伪影。 - 优化权重初始化
如果保留转置卷积,可以用双线性插值的权重初始化转置卷积层,避免随机初始化的核加重重叠不均匀的问题。
内容的提问来源于stack exchange,提问作者Gold
相关产品推荐
相关产品推荐

