ECANet
ECANet copied to clipboard
Adaptive Kernel Size not implemented
It seems that the implementation under models/
differs from the paper's adaptive setting for k_size
, given in Fig 3 of the paper.
Why do the resnet, mobilenet modules not use adaptive kernel sizes?
It is a simple addition, but the resnet model seems to use a fixed k_size
instead.
same question.
class EcaLayer(nn.Module):
def __init__(self, channels, gamma=2, b=1):
super(EcaLayer, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
t = int(abs((math.log(channels, 2) + b) / gamma))
k_size = t if t % 2 else t + 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):
# 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)
Since channel numbers of any architecture (e.g., ResNet and MobileNet) are fixed, we could pre-compute kernel size of 1D convolution according to Eq.12, which was also done in our code.
Although adaptive kernel size according to Eq.12 could achieve further improvement over fixed ones, Eq.12 can be regarded as a guideline to choose kernel size for each channel in general. It indicates high dimensional channels have longer range interaction while low-dimensional ones undergo shorter range interaction. Base on such kind of guideline, we could might as well do some fine-tuning of kernel size in Eq.12, which sometimes bring a little performance gain. It also encourage us to find an optimal mapping function.
i implements the code with pytorch,but found that adaptive kernel size is not easy to implement.
we can't decide the right kernel size because it depends on the input channel.
when you implements it in forward function,you will get a error
Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same
add cuda() behind the conv can fix the problem
but when i print the module,the conv in the forward function seems not regist in the model.
Maybe this is why the author fixed the kernel number
`class EfficientChannelAttention(nn.Module):
def __init__(self, gamma=2, b=1):
super(EfficientChannelAttention, self).__init__()
self.gamma = gamma
self.b = b
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
N, C, H, W = x.size()
t = int(abs((log(C, 2) + self.b) / self.gamma))
k = t if t % 2 else t + 1
# TODO maybe need to fix ,check it
conv = nn.Conv1d(1, 1, kernel_size=k, padding=int(k / 2), bias=False).cuda()
y = self.avg_pool(x)
y = conv(y.squeeze(-1).transpose(-1, -2))
y = y.transpose(-1, -2).unsqueeze(-1)
y = self.sigmoid(y)
return x * y.expand_as(x)`
To clarify:
my application had pre-determined input channel sizes, hence works.
Something like ECA(channel_num=channel_num) for each layer was called.
Can you provide details regarding your implementation?
On 28-Jul-2020, at 3:09 PM, navimelon [email protected] wrote:
i implements the code with pytorch,but found that adaptive kernel size is not easy to implement. we can't decide the right kernel size because it depends on the input channel. when you implements it in forward function,you will get a error Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same add cuda() behind the conv can fix the problem but when i print the module,the conv in the forward function seems not regist in the model. Maybe this is why the author fixed the kernel number https://user-images.githubusercontent.com/31958916/88647816-fa6aee00-d0f8-11ea-9320-40fe9a62ac6b.png `class EfficientChannelAttention(nn.Module): """ Args: x:input features with shape [N,C,H,W] gamma:parameters of mapping function b:parameters of mapping function
"""
def init(self, gamma=2, b=1): super(EfficientChannelAttention, self).init() self.gamma = gamma self.b = b self.avg_pool = nn.AdaptiveAvgPool2d(1) self.sigmoid = nn.Sigmoid()
def forward(self, x): N, C, H, W = x.size() t = int(abs((log(C, 2) + self.b) / self.gamma)) k = t if t % 2 else t + 1 # TODO maybe need to fix ,check it conv = nn.Conv1d(1, 1, kernel_size=k, padding=int(k / 2), bias=False).cuda() y = self.avg_pool(x) y = conv(y.squeeze(-1).transpose(-1, -2)) y = y.transpose(-1, -2).unsqueeze(-1) y = self.sigmoid(y) return x * y.expand_as(x)` — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/BangguWu/ECANet/issues/24#issuecomment-664926242, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFBQJZ36PBARJJGPHC2ES5LR52MG3ANCNFSM4OL2NFLA.
@varun19299 Thank you for sharing!Run your code and find that the kernel size corresponding to resnet is 3,5,5,5, while the author set it to 3,3,3,3. What is the reason? Do they affect the end result?
I haven't shared any code.
However, @cloisonne 's reply is similar to what I used (https://github.com/BangguWu/ECANet/issues/24#issuecomment-652748916).
@navimelon is trying to dynamically compute the needed kernel size, which doesn't work.
thank you! According @cloisonne 's reply ,find that the kernel size corresponding to resnet is 3,5,5,5, while the author set it to 3,3,3,3.What is the reason? Do they affect the end result?
i implements the code with pytorch,but found that adaptive kernel size is not easy to implement. we can't decide the right kernel size because it depends on the input channel. when you implements it in forward function,you will get a error Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same add cuda() behind the conv can fix the problem but when i print the module,the conv in the forward function seems not regist in the model. Maybe this is why the author fixed the kernel number
`class EfficientChannelAttention(nn.Module):
def __init__(self, gamma=2, b=1): super(EfficientChannelAttention, self).__init__() self.gamma = gamma self.b = b self.avg_pool = nn.AdaptiveAvgPool2d(1) self.sigmoid = nn.Sigmoid() def forward(self, x): N, C, H, W = x.size() t = int(abs((log(C, 2) + self.b) / self.gamma)) k = t if t % 2 else t + 1 # TODO maybe need to fix ,check it conv = nn.Conv1d(1, 1, kernel_size=k, padding=int(k / 2), bias=False).cuda() y = self.avg_pool(x) y = conv(y.squeeze(-1).transpose(-1, -2)) y = y.transpose(-1, -2).unsqueeze(-1) y = self.sigmoid(y) return x * y.expand_as(x)`
conv = nn.Conv1d(1, 1, kernel_size=k, padding=int(k / 2), bias=False).cuda() should be defined in the function init().
thank you! According @cloisonne 's reply ,find that the kernel size corresponding to resnet is 3,5,5,5, while the author set it to 3,3,3,3.What is the reason? Do they affect the end result?
same question
I meet an error, who can help me? thanks a lot. RuntimeError: The expanded size of the tensor (64) must match the existing size (63) at non-singleton dimension 1. Target sizes: [8, 64, 256, 256]. Tensor sizes: [8, 63, 1, 1]
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, k_size, gamma=2, b=1):
super(eca_layer, self).__init__()
self.k_size = k_size
self.gamma = gamma
self.b = b
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size=self.k_size, padding=(self.k_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
b, c, h, w = x.size()
t = int(abs((math.log(c, 2) + self.b) / self.gamma))
self.k_size = t if t % 2 else t + 1
y = self.avg_pool(x)
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
y = self.sigmoid(y)
return x * y.expand_as(x)