简介:
由ConvNets学习的表示已被证明对局部纹理有强烈的偏差,从而严重损害全局信息,急需改进。因此,已经做出努力来升级宏观层次的架构和上下文聚合模块。大多数现代深度神经网络倾向于编码极低或高复杂度的博弈理论相互作用,而不是最具鉴别性的中间交互作用,这限制了它们对复杂样本的表示能力和鲁棒性。与之前的尝试不同,MogaNet通过多阶博弈论交互的视角研究了现代卷积网络的表示能力,为解释基于博弈论的深度架构中编码的特征交互行为和效果提供了一个新的视角。
MogaNet:
图1为MogaNet宏观架构图,分为四个阶段。对于阶段i,输入的图像或特征首先被输入到嵌入stem中以调节特征分辨率并嵌入到Ci维度。假设输 入图像的分辨率为H×W,则四个阶段的特征分别为H/4×W/4 ,H/8×W/8 ,H/16×W/16和H/32×W/32的分辨率。然后,嵌入的特征流到NiMoga块中,由空间和通道聚合块组成,用于进一步的上下文提取和聚合。在最终输出后,添加GAP和线性层用于分类任务。
多阶门控聚合:
MogaNet提出一种空间聚合块SMixer(·),用于在统一设计中聚合多阶上下文,如下图所示,由两个级联组件组成。
其中,Moga(·)是一个多阶门控聚合模块,包括门控Fϕ(·)和上下文分支Gψ(·)。 具体细节:
class MogaBlock(nn.Module):
def __init__(self,
embed_dims,
ffn_ratio=4.,
drop_rate=0.,
drop_path_rate=0.,
act_type='GELU',
norm_type='BN',
init_value=1e-5,
attn_dw_dilation=[1, 2, 3],
attn_channel_split=[1, 3, 4],
attn_act_type='SiLU',
attn_force_fp32=False,
):
super(MogaBlock, self).__init__()
self.out_channels = embed_dims
self.norm1 = build_norm_layer(norm_type, embed_dims)
# spatial attention
self.attn = MultiOrderGatedAggregation(
embed_dims,
attn_dw_dilation=attn_dw_dilation,
attn_channel_split=attn_channel_split,
attn_act_type=attn_act_type,
attn_force_fp32=attn_force_fp32,
)
self.drop_path = DropPath(
drop_path_rate) if drop_path_rate > 0. else nn.Identity()
self.norm2 = build_norm_layer(norm_type, embed_dims)
# channel MLP
mlp_hidden_dim = int(embed_dims * ffn_ratio)
self.mlp = ChannelAggregationFFN( # DWConv + Channel Aggregation FFN
embed_dims=embed_dims,
feedforward_channels=mlp_hidden_dim,
act_type=act_type,
ffn_drop=drop_rate,
)
# init layer scale
self.layer_scale_1 = nn.Parameter(
init_value * torch.ones((1, embed_dims, 1, 1)), requires_grad=True)
self.layer_scale_2 = nn.Parameter(
init_value * torch.ones((1, embed_dims, 1, 1)), requires_grad=True)
def forward(self, x):
# spatial
identity = x
x = self.layer_scale_1 * self.attn(self.norm1(x))
x = identity + self.drop_path(x)
# channel
identity = x
x = self.layer_scale_2 * self.mlp(self.norm2(x))
x = identity + self.drop_path(x)
return x
通道聚合块:是一个通道聚合的前馈神经网络,用于特征提取和降维。
class ChannelAggregationFFN(nn.Module):
def __init__(self,
embed_dims,
feedforward_channels,
kernel_size=3,
act_type='GELU',
ffn_drop=0.):
super(ChannelAggregationFFN, self).__init__()
self.embed_dims = embed_dims
self.feedforward_channels = feedforward_channels
self.fc1 = nn.Conv2d(
in_channels=embed_dims,
out_channels=self.feedforward_channels,
kernel_size=1)
self.dwconv = nn.Conv2d(
in_channels=self.feedforward_channels,
out_channels=self.feedforward_channels,
kernel_size=kernel_size,
stride=1,
padding=kernel_size // 2,
bias=True,
groups=self.feedforward_channels)
self.act = build_act_layer(act_type)
self.fc2 = nn.Conv2d(
in_channels=feedforward_channels,
out_channels=embed_dims,
kernel_size=1)
self.drop = nn.Dropout(ffn_drop)
self.decompose = nn.Conv2d(
in_channels=self.feed