一、定义神经网络
BasicConv2d 继承自 nn.Module,这是 PyTorch 中所有神经网络模块的基类。__init__ 方法是构造函数,定义了卷积层的参数。in_planes 是输入通道数。out_planes 是输出通道数。kernel_size 是卷积核的尺寸。stride 是卷积的步幅,默认值为1。padding 是卷积的填充,默认值为0。dilation 是卷积核的扩张率,默认值为1。
接着我们定义了一个二维卷积层和归一化层。
之后使用forward方法模拟前向传播
二、CFM模块
self.relu 定义了一个ReLU激活函数,inplace=True 表示直接对输入数据进行修改,以节省内存。
self.upsample 定义了一个上采样层,用于将特征图的尺寸扩大一倍,使用双线性插值法。
self.conv_upsample1 至 self.conv_upsample5 和 self.conv_concat2 至 self.conv4 定义了一系列卷积层。这些卷积层使用 BasicConv2d 模块,包含卷积、批归一化和ReLU激活。
特征图 x1_1:
x1_1 = x1:保留输入特征图 x1。
特征图 x2_1:
x2_1 = self.conv_upsample1(self.upsample(x1)) * x2:
对 x1 进行上采样(放大一倍)。
经过卷积层 conv_upsample1。
与 x2 逐元素相乘。
特征图 x3_1:
x3_1 = self.conv_upsample2(self.upsample(self.upsample(x1))) * self.conv_upsample3(self.upsample(x2)) * x3:
对 x1 进行两次上采样(放大四倍)。
经过卷积层 conv_upsample2。
对 x2 进行上采样(放大一倍),然后经过卷积层 conv_upsample3。
与 x3 逐元素相乘。
特征图 x2_2:
x2_2 = torch.cat((x2_1, self.conv_upsample4(self.upsample(x1_1))), 1):
对 x1_1 进行上采样(放大一倍),然后经过卷积层 conv_upsample4。
将上述结果与 x2_1 在通道维度上拼接。
x2_2 = self.conv_concat2(x2_2):经过卷积层 conv_concat2。
特征图 x3_2:
x3_2 = torch.cat((x3_1, self.conv_upsample5(self.upsample(x2_2))), 1):
对 x2_2 进行上采样(放大一倍),然后经过卷积层 conv_upsample5。
将上述结果与 x3_1 在通道维度上拼接。
x3_2 = self.conv_concat3(x3_2):经过卷积层 conv_concat3。
最终输出 x1:
x1 = self.conv4(x3_2):经过卷积层 conv4,得到最终融合的特征图。
三、通道注意力机制:
self.avg_pool 定义了自适应平均池化层,将输入特征图的每个通道压缩为一个单值。
self.max_pool 定义了自适应最大池化层,同样将输入特征图的每个通道压缩为一个单值。
平均池化分支:
- self.avg_pool(x) 对输入特征图 x 进行自适应平均池化,将每个通道压缩为一个单值。
- self.fc1(self.avg_pool(x)) 通过 1x1 卷积层 fc1 减少通道数。
- self.relu1 对上一步的输出进行 ReLU 激活。
- self.fc2 通过 1x1 卷积层 fc2 恢复通道数。
- avg_out 存储了平均池化分支的输出。
最大池化分支:
- self.max_pool(x) 对输入特征图 x 进行自适应最大池化,将每个通道压缩为一个单值。
- self.fc1(self.max_pool(x)) 通过 1x1 卷积层 fc1 减少通道数。
- self.relu1 对上一步的输出进行 ReLU 激活。
- self.fc2 通过 1x1 卷积层 fc2 恢复通道数。
- max_out 存储了最大池化分支的输出。
特征融合:
out = avg_out + max_out 将平均池化分支和最大池化分支的输出相加,得到最终的特征图。
注意力权重:
return self.sigmoid(out) 对相加后的特征图进行 Sigmoid 激活,得到通道的注意力权重。