【语义分割|代码解析2】空洞卷积!DSNet-2: A Novel Way to Use Atrous Convolutions in Semantic Segmentation
【语义分割|代码解析】空洞卷积!DSNet-2: A Novel Way to Use Atrous Convolutions in Semantic Segmentation
文章目录
欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz
论文地址:https://arxiv.org/pdf/2406.03702v1
前言
DSNet模型是一种基于膨胀卷积(Atrous Convolution)的语义分割网络,应用在遥感图像分析中能够提高对复杂场景的细节捕捉能力。DSNet模型的整体结构包括多尺度特征提取、特征融合以及分割头输出,以下是对代码的逐层解析,帮助理解每一个模块的功能和设计思想。
1. 代码全局设置
BatchNorm2d = nn.BatchNorm2d
bn_mom = 0.1
algc = True
BatchNorm2d
:批量归一化操作,用于在训练时保持网络的稳定性。bn_mom = 0.1
:批量归一化的动量参数。algc
:通常用于控制算法设置,具体在代码中未直接应用。
2. DUC
(Dense Upsampling Convolution) 模块
class DUC(nn.Module):
def __init__(self, inplanes, planes, upscale_factor=2):
super(DUC, self).__init__()
self.relu = nn.ReLU() # 激活函数
self.conv = nn.Conv2d(inplanes, planes * upscale_factor ** 2, kernel_size=3, padding=1) # 卷积层
self.bn = nn.BatchNorm2d(planes * upscale_factor ** 2) # 批量归一化
self.pixel_shuffle = nn.PixelShuffle(upscale_factor) # 像素洗牌操作用于上采样
self.conv2 = nn.Conv2d(planes, planes, kernel_size=1, padding=0, bias=False)
self.relu
:使用 ReLU 作为激活函数,增强非线性能力。self.conv
:卷积层,将输入通道数扩展为planes * upscale_factor ** 2
,以便在PixelShuffle
后恢复目标分辨率。self.bn
:批量归一化层,应用于卷积输出,帮助加快收敛。self.pixel_shuffle
:通过PixelShuffle
将通道信息转换为更高的分辨率,实现上采样。self.conv2
:1x1
卷积层,用于进一步压缩通道数量。
forward
函数
def forward(self, x):
x = self.relu(x)
x = self.conv(x)
x = self.bn(x)
x = self.relu(x)
x = self.pixel_shuffle(x) # 通过PixelShuffle进行上采样
x = self.conv2(x)
return x
x = self.conv(x)
:卷积操作扩展特征通道。x = self.bn(x)
:对卷积后的特征图进行批量归一化。x = self.pixel_shuffle(x)
:进行上采样操作。x = self.conv2(x)
:使用1x1
卷积将输出通道进一步缩减。
3. ConvX
模块
class ConvX(nn.Module):
def __init__(self, in_planes, out_planes, kernel=3, stride=1, dilation=1):
super(ConvX, self).__init__()
if dilation==1:
self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel, stride=stride, bias=False)
else:
self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel, stride=stride, dilation=dilation, padding=dilation, bias=False)
self.bn = BatchNorm2d(out_planes, momentum=bn_mom)
self.relu = nn.ReLU(inplace=True)
- 根据
dilation
值,决定是否使用膨胀卷积 (dilation > 1
)。 self.bn
:批量归一化层,帮助稳定训练。self.relu
:使用ReLU
激活。
forward
函数
def forward(self, x):
out = self.relu(self.bn(self.conv(x)))
return out
- 逐步进行卷积、批量归一化、激活操作。
4. Conv1X1
模块
class Conv1X1(nn.Module):
def __init__(self, in_planes, out_planes, kernel=1, stride=1, dilation=1):
super(Conv1X1, self).__init__()
self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel, stride=stride, bias=False)
self.bn = BatchNorm2d(out_planes, momentum=bn_mom)
self.relu = nn.ReLU(inplace=True)
Conv1X1
是1x1
卷积,用于调整通道数。self.bn
和self.relu
:批量归一化和激活函数,与ConvX
相同。
5. MFACB
模块
MFACB
使用多种膨胀卷积快速聚拢感受野。
class MFACB(nn.Module):
def __init__(self, in_planes, inter_planes, out_planes, block_num=3, stride=1, dilation=[2,2,2]):
super(MFACB, self).__init__()
self.conv_list = nn.ModuleList()
self.conv_list.append(ConvX(in_planes, inter_planes, stride=stride, dilation=dilation[0]))
self.conv_list.append(ConvX(inter_planes, inter_planes, stride=stride, dilation=dilation[1]))
self.conv_list.append(ConvX(inter_planes, inter_planes, stride=stride, dilation=dilation[2]))
self.conv_list
:一个包含多层膨胀卷积的ModuleList
。- 每层
ConvX
使用不同的膨胀率 (dilation
),实现多尺度特征提取。
forward
函数
def forward(self, x):
out_list = []
out = x
out1 = self.process1(x)
for idx in range(3):
out = self.conv_list[idx](out)
out_list.append(out)
out = torch.cat(out_list, dim=1)
return self.process2(out) + out1
for idx in range(3)
:通过不同膨胀率的卷积层逐步提取多尺度特征。torch.cat(out_list, dim=1)
:将所有特征拼接。self.process2(out) + out1
:经过process2
进一步处理并加上out1
路径的特征,实现特征聚合。
6. SPASPP
模块
SPASPP
实现了具有空间池化的ASPP,用于捕获不同尺度的特征。
class SPASPP(nn.Module):
def __init__(self, in_planes, inter_planes, out_planes, block_num=3, stride=1, dilation=[6,12,18,24]):
super(SPASPP, self).__init__()
self.conv_list = nn.ModuleList()
self.conv_list.append(ConvX(in_planes, inter_planes, stride=stride, dilation=dilation[0]))
self.conv_list.append(ConvX(inter_planes, inter_planes, stride=stride, dilation=dilation[1]))
self.conv_list.append(ConvX(inter_planes, inter_planes, stride=stride, dilation=dilation[2]))
self.conv_list.append(ConvX(inter_planes, inter_planes, stride=stride, dilation=dilation[3]))
self.pooling = ASPPPooling(in_planes, inter_planes)
self.conv_list
:包含四个不同膨胀率的卷积层。self.pooling
:空间池化层,用于进一步丰富特征的上下文信息。
forward
函数
def forward(self, x):
out_list = []
out = x
out1 = self.process1(x)
out2 = self.pooling(x)
for idx in range(4):
out = self.conv_list[idx](out)
out_list.append(out)
out = torch.cat(out_list, dim=1)
out = torch.cat((out, out2), dim=1)
return self.process3(self.process2(out) + out1)
out2 = self.pooling(x)
:使用空间池化进一步补充上下文信息。out = torch.cat((out, out2), dim=1)
:将不同膨胀率卷积特征与池化特征拼接。- 最后通过
process2
和process3
完成融合,输出最终结果。
欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz