1-channel Resnet50 not working with different input sizes

theguijo: <p>Hi! I’m using the following ResNet50:</p>
<pre><code class="lang-auto">ResNet(
  (conv1): Conv2d(1, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (layer1): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential(
        (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (2): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
  )
  (layer2): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (2): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (3): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
  )
  (layer3): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential(
        (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (2): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (3): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (4): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (5): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
  )
  (layer4): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential(
        (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
    (2): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (shortcut): Sequential()
    )
  )
  (linear): Linear(in_features=2048, out_features=2, bias=True)
)
</code></pre>
<p>The images only include one channel. I run this code with different input sizes (different problems). For these input sizes, the code works perfectly:</p>
<pre><code class="lang-auto">[batch_size, 1, 32, 32]
[batch_size, 1, 36, 36]
[batch_size, 1, 41, 41]
[batch_size, 1, 48, 48]
</code></pre>
<p>However, for datasets with a higher input size, such as [batch_size, 1, 58, 58] or even higher, the code gave me the following error:</p>
<pre><code class="lang-auto">RuntimeError: size mismatch, m1: [32 x 8192], m2: [2048 x 2] at /pytorch/aten/src/THC/generic/THCTensorMathBlas.cu:283
</code></pre>
<p>The thing is that I don’t know where the 8192 comes from. The 32 is the batch size, the 2048 comes from the linear layer (512*expansion blocks, which is 4) and the 2 is the number of classes.</p>
<p>It’s so weird that it only works with small images.</p>
<p>Many thanks in advance.</p>
<p>Best!</p>

Isaac_Kargar: <p>You have to use standard image size as resnet50. It cannot handle different image sizes and the 8192 is the size of flattened featuremap. If you use the standard image size, the flattened tensor will have 2048 and this error will disappear. I think the standard size is 224x224. You need to resize your images before feeding them into resent. check <a href="https://pytorch.org/hub/pytorch_vision_resnet/" rel="nofollow noopener">this</a>.</p>

theguijo: <p>Thanks for the quick response.</p>
<p>I’m sorry, I think I’ve explained myself in a wrong way. All my images have the same size, I meant that running the same code with images with other sizes make it to fail. But if the images are bigger than 48x48, it fails.</p>
<p>Do you know if a resizing is automatically done depending on the input size? For instance, for sizes smaller or equal than 48, it is done, whereas for higher than 48 it isn’t.</p>
<p>Many thanks in advance!</p>

Nikronic: <p>Hi,</p>
<p>In all of resnets and even in your resnet50 (although you have removed some downsampling and pooling layers plus changed first layer to accept images with 1 channel), images get smaller and smaller and the reason is the definition of Conv2d. In each convolution, your input dimension let’s say <code>x</code> will be reduced to <code>floor((x - kernel_size + 2* padding_size) / stride) + 1</code> and pooling layers just are a division by <code>stride</code>. So, What I meant is that if your model works for <code>[x, x]</code> input (batch_size does not matter as you said so), it must also work for <code>[y, y]</code> where <code>y &gt; x</code>.<br>
If you could share your model definition and stacktrace of error, it would be great as currently, it is hard to follow and apply some tests.</p>
<p>Also, about the definition of original resents, all of those accept inputs equal or bigger than <code>[224, 224]</code>. Less than this will lead to <code>[batch_size, 0, ...]</code> which literally is a zero size tensor. That is why I cannot figure it our why your model is ok with smaller size.</p>
<p>bests</p>

theguijo: <p>Thank you very much, Nicronik.</p>
<p>This is the code I’m using for ResNet50:</p>
<pre><code class="lang-auto">class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, in_planes, planes, stride=1):
        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
                               stride=stride, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, self.expansion *
                               planes, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(self.expansion*planes)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion*planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion*planes,
                          kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion*planes)
            )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.relu(self.bn2(self.conv2(out)))
        out = self.bn3(self.conv3(out))
        out += self.shortcut(x)
        out = F.relu(out)
        return out


