J4 - ResNet与DenseNet结合

部署运行你感兴趣的模型镜像


环境

  • 系统: Linux
  • 语言: Python3.8.10
  • 深度学习框架: Pytorch2.0.0+cu118
  • 显卡:GTX2080TI

模型设计

原始的DenseNet结构图如下:
DenseNet结构图
原始的ResNet结构图如下:
ResNet结构图
经过对比可以发现,ResNet的恒等块是经过了3个Conv层,而DenseNet只有两个,于是将DenseNet的结构修改为ResNet的风格,然后进行测试。

# BN ReLU Conv 顺序的残差块
class ResidualBlock(nn.Sequential):
    def __init__(self, kernel_size, input_size, hidden_size, drop_rate):
        super().__init__()
        
        self.add_module('norm1', nn.BatchNorm2d(input_size)),
        self.add_module('relu1', nn.ReLU(inplace=True)),
        self.add_module('conv1', nn.Conv2d(input_size, hidden_size, kernel_size=1, bias=False))
        
        self.add_module('norm2', nn.BatchNorm2d(hidden_size)),
        self.add_module('relu2', nn.ReLU(inplace=True)),
        self.add_module('conv2', nn.Conv2d(hidden_size, hidden_size, kernel_size=kernel_size, padding='same', bias=False))
        
        
        self.add_module('norm3', nn.BatchNorm2d(hidden_size)),
        self.add_module('relu3', nn.ReLU(inplace=True)),
        self.add_module('conv3', nn.Conv2d(hidden_size, input_size, kernel_size=1, bias=False))
        
        self.drop_rate = drop_rate
        
    def forward(self, x):
        features = super().forward(x)
        if self.drop_rate > 0:
            features = F.dropout(features, p = self.drop_rate, training=self.training)
        
        return torch.concat([x, features], 1)
class DenseBlock(nn.Sequential):
    def __init__(self, num_layers, input_size, drop_rate):
        super().__init__()
        for i in range(num_layers):
            layer = ResidualBlock(3, input_size, int(input_size / 4), drop_rate)
            input_size *= 2 # 每次都是上个的堆叠,每次都翻倍
            self.add_module('denselayer%d'%(i+1,), layer)
# 过渡层没有任务变化
class Transition(nn.Sequential):
    def __init__(self, input_size, output_size):
        super().__init__()
        self.add_module('norm', nn.BatchNorm2d(input_size))
        self.add_module('relu', nn.ReLU())
        self.add_module('conv', nn.Conv2d(input_size, output_size, kernel_size=1, stride=1, bias=False))
        self.add_module('pool', nn.AvgPool2d(2, stride=2))
# 构建自定义的DenseNet
class DenseNet(nn.Module):
	# 模型的规模小一点,方便测试
    def __init__(self, growth_rate=32, block_config=(2,4,3, 2), 
                 init_size=64, bn_size=4, compression_rate=0.5, drop_rate=0, num_classes=1000):
        super().__init__()
        
        self.features = nn.Sequential(OrderedDict([
            ("conv0", nn.Conv2d(3, init_size, kernel_size=7, stride=2, padding=3, bias=False)),
            ('norm0', nn.BatchNorm2d(init_size)),
            ('relu0', nn.ReLU()),
            ('pool0', nn.MaxPool2d(3, stride=2, padding=1))
        ]))
        
        num_features = init_size
        for i, num_layers in enumerate(block_config):
            block = DenseBlock(num_layers, num_features, drop_rate)
            self.features.add_module('denseblock%d' % (i + 1), block)
            num_features = num_features*(2**num_layers)
            if i != len(block_config) - 1:
                transition = Transition(num_features, int(num_features*compression_rate))
                self.features.add_module('transition%d' % (i + 1), transition)
                num_features = int(num_features * compression_rate)
                
        self.features.add_module('norm5', nn.BatchNorm2d(num_features))
        self.features.add_module('relu5', nn.ReLU())
        
        self.classifier = nn.Linear(num_features, num_classes)
        
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.bias, 0)
                nn.init.constant_(m.weight, 1)
            elif isinstance(m, nn.Linear):
                nn.init.constant_(m.bias, 0)
                
    def forward(self, x):
        features = self.features(x)
        out = F.avg_pool2d(features, 7, stride=1).view(features.size(0), -1)
        out = self.classifier(out)
        return out

