SENet论文理解与代码复现(pytorch)

SENet-pytorch代码链接

Jnmz/SENet-pytorch: Implementing SENet using the pytorch framework,You can use tensorboard to view the log and resume training at checkpoints (github.com)

Attention机制

模仿人类视觉机制,只关注部分区域,忽略无关区域。

在神经网络中加入注意力机制有很多方法,可以在空间维度引入注意力机制(eg inception结构,让并联的卷积层分配不同的权重),也可以在通道维度引入attention机制

通过自动学习的方式(用另外一个神经网络实现)获取到每个特征通道的重要程度,然后用这个重要程度去给每一个特征通道赋予权重值,从而让神经网络重点关注某些特征通道。实现在通道维度上引入attention机制。

Global pooling就是squeeze操作,FC+ReLU+FC+Sigmoid就是excitation操作

这里全连接层的参数根据loss一起不断迭代更新。最后通过sigmoid函数转化为一个0~1的归一化权重。

SENet的核心思想在于通过全连接网络根据loss去自动学习特征权重(并不是直接根据特征通道的数值分布来判断),使得有效的特征通道权重大。

而excitation操作中用两个全连接层的好处在于:具有更多非线性,可以更好的拟合通道间的复杂性。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 示例代码:import torch import torch.nn as nn class SENet(nn.Module): def __init__(self, in_channels, out_channels): super(SENet, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, 3, padding=1) self.se_block = nn.Sequential( nn.Linear(out_channels, out_channels // 16), nn.ReLU(), nn.Linear(out_channels // 16, out_channels) ) self.relu = nn.ReLU() self.conv2 = nn.Conv2d(out_channels, out_channels, 3, padding=1) def forward(self, x): x = self.conv1(x) x = self.se_block(x) x = self.relu(x) x = self.conv2(x) return x ### 回答2: import torch import torch.nn as nn # 定义SENet模块中的Squeeze-and-Excitation块 class SEBlock(nn.Module): def __init__(self, in_channels, reduction_ratio): super(SEBlock, self).__init__() self.pool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Sequential( nn.Linear(in_channels, in_channels // reduction_ratio), nn.ReLU(inplace=True), nn.Linear(in_channels // reduction_ratio, in_channels), nn.Sigmoid() ) def forward(self, x): b, c, _, _ = x.size() inputs = x x = self.pool(x).view(b, c) x = self.fc(x).view(b, c, 1, 1) return inputs * x # 定义SENet网络模型 class SENet(nn.Module): def __init__(self, num_classes=1000, reduction_ratio=16): super(SENet, self).__init__() self.num_classes = num_classes self.reduction_ratio = reduction_ratio self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(64) self.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(64) self.pool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) self.layer1 = self._make_seresnet_layer(64, 64, 3) self.layer2 = self._make_seresnet_layer(64, 128, 4, stride=2) self.layer3 = self._make_seresnet_layer(128, 256, 6, stride=2) self.layer4 = self._make_seresnet_layer(256, 512, 3, stride=2) self.avgpool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Linear(512, num_classes) def _make_seresnet_layer(self, in_channels, out_channels, num_blocks, stride=1): layers = [] layers.append(SEBlock(in_channels, self.reduction_ratio)) for _ in range(1, num_blocks): layers.append(nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=stride, padding=1, bias=False)) layers.append(nn.BatchNorm2d(in_channels)) layers.append(nn.ReLU(inplace=True)) layers.append(SEBlock(in_channels, self.reduction_ratio)) layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)) layers.append(nn.BatchNorm2d(out_channels)) return nn.Sequential(*layers) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) x = self.conv2(x) x = self.bn2(x) x = self.relu(x) x = self.pool(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = x.view(x.size(0), -1) x = self.fc(x) return x # 创建SENet实例并使用 se_net = SENet(num_classes=10) inputs = torch.randn(1, 3, 224, 224) outputs = se_net(inputs) print(outputs.size()) # 打印输出的结果维度,例如torch.Size([1, 10])表示输出为1个样本,有10个类别输出 ### 回答3: import torch import torch.nn as nn class SEBlock(nn.Module): def __init__(self, inplanes, reduction_ratio=16): super(SEBlock, self).__init__() self.avgpool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Sequential( nn.Linear(inplanes, inplanes // reduction_ratio), nn.ReLU(inplace=True), nn.Linear(inplanes // reduction_ratio, inplanes), nn.Sigmoid() ) def forward(self, x): out = self.avgpool(x).squeeze(3).squeeze(2) out = self.fc(out).unsqueeze(2).unsqueeze(3) return x * out class SENet(nn.Module): def __init__(self, num_classes=1000): super(SENet, self).__init__() self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) self.bn1 = nn.BatchNorm2d(64) self.relu = nn.ReLU(inplace=True) self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) self.layer1 = self._make_layer(64, 64, 3) self.layer2 = self._make_layer(64, 128, 4, stride=2) self.layer3 = self._make_layer(128, 256, 6, stride=2) self.layer4 = self._make_layer(256, 512, 3, stride=2) self.avgpool = nn.AdaptiveAvgPool2d(1) self.fc = nn.Linear(512, num_classes) def _make_layer(self, inplanes, planes, blocks, stride=1): layers = [] layers.append(SEBlock(inplanes)) layers.append(nn.Sequential( nn.Conv2d(inplanes, planes, kernel_size=3, stride=stride, padding=1, bias=False), nn.BatchNorm2d(planes), nn.ReLU(inplace=True) )) for _ in range(1, blocks): layers.append(nn.Sequential( nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False), nn.BatchNorm2d(planes), nn.ReLU(inplace=True) )) return nn.Sequential(*layers) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) x = self.maxpool(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = torch.flatten(x, 1) x = self.fc(x) return x model = SENet() print(model)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值