How to match sizes of Tensors for concatenation

username: exponential
cooked: <p>Hello,<br>
I am trying to modify densenet for my use case by taking the output of a denseblock and concat. it with another while retaining the information. See the code below:</p>
<pre><code class="lang-auto">class DenseNet(nn.Module):
    def __init__(self, growthRate, depth, reduction, bottleneck):
        super(DenseNet, self).__init__()

        nDenseBlocks = (depth - 4) // 3
        if bottleneck:
            nDenseBlocks //= 2

        nChannels = 2 * growthRate
        self.conv1 = nn.Conv2d(3, nChannels, kernel_size=3, padding=1,
                               bias=False)
        self.dense1 = self._make_dense(nChannels, growthRate, nDenseBlocks, bottleneck)
        nChannels += nDenseBlocks * growthRate
        nOutChannels = int(math.floor(nChannels * reduction))
        self.trans1 = Transition(nChannels, nOutChannels)

        nChannels = nOutChannels
        self.dense2 = self._make_dense(nChannels, growthRate, nDenseBlocks, bottleneck)
        nChannels += nDenseBlocks * growthRate
        nOutChannels = int(math.floor(nChannels * reduction))
        self.trans2 = Transition(516, nOutChannels)

       nChannels = nOutChannels
        self.dense3 = self._make_dense(nChannels, growthRate, nDenseBlocks, bottleneck)
        nChannels += nDenseBlocks * growthRate
        self.trans3 = Transition(nChannels, nOutChannels)

def _make_dense(self, nChannels, growthRate, nDenseBlocks, bottleneck):
        layers = []
        for i in range(int(nDenseBlocks)):
            if bottleneck:
                layers.append(Bottleneck(nChannels, growthRate))
            else:
                layers.append(SingleLayer(nChannels, growthRate))
            nChannels += growthRate
        return nn.Sequential(*layers)

    def forward(self, x):
        x_shape = x.shape[2:]
        out = self.conv1(x)
        out_a = self.dense1(out)  # A
#         out_a = self.dropout(out_a)
        print(f'Shape of out_a is {out_a.shape}')

        out_b = self.trans1(out_a.clone())
        print(f'Shape of out_b is {out_b.shape}')


        out_c = self.dense2(out_b)
        print(f'Shape of out_c is {out_c.shape}')
        out_d = torch.cat([out_c.clone(), out_a], 1)

        out_e = self.trans2(out_d.clone())
        out_f = self.dense3(out_e)
        out_g = torch.cat([out_f.clone(), out_d], 1)
        return out_g
</code></pre>
<p>However, when I tried to print my model summary, feeding it image size 224 x 224 of channel size 3 ==&gt; 3, 224, 224</p>
<pre><code class="lang-auto">from torchsummary import summary

summary(model, (3, 224, 224))
</code></pre>
<p>I get the following error</p>
<pre><code class="lang-auto">Shape of out_a is torch.Size([2, 216, 224, 224])
Shape of out_b is torch.Size([2, 108, 112, 112])
Shape of out_c is torch.Size([2, 300, 112, 112])
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
&lt;ipython-input-9-d3385e62fb19&gt; in &lt;module&gt;
      1 from torchsummary import summary
      2 
----&gt; 3 summary(model, (3, 224, 224), 16)

~/opt/anaconda3/envs/ge-mac/lib/python3.6/site-packages/torchsummary/torchsummary.py in summary(model, input_size, batch_size, device)
     70     # make a forward pass
     71     # print(x.shape)
---&gt; 72     model(*x)
     73 
     74     # remove these hooks

~/opt/anaconda3/envs/ge-mac/lib/python3.6/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    530             result = self._slow_forward(*input, **kwargs)
    531         else:
--&gt; 532             result = self.forward(*input, **kwargs)
    533         for hook in self._forward_hooks.values():
    534             hook_result = hook(self, input, result)

&lt;ipython-input-5-aa8ff12b625d&gt; in forward(self, x)
     88         out_c = self.dense2(out_b)
     89         print(f'Shape of out_c is {out_c.shape}')
---&gt; 90         out_d = torch.cat([out_c.clone(), out_a], 1)
     91 
     92 #         out_c_ =  F.interpolate(out_c.clone(), (224,224), mode='bilinear', align_corners=True)

RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension 1. Got 112 and 224 in dimension 2 at /Users/distiller/project/conda/conda-bld/pytorch_1579022036889/work/aten/src/TH/generic/THTensor.cpp:612```

After printing out the output shape, I could see there is a size mismatch, 
</code></pre>
<p>Shape of out_a is torch.Size([2, 216, 224, 224])<br>
Shape of out_b is torch.Size([2, 108, 112, 112])<br>
Shape of out_c is torch.Size([2, 300, 112, 112])```</p>
<p>I thought of upsampling the <code>out_c</code>  i.e using <code>F.interpolate(out_x, desired_shape, mode='bilinear', align_corners=True)</code><br>
but would this retain my information without altering it? if not, any other way to match the size for subsequent concatenation?<br>
Many thanks for the help</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="exponential" data-post="1" data-topic="156475">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/exponential/48/50889_2.png" class="avatar"> exponential:</div>
<blockquote>
<p>but would this retain my information without altering it?</p>
</blockquote>
</aside>
<p>Your suggested interpolation will use the <code>bilinear</code> interpolation so would change the activation tensor. It depends on your use case if this would be acceptable or if e.g. a nearest neighbor interpolation would be preferable.</p>

username: exponential
cooked: <p>thank you for your response,</p>
<p>I do not want a change in the activation tensor. I want to concat it as is, the interpolation should not change features. So, does this mean nearest neighbour allows for upsampling without a change in the activation tensors? I can’t seem to find enough documentation on bilinear and nearest interpolation.</p>

username: ptrblck
cooked: <p><a href="https://staff.fnwi.uva.nl/r.vandenboomgaard/IPCV20172018/LectureNotes/IP/Images/ImageInterpolation.html">These lecture notes</a> might help. In summary: nearest neighbor interpolation will reuse the value from its nearest neighbor, while (bi)linear interpolation will interpolate new values using the neighbors and their distance as the weight.</p>

username: exponential
cooked: <p>Many thanks ptrblck!<br>
This is explanatory, and the resource shared is useful.</p>