打印一下模型的结构

DenseNet(
  (features): Sequential(
    (conv0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (norm0): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu0): ReLU()
    (pool0): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
    (denseblock1): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(64, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(16, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(32, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition1): Transition(
      (norm): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock2): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(32, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer3): ResidualBlock(
        (norm1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer4): ResidualBlock(
        (norm1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition2): Transition(
      (norm): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(2048, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock3): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer3): ResidualBlock(
        (norm1): BatchNorm2d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(4096, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(1024, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (transition3): Transition(
      (norm): BatchNorm2d(8192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU()
      (conv): Conv2d(8192, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
    )
    (denseblock4): DenseBlock(
      (denselayer1): ResidualBlock(
        (norm1): BatchNorm2d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(4096, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(1024, 1024, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(1024, 4096, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
      (denselayer2): ResidualBlock(
        (norm1): BatchNorm2d(8192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU(inplace=True)
        (conv1): Conv2d(8192, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (norm2): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU(inplace=True)
        (conv2): Conv2d(2048, 2048, kernel_size=(3, 3), stride=(1, 1), padding=same, bias=False)
        (norm3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu3): ReLU(inplace=True)
        (conv3): Conv2d(2048, 8192, kernel_size=(1, 1), stride=(1, 1), bias=False)
      )
    )
    (norm5): BatchNorm2d(16384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu5): ReLU()
  )
  (classifier): Linear(in_features=16384, out_features=2, bias=True)
)
# 使用torchinfo打印
summary(model, input_size=(32, 3, 224, 224))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
DenseNet                                 [32, 2]                   --
├─Sequential: 1-1                        [32, 16384, 7, 7]         --
│    └─Conv2d: 2-1                       [32, 64, 112, 112]        9,408
│    └─BatchNorm2d: 2-2                  [32, 64, 112, 112]        128
│    └─ReLU: 2-3                         [32, 64, 112, 112]        --
│    └─MaxPool2d: 2-4                    [32, 64, 56, 56]          --
│    └─DenseBlock: 2-5                   [32, 256, 56, 56]         --
│    │    └─ResidualBlock: 3-1           [32, 128, 56, 56]         4,544
│    │    └─ResidualBlock: 3-2           [32, 256, 56, 56]         17,792
│    └─Transition: 2-6                   [32, 128, 28, 28]         --
│    │    └─BatchNorm2d: 3-3             [32, 256, 56, 56]         512
│    │    └─ReLU: 3-4                    [32, 256, 56, 56]         --
│    │    └─Conv2d: 3-5                  [32, 128, 56, 56]         32,768
│    │    └─AvgPool2d: 3-6               [32, 128, 28, 28]         --
│    └─DenseBlock: 2-7                   [32, 2048, 28, 28]        --
│    │    └─ResidualBlock: 3-7           [32, 256, 28, 28]         17,792
│    │    └─ResidualBlock: 3-8           [32, 512, 28, 28]         70,400
│    │    └─ResidualBlock: 3-9           [32, 1024, 28, 28]        280,064
│    │    └─ResidualBlock: 3-10          [32, 2048, 28, 28]        1,117,184
│    └─Transition: 2-8                   [32, 1024, 14, 14]        --
│    │    └─BatchNorm2d: 3-11            [32, 2048, 28, 28]        4,096
│    │    └─ReLU: 3-12                   [32, 2048, 28, 28]        --
│    │    └─Conv2d: 3-13                 [32, 1024, 28, 28]        2,097,152
│    │    └─AvgPool2d: 3-14              [32, 1024, 14, 14]        --
│    └─DenseBlock: 2-9                   [32, 8192, 14, 14]        --
│    │    └─ResidualBlock: 3-15          [32, 2048, 14, 14]        1,117,184
│    │    └─ResidualBlock: 3-16          [32, 4096, 14, 14]        4,462,592
│    │    └─ResidualBlock: 3-17          [32, 8192, 14, 14]        17,838,080
│    └─Transition: 2-10                  [32, 4096, 7, 7]          --
│    │    └─BatchNorm2d: 3-18            [32, 8192, 14, 14]        16,384
│    │    └─ReLU: 3-19                   [32, 8192, 14, 14]        --
│    │    └─Conv2d: 3-20                 [32, 4096, 14, 14]        33,554,432
│    │    └─AvgPool2d: 3-21              [32, 4096, 7, 7]          --
│    └─DenseBlock: 2-11                  [32, 16384, 7, 7]         --
│    │    └─ResidualBlock: 3-22          [32, 8192, 7, 7]          17,838,080
│    │    └─ResidualBlock: 3-23          [32, 16384, 7, 7]         71,327,744
│    └─BatchNorm2d: 2-12                 [32, 16384, 7, 7]         32,768
│    └─ReLU: 2-13                        [32, 16384, 7, 7]         --
├─Linear: 1-2                            [32, 2]                   32,770
==========================================================================================
Total params: 149,871,874
Trainable params: 149,871,874
Non-trainable params: 0
Total mult-adds (G): 595.94
==========================================================================================
Input size (MB): 19.27
Forward/backward pass size (MB): 5317.85
Params size (MB): 599.49
Estimated Total Size (MB): 5936.61
==========================================================================================

模型效果展示

Epoch: 1, Train_acc:83.8, Train_loss: 0.392, Test_acc: 86.8, Test_loss: 0.324, Lr: 1.00E-04
Epoch: 2, Train_acc:86.8, Train_loss: 0.327, Test_acc: 88.5, Test_loss: 0.291, Lr: 1.00E-04
Epoch: 3, Train_acc:88.1, Train_loss: 0.290, Test_acc: 87.7, Test_loss: 0.415, Lr: 1.00E-04
Epoch: 4, Train_acc:88.1, Train_loss: 0.287, Test_acc: 89.8, Test_loss: 0.249, Lr: 1.00E-04
Epoch: 5, Train_acc:89.7, Train_loss: 0.251, Test_acc: 90.5, Test_loss: 0.235, Lr: 1.00E-04
Epoch: 6, Train_acc:90.2, Train_loss: 0.241, Test_acc: 90.7, Test_loss: 0.253, Lr: 1.00E-04
Epoch: 7, Train_acc:90.6, Train_loss: 0.227, Test_acc: 90.5, Test_loss: 0.236, Lr: 1.00E-04
Epoch: 8, Train_acc:91.5, Train_loss: 0.212, Test_acc: 90.5, Test_loss: 0.228, Lr: 1.00E-04
Epoch: 9, Train_acc:91.7, Train_loss: 0.207, Test_acc: 91.0, Test_loss: 0.247, Lr: 1.00E-04
Epoch:10, Train_acc:92.0, Train_loss: 0.206, Test_acc: 91.2, Test_loss: 0.290, Lr: 1.00E-04
Epoch:11, Train_acc:92.0, Train_loss: 0.203, Test_acc: 88.2, Test_loss: 0.283, Lr: 1.00E-04
Epoch:12, Train_acc:92.5, Train_loss: 0.185, Test_acc: 91.3, Test_loss: 0.232, Lr: 1.00E-04
Epoch:13, Train_acc:93.2, Train_loss: 0.172, Test_acc: 90.7, Test_loss: 0.247, Lr: 1.00E-04
Epoch:14, Train_acc:93.3, Train_loss: 0.177, Test_acc: 90.2, Test_loss: 0.238, Lr: 1.00E-04
Epoch:15, Train_acc:93.8, Train_loss: 0.166, Test_acc: 90.1, Test_loss: 0.357, Lr: 1.00E-04
Epoch:16, Train_acc:94.6, Train_loss: 0.146, Test_acc: 91.2, Test_loss: 0.255, Lr: 1.00E-04
Epoch:17, Train_acc:95.4, Train_loss: 0.119, Test_acc: 90.2, Test_loss: 0.270, Lr: 1.00E-04
Epoch:18, Train_acc:95.5, Train_loss: 0.116, Test_acc: 81.7, Test_loss: 0.752, Lr: 1.00E-04
Epoch:19, Train_acc:95.6, Train_loss: 0.117, Test_acc: 89.3, Test_loss: 0.339, Lr: 1.00E-04
Epoch:20, Train_acc:95.5, Train_loss: 0.120, Test_acc: 91.0, Test_loss: 0.285, Lr: 1.00E-04
Done

训练结果

打印评估结果

总结与心得体会

虽然大幅度的降低了模型的规模,实际的总参数还是数倍于DenseNet121。然而,模型似乎比DenseNet121的泛化性能好不少,训练和验证的Gap比DenseNet121小很多,甚至有的时候验证集上的表现比训练集还好。直接使用ResNet的ResidualBlock实现DenseNet会让参数量迅速的膨胀。接下来再改进,应该从如何压缩DenseNet的参数量的角度来考虑。

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>首先,用户的问题是:“我想了解SE - ResNet相关信息 请问SE - ResNet介绍、原理、应用等相关信息”。这要求我提供关于SE-ResNet的介绍、基本原理应用领域。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户引用了几个站内引用,我需要参考这些引用: - 引用[1]: 谈论3D-SE-ResNet在遥感领域的应用,包括地物分类、植被监测等。还提到了未来研究方向如模型优化、多模态数据融合、实时应用。[^1] - 引用[2]: 描述SE-Net模嵌入传统CNN架构中,通过通道级注意力机制增强性能。涉及全局信息池化权重调整。[^2] - 引用[3]: 展示SE模嵌入到InceptionResNet中,包括维度信息SE模型效果对比。[^3] - 引用[4]: 解释SE-ResNet module,包括Reweight操作,特征重标定。[^4] - 引用[5]: 讨论SE-NET应用于ResNet,引入SE增强通道相互关系。[^5] 用户的问题焦点是SE-ResNet的介绍、原理、应用。所以,我应该基于这些引用自己的知识构建回答。 关键点: - **SE-ResNet介绍**: SE-ResNetResNet架构的变体,引入了Squeeze-and-Excitation (SE) 模ResNet是深度残差网络,用于图像识别等任务。 - **原理**: SE模的核心是通道注意力机制。它通过Squeeze步骤(如全局平均池化)压缩特征图到通道级别的描述符,然后Excitation步骤(通常是全连接层)学习每个通道的重要性权重,最后Reweighting步骤将权重应用到原始特征图上。这允许网络自适应地强调重要特征。 - 数学上:给定输入特征图$X$,形状为$H \times W \times C$。 - Squeeze: 计算每个通道的平均值,得到$1 \times 1 \times C$的向量。 - Excitation: 通过网络(如两个FC层)输出通道权重向量$S$。 - Reweight: 将$S$乘以原始特征图$X$,得到输出。 - 公式:$$S = \sigma(W_2 \delta(W_1 z))$$ 其中$z$是全局平均池化结果,$\delta$是ReLU,$\sigma$是sigmoid。 - **应用**: 如引用中提到的,广泛应用于图像分类、目标检测、语义分割、遥感图像处理等。具体到引用[1],在地物分类、植被监测、变化检测中有效。 回答结构: 1. **介绍SE-ResNet**:定义它,基于ResNetSE模结合。 2. **详细解释原理**:分步骤描述SE模的工作机制,使用数学表达式。 3. **应用领域**:列出常见应用,参考引用如遥感领域的应用。 4. **生成相关问题**:在末尾添加相关问题部分。 确保使用中文回答。引用时自然地添加引用标识,例如在相关段落末尾添加[^1]等。 生成相关问题: - 基于用户问题引用,例如: 1. SE模如何集成到ResNet架构中? 2. SE-ResNet在遥感图像处理中的具体优势是什么? 3. 如何优化SE-ResNet以提高性能? 4. SE-ResNet其他注意力机制的比较? 5. SE-ResNet的实际部署挑战? 最后,回答要清晰、结构良好。 </think>### SE-ResNet介绍、原理应用 SE-ResNet(Squeeze-and-Excitation ResNet)是一种基于经典ResNet(残差网络)架构的改进模型,它引入了SE模(Squeeze-and-Excitation Block)以增强网络的通道注意力机制。这种设计源于Hu等人在2017年提出的SE-Net,通过自适应地重新校准特征图的通道权重,使网络能够更有效地捕捉重要信息,并抑制无关特征[^2][^4]。SE-ResNet广泛应用于图像分类、目标检测遥感分析等任务,显著提升了模型性能泛化能力。 #### 1. SE-ResNet介绍 SE-ResNet的核心创新是将SE模嵌入到ResNet的残差中。ResNet本身通过残差连接解决了深层网络训练中的梯度消失问题,而SE模则添加了通道级别的注意力机制。这使得模型能动态调整每个通道的特征权重,从而放大有用特征并抑制噪声[^4][^5]。例如,在ResNet架构中,SE模通常插入在残差的卷积层之后,形成SE-ResNet(如下图所示结构)。 ```plaintext 输入特征图 → 卷积层 → SE模 → 残差连接 → 输出特征图 ``` 这种集成方式保持了ResNet的深度优势,同时引入了轻量级的注意力计算,增加了模型对不同场景的适应能力[^3][^5]。相较于原始ResNet,SE-ResNet在ImageNet等基准数据集上取得了更高的准确率,且计算开销相对较小[^3]。 #### 2. SE-ResNet原理 SE模的原理基于“Squeeze(压缩)”、“Excitation(激励)”“Reweight(重加权)”三个步骤,实现了通道注意力机制。下面详细解释其数学过程(使用独立公式格式): 给定输入特征图$X \in \mathbb{R}^{H \times W \times C}$,其中$H$是高度,$W$是宽度,$C$是通道数。 - **Squeeze操作**:通过全局平均池化(Global Average Pooling)压缩空间维度,生成通道级别的统计量$z \in \mathbb{R}^{1 \times 1 \times C}$。这一步捕捉全局上下文信息: $$ z_c = \frac{1}{H \times W} \sum_{i=1}^{H} \sum_{j=1}^{W} X_c(i,j) $$ 其中$z_c$表示第$c$个通道的全局平均值。 - **Excitation操作**:使用全连接层非线性激活函数学习每个通道的权重$s \in \mathbb{R}^{1 \times 1 \times C}$。这里引入了一个瓶颈结构(例如两个FC层)来建模通道间的依赖关系: $$ s = \sigma(W_2 \delta(W_1 z)) $$ 其中$W_1$$W_2$是全连接层的权重矩阵,$\delta$是ReLU激活函数,$\sigma$是sigmoid函数,确保输出权重在$[0,1]$范围内。这步动态调整通道重要性,例如在高光谱遥感图像中,强调植被相关通道[^2][^4]。 - **Reweight操作**:将学到的权重$s$应用到原始特征图上,通过逐通道乘法实现特征重标定: $$ \tilde{X}_c = s_c \cdot X_c $$ 其中$\tilde{X}$是输出特征图,它增强了有用特征并减弱了噪声通道。 在SE-ResNet中,SE模被嵌入到每个残差的末端(如图示示例),形成端到端的训练流程[^3][^4]。整体上,SE模通过$ \text{Squeeze} \to \text{Excitation} \to \text{Reweight} $序列,提升了模型的特征选择能力,参数增加少(仅占ResNet的~1%),计算效率高[^5]。 #### 3. SE-ResNet应用 SE-ResNet凭借其通道注意力优势,已广泛应用于多个领域: - **图像分类目标检测**:在ImageNet、COCO等数据集上,SE-ResNet显著提高了分类精度检测鲁棒性。例如,SE模能使ResNet更好地区分细微特征,如动物纹理或物体边缘[^4][^5]。 - **遥感图像处理**:如参考文献所述,3D-SE-ResNet(SE-ResNet的3D扩展)在地物分类、植被监测土地利用变化检测中表现突出。高光谱遥感图像提供丰富的光谱信息,SE模能高效利用这些数据,提升分类准确率[^1]。例如,在植被监测任务中,SE机制自动增强叶绿素相关的通道,减少云层干扰。 - **其他领域**:包括语义分割(结合UNet或DenseNet)、医疗影像分析(如肿瘤检测)实时系统(无人机导航)。未来研究方向包括模型优化(如改进SE结构)、多模态数据融合(结合RGB或LiDAR数据)实时应用(优化计算延迟)[^1][^5]。 SE-ResNet的优点包括:轻量级注意力机制、易于集成到现有架构、提升泛化能力;缺点是训练时需额外参数调整,实时应用中可能需优化延迟[^1][^3]。整体上,它代表了注意力机制在CNN中的关键进展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值