027、注意力机制的革命RCAN残差通道注意力网络的原理与超分实战去年有个项目让我印象特别深——客户要求把监控视频中的人脸从64×64放大到512×512还要保留足够的细节用于身份识别。我一开始用SRResNet跑结果出来的脸跟打了马赛克似的眼睛糊成一团。后来换成EDSR效果好了点但高频纹理还是出不来。直到我翻到RCAN那篇论文才意识到问题出在哪我们一直在空间维度上做文章却忽略了通道维度上信息的重要性。为什么RCAN能吊打之前的网络先说说RCAN的核心思想。传统的超分网络比如SRResNet、EDSR它们用的残差块都是“平等对待”每个通道的。但实际上一张图像的不同通道携带的信息量完全不同——有的通道包含丰富的边缘纹理有的通道可能全是噪声。RCAN的聪明之处在于它让网络学会“关注”那些重要的通道抑制不重要的通道。这个机制叫通道注意力Channel Attention。简单来说就是给每个通道学一个权重重要的通道权重高不重要的权重低。但RCAN不是简单加个SE模块就完事了它做了两件更狠的事一是把通道注意力和残差结构深度耦合形成了残差通道注意力块RCAB二是用残差中的残差RIR结构让网络能堆到400多层还不退化。残差通道注意力块RCAB的实现细节RCAB的结构其实不复杂但有几个坑必须说清楚。先看核心代码classRCAB(nn.Module):def__init__(self,n_feats,reduction16):super(RCAB,self).__init__()# 这里reduction16是经验值别乱改后面会解释self.bodynn.Sequential(nn.Conv2d(n_feats,n_feats,3,padding1),nn.ReLU(True),nn.Conv2d(n_feats,n_feats,3,padding1))# 通道注意力部分self.cann.Sequential(nn.AdaptiveAvgPool2d(1),# 全局平均池化把空间维度压缩到1x1nn.Conv2d(n_feats,n_feats//reduction,1),# 降维这里踩过坑reduction不能太小nn.ReLU(True),nn.Conv2d(n_feats//reduction,n_feats,1),# 升维回原通道数nn.Sigmoid()# 输出0-1之间的权重)defforward(self,x):residualx outself.body(x)# 通道注意力权重weightself.ca(out)# 别这样写out out * weight.expand_as(out)# 直接用广播机制PyTorch会自动处理维度outout*weightreturnoutresidual# 残差连接这里有个细节很多人会忽略全局平均池化之后特征图的尺寸变成了1×1这时候用1×1卷积做通道间的信息交互。reduction16的意思是先把通道数压缩到原来的1/16再升回来。为什么是16论文里做过消融实验8、16、32都试过16效果最好。我试过reduction8参数量上去了但效果没提升反而容易过拟合。残差中的残差RIR结构RCAN能堆到400多层靠的就是RIR结构。它把多个RCAB组成一个残差组RG然后再把多个RG串起来外面再套一层长残差连接。classRCAGroup(nn.Module):def__init__(self,n_feats,n_rcab,reduction):super(RCAGroup,self).__init__()# n_rcab表示这个组里有多少个RCAB块body[]for_inrange(n_rcab):body.append(RCAB(n_feats,reduction))self.bodynn.Sequential(*body)# 组内残差连接这里用1x1卷积做通道对齐self.convnn.Conv2d(n_feats,n_feats,1)defforward(self,x):residualx outself.body(x)outself.conv(out)returnoutresidual注意看每个RG内部有一个短残差多个RG之间还有长残差。这种设计让梯度可以沿着多条路径回传解决了深层网络的梯度消失问题。我试过不加长残差20个RG就开始不收敛了。训练RCAN的那些坑第一个坑是学习率。RCAN的参数量比EDSR大不少我用Adam优化器初始学习率设1e-4结果loss震荡得厉害。后来改成1e-4跑50个epoch然后每50个epoch衰减0.5才稳定下来。第二个坑是batch size。RCAN的显存消耗很大我的RTX 3090只能跑batch size16输入patch size48×48。如果显存不够可以试试梯度累积但注意BN层的统计量会受影响。第三个坑是数据增强。我一开始只做了随机翻转和旋转效果一般。后来加了随机裁剪和颜色抖动PSNR提升了0.3dB左右。但注意不要用太强的颜色抖动超分任务对颜色一致性要求很高。实战用RCAN做4倍超分完整的训练代码我就不贴了说几个关键点。数据预处理用DIV2K数据集把HR图像切成96×96的patchLR图像用bicubic下采样到24×24。注意下采样要用PIL的Image.BICUBIC别用OpenCV的INTER_CUBIC两者结果有差异。损失函数我用L1损失比L2损失收敛更快而且PSNR更高。别问我为什么实验就是这么说的。评估指标PSNR和SSIM都要看。PSNR反映像素级误差SSIM反映结构相似性。有时候PSNR高但SSIM低说明图像虽然像素误差小但纹理细节丢失了。个人经验性建议别盲目追求层数。RCAN原论文用了400层但实际应用中200层就够了。层数越多训练越慢而且边际效益递减。我试过800层PSNR只提升了0.05dB但训练时间翻了一倍。通道注意力不是万能的。对于纹理丰富的图像比如建筑、自然风景RCAN效果很好。但对于人脸、文字这类结构化的图像空间注意力可能更有效。我现在的做法是把通道注意力和空间注意力结合起来效果更好。注意reduction参数。这个参数控制通道注意力的压缩比直接影响模型容量。对于小数据集比如Set5、Set14reduction16就够了。对于大数据集比如DIV2K、Flickr2K可以试试reduction8。训练时监控每个RCAB的权重分布。如果大部分权重都集中在0.5附近说明通道注意力没学到东西可能是网络太浅或者数据量不够。最后说个玄学RCAN对输入图像的噪声很敏感。如果LR图像有噪声先做去噪再超分效果比端到端训练好。我试过在RCAN前面加个DnCNNPSNR提升了0.8dB。RCAN的出现确实推动了超分领域的发展但它不是终点。现在大家都在做Transformer和注意力机制的融合比如SwinIR、HAT等。但RCAN的思想——用通道注意力让网络学会关注重要信息——这个思路永远不会过时。