class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes, channels):
        super(ResNet, self).__init__()
        self.in_planes = 64

        self.conv1 = nn.Conv2d(channels, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.linear = nn.Linear(512*block.expansion, num_classes)

    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = F.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out


def ResNet50(num_classes, channels):
    return ResNet(Bottleneck, [3, 4, 6, 3], num_classes, channels)
</code></pre>
<p>As you’ve said, I’ve adapted the first layer to accept 1 channel images, but that is everything I’ve modify from the original ResNet50.</p>
<p>I have this testing code:</p>
<pre><code class="lang-auto">def test():
    net = ResNet50(num_classes=2, channels=1)
    criterion = nn.CrossEntropyLoss(reduction='sum')
    inputs = torch.randn(2, 1, 56, 56)
    label = torch.tensor([0, 1])

    outputs = net(inputs)
    loss = criterion(outputs, label)
    print(loss.item())
</code></pre>
<p>If you run it using inputs with size upto 56x56, it works fine. However, if you increase the size to 57x57 or more, it fails, giving the following stacktrace of error:</p>
<pre><code class="lang-auto">  File "/home/david/main.py", line 15, in test
    outputs = net(inputs)
  File "//torch/nn/modules/module.py", line 550, in __call__
    result = self.forward(*input, **kwargs)
  File "/home/david/ResNet50.py", line 208, in forward
    out = self.linear(out)
  File "/torch/nn/modules/module.py", line 550, in __call__
    result = self.forward(*input, **kwargs)
  File "/torch/nn/modules/linear.py", line 87, in forward
    return F.linear(input, self.weight, self.bias)
  File "/torch/nn/functional.py", line 1610, in linear
    ret = torch.addmm(bias, input, weight.t())
RuntimeError: size mismatch, m1: [2 x 8192], m2: [2048 x 2] at /pytorch/aten/src/THC/generic/THCTensorMathBlas.cu:283
</code></pre>
<p>Many thanks!</p>

Isaac_Kargar: <p>I checked your code. It seems that the shape of the tensor after your average pooling layer is <code>torch.Size([2, 2048, 1, 1])</code> for images with the size lower than 57x57 and for images with higher size, the size would be sth like <code>torch.Size([2, 2048, x, x])</code> which x is bigger than 1. So the number of neurons will be incompatible with the next fully-connected layer which always expects a fixed size tensor. So for bigger input images, it raises an error.</p>

Nikronic: <aside class="quote no-group" data-username="theguijo" data-post="6" data-topic="81803">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/t/bc8723/48.png" class="avatar"> theguijo:</div>
<blockquote>
<p><code>out = F.avg_pool2d(out, 4)</code></p>
</blockquote>
</aside>
<p>This is the problem. Original resnet uses <code>adaptive_avg_pool2d(out, (1, 1))</code> in its last layer before connecting it to linear layer. So, if you change this line to<br>
<code>out = F.adaptive_avg_pool2d(out, (1, 1))</code>,<br>
your model will work just fine. This layer forces output to be in shape of <code>output_size=(1, 1)</code>.</p>
<p>Here is a post about how it works:</p><aside class="quote" data-post="1" data-topic="26897">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/x/9dc877/48.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/what-is-adaptiveavgpool2d/26897">What is AdaptiveAvgPool2d?</a> 
  </div>
  <blockquote>
    The AdaptiveAvgPool2d layers confuse me a lot. 
Is there any math formula explaning it?
  </blockquote>
</aside>

<p>Here is the link to source code of this line:</p><aside class="onebox githubblob" data-onebox-src="https://github.com/pytorch/vision/blob/e6d3f8c515ee1a4bbda4c17594b00a4e5cb58e07/torchvision/models/resnet.py#L157">
  <header class="source">

      <a href="https://github.com/pytorch/vision/blob/e6d3f8c515ee1a4bbda4c17594b00a4e5cb58e07/torchvision/models/resnet.py#L157" target="_blank" rel="noopener nofollow ugc">github.com</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/pytorch/vision/blob/e6d3f8c515ee1a4bbda4c17594b00a4e5cb58e07/torchvision/models/resnet.py#L157" target="_blank" rel="noopener nofollow ugc">pytorch/vision/blob/e6d3f8c515ee1a4bbda4c17594b00a4e5cb58e07/torchvision/models/resnet.py#L157</a></h4>



    <pre class="onebox"><code class="lang-py">
      <ol class="start lines" start="147" style="counter-reset: li-counter 146 ;">
          <li>self.bn1 = norm_layer(self.inplanes)</li>
          <li>self.relu = nn.ReLU(inplace=True)</li>
          <li>self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)</li>
          <li>self.layer1 = self._make_layer(block, 64, layers[0])</li>
          <li>self.layer2 = self._make_layer(block, 128, layers[1], stride=2,</li>
          <li>                               dilate=replace_stride_with_dilation[0])</li>
          <li>self.layer3 = self._make_layer(block, 256, layers[2], stride=2,</li>
          <li>                               dilate=replace_stride_with_dilation[1])</li>
          <li>self.layer4 = self._make_layer(block, 512, layers[3], stride=2,</li>
          <li>                               dilate=replace_stride_with_dilation[2])</li>
          <li class="selected">self.avgpool = nn.AdaptiveAvgPool2d((1, 1))</li>
          <li>self.fc = nn.Linear(512 * block.expansion, num_classes)</li>
          <li></li>
          <li>for m in self.modules():</li>
          <li>    if isinstance(m, nn.Conv2d):</li>
          <li>        nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')</li>
          <li>    elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):</li>
          <li>        nn.init.constant_(m.weight, 1)</li>
          <li>        nn.init.constant_(m.bias, 0)</li>
          <li></li>
          <li># Zero-initialize the last BN in each residual branch,</li>
      </ol>
    </code></pre>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>bests</p>

theguijo: <p>Thank you very much Nikronic and Isaac_Kargar for your help.</p>
<p>I’ve already solved my problem!</p>
<p>Thanks again.</p>