I can't concat, how should I do it?

YuhskeHujisaki: <aside class="onebox allowlistedgeneric" data-onebox-src="https://link.springer.com/chapter/10.1007/978-3-030-51935-3_11">
  <header class="source">
      <img src="https://link.springer.com/oscar-static/images/favicons/springerlink/favicon-eb9f5576a3.ico" class="site-icon" width="48" height="48">

      <a href="https://link.springer.com/chapter/10.1007/978-3-030-51935-3_11" target="_blank" rel="noopener nofollow ugc">SpringerLink</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:153/232;"><img src="https://static-content.springer.com/cover/book/978-3-030-51935-3.jpg" class="thumbnail" width="153" height="232"></div>

<h3><a href="https://link.springer.com/chapter/10.1007/978-3-030-51935-3_11" target="_blank" rel="noopener nofollow ugc">Incep-EEGNet: A ConvNet for Motor Imagery Decoding</a></h3>

  <p>The brain-computer interface consists of connecting the brain with machines using the brainwaves as a mean of communication for several applications that help to improve human life. Unfortunately, Electroencephalography that is mainly used to measure...</p>


  </article>

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

  <div style="clear: both"></div>
</aside>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/7/a/7ac881971bc698843e74f5253be4e27296db1734.png" data-download-href="https://discuss.pytorch.org/uploads/default/7ac881971bc698843e74f5253be4e27296db1734" title="image"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/7/a/7ac881971bc698843e74f5253be4e27296db1734_2_623x500.png" alt="image" data-base62-sha1="hwbPHN3tBPSPiHomH9XzlZm34Ms" width="623" height="500" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/7/a/7ac881971bc698843e74f5253be4e27296db1734_2_623x500.png, https://discuss.pytorch.org/uploads/default/original/3X/7/a/7ac881971bc698843e74f5253be4e27296db1734.png 1.5x, https://discuss.pytorch.org/uploads/default/original/3X/7/a/7ac881971bc698843e74f5253be4e27296db1734.png 2x" data-dominant-color="E5E1E7"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">685×549 115 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><br>
I’m creating a model like the one in the figure above, but concat doesn’t match the size and I get an error. RuntimeError: Sizes of tensors must match except in dimension 1. Expected size 128 but got size 64 for tensor number 2 in the list.<br>
How can I create one?</p>
<pre><code class="lang-auto">import torch
from torch import nn
import torch.nn.functional as F
class DepthwiseConv2d(torch.nn.Conv2d):
    def __init__(self,
                 in_channels,
                 depth_multiplier=1,
                 kernel_size=3,
                 stride=1,
                 padding=0,
                 dilation=1,
                 bias=True,
                 padding_mode='zeros'
                 ):
        out_channels = in_channels * depth_multiplier
        super().__init__(
            in_channels=in_channels,
            out_channels=out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            dilation=dilation,
            groups=in_channels,
            bias=bias,
            padding_mode=padding_mode
        )
class InceptionEEGNet(nn.Module):
  def __init__(self,bathsize): # input = (1,22,256)
    super().__init__()
    self.bathsize = bathsize
    self.conv2d_1 = nn.Conv2d(1,64,(1,16),padding='same')
    self.batchnorm2d_1 = nn.BatchNorm2d(64)
    self.conv2d_2 = DepthwiseConv2d(64,depth_multiplier=4,kernel_size=(22,1),padding='valid')
    self.batchnorm2d_elu_1 = nn.Sequential(
        nn.BatchNorm2d(256),
        nn.ELU()
        )
    self.averagepooling = nn.Sequential(
        nn.AvgPool2d((1,2)),
        nn.Dropout2d(p=0.5)
    )
    self.inception_block_1 = nn.Sequential(
        nn.Conv2d(256,64,(1,1),padding='same'),
        nn.Conv2d(64,64,(1,7),padding='same'),
    )
    self.inception_block_2 = nn.Sequential(
        nn.Conv2d(256,64,(1,1),padding='same'),
        nn.Conv2d(64,64,(1,9),padding='same'),
    )
    self.inception_block_3 = nn.Sequential(
        nn.AvgPool2d((1,2)),
        nn.Conv2d(256,64,(1,1),padding='same'),
    )
    self.inception_block_4 =  nn.Conv2d(256,64,(1,1),stride=(1,2))
    self.batchnorm2d_elu_2 = nn.Sequential(
        nn.BatchNorm2d(64),
        nn.ELU(),
        nn.Dropout2d(p=0.5)
        )
    self.conv2d_3 = nn.Conv2d(256,256,(1,5),padding='same')

  def forward(self,x):
    x = self.conv2d_1(x)
    x = self.batchnorm2d_1(x)
    x = self.conv2d_2(x)
    x = self.batchnorm2d_elu_1(x)
    x = self.averagepooling(x)
    print(x.shape)
    x1 = self.inception_block_1(x)
    print(x1.shape)
    x2 = self.inception_block_2(x)
    x3 = self.inception_block_3(x)
    x4 = self.inception_block_4(x)
    x = torch.cat((x1, x2, x3, x4), 1)
    x = self.batchnorm2d_elu_2(x)
    x = self.conv2d_3(x)
    x = self.batchnorm2d_elu_2(x)
    x = F.adaptive_avg_pool3d(x, (1,1,3))
    x = x.squeeze()
    return x

net = InceptionEEGNet(10)
x = torch.rand(10,1,22,256)
print(net(x).shape)
</code></pre>

ptrblck: <p>The spatial size doesn’t match as the <code>x1/2/3/4</code> tensors have the shape:</p>
<pre><code class="lang-python">torch.Size([10, 64, 1, 128])
torch.Size([10, 64, 1, 128])
torch.Size([10, 64, 1, 64])
torch.Size([10, 64, 1, 64])
</code></pre>
<p>Remove the pooling layer in <code>inception_block_3</code> and reduce the <code>stride</code> in <code>inception_block_4</code> to return tensors with a spatial size of <code>[1, 128]</code> and this part of the model will work.<br>
Afterwards, fix the channels of the <code>nn.BatchNorm2d</code> layer to <code>256</code> and the forward pass will work.</p>

YuhskeHujisaki: <p>Is this code different from the model in the paper above?</p>
<pre><code class="lang-auto">import torch
from torch import nn
import torch.nn.functional as F
class DepthwiseConv2d(torch.nn.Conv2d):
    def __init__(self,
                 in_channels,
                 depth_multiplier=1,
                 kernel_size=3,
                 stride=1,
                 padding=0,
                 dilation=1,
                 bias=True,
                 padding_mode='zeros'
                 ):
        out_channels = in_channels * depth_multiplier
        super().__init__(
            in_channels=in_channels,
            out_channels=out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            dilation=dilation,
            groups=in_channels,
            bias=bias,
            padding_mode=padding_mode
        )
class InceptionEEGNet(nn.Module):
  def __init__(self,bathsize): # input = (1,22,256)
    super().__init__()
    self.bathsize = bathsize
    self.conv2d_1 = nn.Conv2d(1,64,(1,16),padding='same')
    self.batchnorm2d_1 = nn.BatchNorm2d(64)
    self.conv2d_2 = DepthwiseConv2d(64,depth_multiplier=4,kernel_size=(16,1),padding='valid')
    self.batchnorm2d_elu_1 = nn.Sequential(
        nn.BatchNorm2d(256),
        nn.ELU()
        )
    self.averagepooling = nn.Sequential(
        nn.AvgPool2d((1,2)),
        nn.Dropout2d(p=0.5)
    )
    self.inception_block_1 = nn.Sequential(
        nn.Conv2d(256,64,(1,1),padding='same'),
        nn.Conv2d(64,64,(1,7),padding='same'),
    )
    self.inception_block_2 = nn.Sequential(
        nn.Conv2d(256,64,(1,1),padding='same'),
        nn.Conv2d(64,64,(1,9),padding='same'),
    )
    self.inception_block_3 = nn.Sequential(
        nn.Conv2d(256,64,(1,1),padding='same'),
    )
    self.inception_block_4 =  nn.Conv2d(256,64,(1,1))
    self.batchnorm2d_elu_2 = nn.Sequential(
        nn.BatchNorm2d(256),
        nn.ELU(),
        nn.Dropout2d(p=0.5)
        )
    self.conv2d_3 = nn.Conv2d(256,256,(1,5),padding='same')

  def forward(self,x):
    x = self.conv2d_1(x)
    x = self.batchnorm2d_1(x)
    x = self.conv2d_2(x)
    x = self.batchnorm2d_elu_1(x)
    x = self.averagepooling(x)
    x1 = self.inception_block_1(x)
    x2 = self.inception_block_2(x)
    x3 = self.inception_block_3(x)
    x4 = self.inception_block_4(x)
    x = torch.cat((x1, x2, x3, x4), 1)
    x = self.batchnorm2d_elu_2(x)
    x = self.conv2d_3(x)
    x = self.batchnorm2d_elu_2(x)
    x = F.adaptive_avg_pool3d(x, (1,1,3))
    x = x.squeeze()
    return x

net = InceptionEEGNet(10)
x = torch.rand(10,1,16,125)
print(net(x).shape)
</code></pre>

ptrblck: <p>Sorry, I haven’t read the thesis and the posted picture doesn’t show any shapes, so I just fixed your code.</p>
<p>EDIT: maybe the dimension in the concatenation is wrong and it should be e.g. <code>dim=3</code>?</p>

YuhskeHujisaki: <p>I think it connects to 3D.</p>