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

Max pooling issue when stride is 1 #62

Open
ersheng-ai opened this issue May 25, 2020 · 4 comments
Open

Max pooling issue when stride is 1 #62

ersheng-ai opened this issue May 25, 2020 · 4 comments

Comments

@ersheng-ai
Copy link
Collaborator

In the original DarkNet model, the there are 3 max pooling layers of kernel size: 5, 9, 13, and stride is 1 for all of them.
But the solution in darknet2pytorch is confusing.
I don't know why kernel size is set to 2 when stride is 1 because it would not be mathematical identical.

                padding = 0
                if 'pad' in block.keys() and int(block['pad']) == 1:
                    padding = int((pool_size - 1) / 2)
                if stride > 1:
                    model = nn.MaxPool2d(pool_size, stride, padding=padding)
                else:
                    model = MaxPoolStride1()

and

class MaxPoolStride1(nn.Module):
    def __init__(self, size=2):
        super(MaxPoolStride1, self).__init__()
        self.size = size
        if (self.size - 1) % 2 == 0:
            self.padding1 = (self.size - 1) // 2
            self.padding2 = self.padding1
        else:
            self.padding1 = (self.size - 1) // 2
            self.padding2 = self.padding1 + 1

    def forward(self, x):
        x = F.max_pool2d(F.pad(x, (self.padding1, self.padding2, self.padding1, self.padding2), mode='replicate'),
                         self.size, stride=1)
        return x
@dhiyu
Copy link
Contributor

dhiyu commented May 25, 2020

I think it may be model = MaxPoolStride1(pool_size). But any one knows what is different between stride > 1 and stride == 1?

@ersheng-ai
Copy link
Collaborator Author

I think it may be model = MaxPoolStride1(pool_size). But any one knows what is different between stride > 1 and stride == 1?

You can simply do this to temporarily bypass this issue:

if pool_size == 5:
    model = nn.MaxPool2d(5,  1,  padding=2)
elif pool_size == 9:
    model = nn.MaxPool2d(9,  1,  padding=4)
else: # pool_size == 13
    model = nn.MaxPool2d(13,  1,  padding=6)

@Tianxiaomo
Copy link
Owner

This is result of the difference between darknet and pytorch's implementation of padding.

darknet parser.c

maxpool_layer parse_maxpool(list *options, size_params params)
{
...
    int size = option_find_int(options, "size",stride);
    int padding = option_find_int_quiet(options, "padding", size-1);
...
   maxpool_layer layer = make_maxpool_layer(batch, h, w, c, size, stride_x, stride_y, padding, maxpool_depth, out_channels, antialiasing, avgpool, params.train);
    return layer;
}

darknet maxpool_layer.c

maxpool_layer make_maxpool_layer(int batch, int h, int w, int c, int size, int stride_x, int stride_y, int padding, int maxpool_depth, int out_channels, int antialiasing, int avgpool, int train)
{
...
    if (maxpool_depth) {
        l.out_c = out_channels;
        l.out_w = l.w;
        l.out_h = l.h;
    }
    else {
        l.out_w = (w + padding - size) / stride_x + 1;
        l.out_h = (h + padding - size) / stride_y + 1;
        l.out_c = c;
    }
...
}

It can be found that the darknet's pad parameter is set to '1' and the padding is 'SAME' in tensorflow is the same.
but in pytorch,
padding: implicit zero padding to be added on both sides.

So I do n’t have a beautiful way to deal with it.:sweat:

@ersheng-ai
Copy link
Collaborator Author

Make the solution perfect and universal is difficult but the minimum requirement is that you make YOLOv4/v3 correct.
So, take it easy.

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

3 participants