Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sk-resnet50 #24

Open
Yao-DD opened this issue Nov 13, 2019 · 1 comment
Open

sk-resnet50 #24

Yao-DD opened this issue Nov 13, 2019 · 1 comment

Comments

@Yao-DD
Copy link

Yao-DD commented Nov 13, 2019

As paper(Selective Kernel Networks) said,the conventional convolution with a 5×5 kernel is replaced with the dilated convolution with a 3×3 kernel and dilation size 2. But the code is implemented as:
"
self.conv2g = conv3x3(planes, planes, stride, groups = 32)
self.bn2g = nn.BatchNorm2d(planes)
"
I can't understand why. Could you tell me? thank you.

@jianghaojun
Copy link

jianghaojun commented Jul 21, 2020

I found another two mistakes:

  • self.conv2 is not implemented as groupconv.
self.conv2 = conv3x3(planes, planes, stride)
self.bn2 = nn.BatchNorm2d(planes)
self.conv2g = conv3x3(planes, planes, stride, padding=2, dilation=2, groups = 32)
self.bn2g   = nn.BatchNorm2d(planes)

And I checked the sknet50.prototxt in original caffe repo, both of the conv3x3s' groups are 32:
conv2_1/3x3g32
conv2_1/3x3g32d2

  • As paper said, the output channel d for fc1 is follow this equation:

d = max(C/r, L), where L denotes the minimal value of d (L=32 is a typical setting our experiments).

However, the code is implemented as d = C/r, where r=16.

  • The following code is corrected:
class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, inplanes, planes, stride=1, downsample=None, reduction=16):
        super(Bottleneck, self).__init__()
        self.conv1 = conv1x1(inplanes, planes)
        self.bn1 = nn.BatchNorm2d(planes)

        self.conv2 = conv3x3(planes, planes, stride, padding=1,  groups=32)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv2g = conv3x3(planes, planes, stride, padding=2, dilation=2, groups = 32)
        self.bn2g   = nn.BatchNorm2d(planes)

        self.conv3 = conv1x1(planes, planes * self.expansion)
        self.bn3 = nn.BatchNorm2d(planes * self.expansion)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        reduction_planes = planes // reduction if planes // reduction > 32 else 32
        self.conv_fc1 = nn.Conv2d(planes, reduction_planes, 1, bias=False)
        self.bn_fc1   = nn.BatchNorm2d(reduction_planes)
        self.conv_fc2 = nn.Conv2d(reduction_planes, 2 * planes, 1, bias=False)

        self.D = planes

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        d1 = self.conv2(out)
        d1 = self.bn2(d1)
        d1 = self.relu(d1)

        d2 = self.conv2g(out)
        d2 = self.bn2g(d2)
        d2 = self.relu(d2)

        d  = self.avg_pool(d1) + self.avg_pool(d2)
        d = F.relu(self.bn_fc1(self.conv_fc1(d)))
        d = self.conv_fc2(d)
        d = torch.unsqueeze(d, 1).view(-1, 2, self.D, 1, 1)
        d = F.softmax(d, 1)
        d1 = d1 * d[:, 0, :, :, :].squeeze(1)
        d2 = d2 * d[:, 1, :, :, :].squeeze(1)
        d  = d1 + d2

        out = self.conv3(d)
        out = self.bn3(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants