implement ECA module by 1. adopting original eca_module.py into models folder 2. adding use_eca layer besides every instance of SE layerpull/82/head
parent
697e05cb3e
commit
f87fcd7e88
@ -0,0 +1,110 @@
|
|||||||
|
'''
|
||||||
|
ECA module from ECAnet
|
||||||
|
original paper: ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks
|
||||||
|
https://arxiv.org/abs/1910.03151
|
||||||
|
|
||||||
|
https://github.com/BangguWu/ECANet
|
||||||
|
original ECA model borrowed from original github
|
||||||
|
modified circular ECA implementation and
|
||||||
|
adoptation for use in pytorch image models package
|
||||||
|
by Chris Ha https://github.com/VRandme
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 BangguWu, Qilong Wang
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
'''
|
||||||
|
import torch
|
||||||
|
from torch import nn
|
||||||
|
from torch.nn.parameter import Parameter
|
||||||
|
|
||||||
|
|
||||||
|
class eca_layer(nn.Module):
|
||||||
|
"""Constructs a ECA module.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
channel: Number of channels of the input feature map
|
||||||
|
k_size: Adaptive selection of kernel size
|
||||||
|
"""
|
||||||
|
def __init__(self, channel, k_size=3):
|
||||||
|
super(eca_layer, self).__init__()
|
||||||
|
assert k_size % 2 == 1
|
||||||
|
self.avg_pool = nn.AdaptiveAvgPool2d(1)
|
||||||
|
self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
|
||||||
|
self.sigmoid = nn.Sigmoid()
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
# x: input features with shape [b, c, h, w]
|
||||||
|
b, c, h, w = x.size()
|
||||||
|
|
||||||
|
# feature descriptor on the global spatial information
|
||||||
|
y = self.avg_pool(x)
|
||||||
|
|
||||||
|
# Two different branches of ECA module
|
||||||
|
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
|
||||||
|
|
||||||
|
# Multi-scale information fusion
|
||||||
|
y = self.sigmoid(y)
|
||||||
|
|
||||||
|
return x * y.expand_as(x)
|
||||||
|
|
||||||
|
class ceca_layer(nn.Module):
|
||||||
|
"""Constructs a circular ECA module.
|
||||||
|
the primary difference is that the conv uses a circular padding rather than zero padding.
|
||||||
|
This is because unlike images, the channels themselves do not have inherent ordering nor
|
||||||
|
locality. Although this module in essence, applies such an assumption, it is unnecessary
|
||||||
|
to limit the channels on either "edge" from being circularly adapted to each other.
|
||||||
|
This will fundamentally increase connectivity and possibly increase performance metrics
|
||||||
|
(accuracy, robustness), without signficantly impacting resource metrics
|
||||||
|
(parameter size, throughput,latency, etc)
|
||||||
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
channel: Number of channels of the input feature map
|
||||||
|
k_size: Adaptive selection of kernel size
|
||||||
|
"""
|
||||||
|
def __init__(self, channel, k_size=3):
|
||||||
|
super(ceca_layer, self).__init__()
|
||||||
|
assert k_size % 2 == 1
|
||||||
|
self.avg_pool = nn.AdaptiveAvgPool2d(1)
|
||||||
|
#pytorch circular padding mode is bugged as of pytorch 1.4
|
||||||
|
# see https://github.com/pytorch/pytorch/pull/17240
|
||||||
|
#implement manual circular padding
|
||||||
|
self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding = 0, bias=False)
|
||||||
|
self.padding = (k_size - 1) // 2
|
||||||
|
self.sigmoid = nn.Sigmoid()
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
# x: input features with shape [b, c, h, w]
|
||||||
|
b, c, h, w = x.size()
|
||||||
|
# feature descriptor on the global spatial information
|
||||||
|
y = self.avg_pool(x)
|
||||||
|
|
||||||
|
#manually implement circular padding
|
||||||
|
y = torch.cat((y[:,:self.padding,:,:], y, y[:,-self.padding:,:,:]),dim=1)
|
||||||
|
|
||||||
|
|
||||||
|
# Two different branches of ECA module
|
||||||
|
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
|
||||||
|
|
||||||
|
# Multi-scale information fusion
|
||||||
|
y = self.sigmoid(y)
|
||||||
|
|
||||||
|
return x * y.expand_as(x)
|
Loading…
Reference in new issue