ECANet icon indicating copy to clipboard operation
ECANet copied to clipboard

Adaptive Kernel Size not implemented

Open varun19299 opened this issue 4 years ago • 12 comments

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?

varun19299 avatar Jun 30 '20 04:06 varun19299

It is a simple addition, but the resnet model seems to use a fixed k_size instead.

varun19299 avatar Jun 30 '20 04:06 varun19299

same question.

ykk648 avatar Jul 02 '20 02:07 ykk648

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)

ykk648 avatar Jul 02 '20 02:07 ykk648

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.

BangguWu avatar Jul 06 '20 13:07 BangguWu

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 image

`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)`

xiaomoguhzz avatar Jul 28 '20 09:07 xiaomoguhzz

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 avatar Jul 28 '20 10:07 varun19299

@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?

lampardwk avatar Aug 02 '20 02:08 lampardwk

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.

varun19299 avatar Aug 02 '20 03:08 varun19299

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?

lampardwk avatar Aug 02 '20 03:08 lampardwk

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 image

`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().

dongsheng1991 avatar Sep 14 '20 07:09 dongsheng1991

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

xcliang2 avatar Nov 07 '20 12:11 xcliang2

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)

15114218 avatar Dec 17 '20 03:12 15114218