Losing my mind over mat1 dim1 and mat2 dim0

username: Jbrec
cooked: <p>Really losing my cool here with this CNN. I’m not sure where I am going wrong. Another set of eyes would be super helpful</p>
<pre><code class="lang-auto">import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import lr_scheduler


class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1,int(61952/8))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


CNNModel = Net()
print(CNNModel)
</code></pre>
<pre><code class="lang-auto">def train_model(model, criterion, optimizer, scheduler, num_epochs=20):
  device = torch.device("cuda")
  model.to(device)
  since = time.time()

  best_model_wts = copy.deepcopy(model.state_dict())
  best_acc = 0.0

  for epoch in range(num_epochs):
    print(f"Epoch {epoch+1}/{num_epochs}")
    print('----------------')

    # Each epoch has a training and validation phase
    for phase in ['mytrain', 'mytest']:
      if phase == 'mytrain':
        model.train()  # Set model to training mode
      else:
        model.eval()   # Set model to evaluate mode

      running_loss = 0.0
      running_corrects = 0

      # Iterate over data
      for inputs, labels in dataloaders[phase]:
        # move data to GPU
        inputs = inputs.to(device)
        labels = labels.to(device)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward
        # track history if only in train
        with torch.set_grad_enabled(phase == 'mytrain'):
          outputs = model(inputs)
          _, preds = torch.max(outputs, 1)
          loss = criterion(outputs, labels)

          # backward + optimize only if in training phase
          if phase == 'mytrain':
            loss.backward()
            optimizer.step()

        # statistics
        running_loss += loss.item() * inputs.size(0)
        running_corrects += torch.sum(preds == labels.data)

      # update learning rate with scheduler
      if phase == 'mytrain':CNNModel
      scheduler.step()

      epoch_loss = running_loss / dataset_sizes[phase]
      epoch_acc = running_corrects.double() / dataset_sizes[phase]

      print(f"{phase} loss: {epoch_loss:.4f} acc: {epoch_acc:.4f}")

      # deep copy the model with best accuracy on validation set
      if phase == 'mytest' and epoch_acc &gt; best_acc:
        best_acc = epoch_acc
        best_model_wts = copy.deepcopy(model.state_dict())

    print()

  time_elapsed = time.time() - since
  print(f"Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s")
  print(f"Best val acc: {best_acc:4f}")

  # load best model weights
  model.load_state_dict(best_model_wts)
  return model
</code></pre>
<pre><code class="lang-auto">loss = nn.CrossEntropyLoss()

optimizer = optim.SGD(CNNModel.parameters(), lr=0.01, momentum=0.5)

# Decay LR by a factor of 0.1 every 5 epochs

exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)

train_model(CNNModel, loss, optimizer, exp_lr_scheduler, num_epochs=20)
</code></pre>
<pre><code class="lang-auto">Epoch 1/20
----------------
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
&lt;ipython-input-567-757004c76098&gt; in &lt;module&gt;()
      6 exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
      7 
----&gt; 8 train_model(CNNModel, loss, optimizer, exp_lr_scheduler, num_epochs=20)

5 frames
&lt;ipython-input-566-0ce3493ed3b6&gt; in train_model(model, criterion, optimizer, scheduler, num_epochs)
     33         # track history if only in train
     34         with torch.set_grad_enabled(phase == 'mytrain'):
---&gt; 35           outputs = model(inputs)
     36           _, preds = torch.max(outputs, 1)
     37           loss = criterion(outputs, labels)

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--&gt; 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

&lt;ipython-input-563-8d673c2ca45f&gt; in forward(self, x)
     21         x = self.pool(F.relu(self.conv2(x)))
     22         x = x.view(-1,int(61952/8))
---&gt; 23         x = F.relu(self.fc1(x))
     24         x = F.relu(self.fc2(x))
     25         x = self.fc3(x)

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--&gt; 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/linear.py in forward(self, input)
     92 
     93     def forward(self, input: Tensor) -&gt; Tensor:
---&gt; 94         return F.linear(input, self.weight, self.bias)
     95 
     96     def extra_repr(self) -&gt; str:

/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in linear(input, weight, bias)
   1751     if has_torch_function_variadic(input, weight):
   1752         return handle_torch_function(linear, (input, weight), input, weight, bias=bias)
-&gt; 1753     return torch._C._nn.linear(input, weight, bias)
   1754 
   1755 

RuntimeError: mat1 dim 1 must match mat2 dim 0
</code></pre>

username: eqy
cooked: <p>It looks like the input to your first fully connected layer doesn’t match the requires shape. The view will yield a shape of [?, 7744] while the  layer expects an input shape of [?, 400] as 400 = 16 * 5 * 5.</p>

username: Jbrec
cooked: <p>Thank you for taking a look. I should be inputting a batch of 8, 3-channel images with shape 100x100. I have 7 class labels. I’m not too sure where I am going wrong. I updated my x.view to (-1,8) and still get dim errors</p>

username: Tejan_Mehndiratta
cooked: <p>update your <code>x.view</code> as <code>x = x.view(x.size(0), -1)</code> .</p>

username: Jbrec
cooked: <aside class="quote no-group" data-username="Tejan_Mehndiratta" data-post="4" data-topic="120494">
<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/tejan_mehndiratta/48/29857_2.png" class="avatar"> Tejan_Mehndiratta:</div>
<blockquote>
<p>x.view(x.size(0), -1)</p>
</blockquote>
</aside>
<p>Thanks for taking a look, I still get a mat1 dim error:</p>
<pre><code class="lang-auto">RuntimeError                              Traceback (most recent call last)
&lt;ipython-input-139-757004c76098&gt; in &lt;module&gt;()
      6 exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
      7 
----&gt; 8 train_model(CNNModel, loss, optimizer, exp_lr_scheduler, num_epochs=20)

5 frames
&lt;ipython-input-132-0ce3493ed3b6&gt; in train_model(model, criterion, optimizer, scheduler, num_epochs)
     33         # track history if only in train
     34         with torch.set_grad_enabled(phase == 'mytrain'):
---&gt; 35           outputs = model(inputs)
     36           _, preds = torch.max(outputs, 1)
     37           loss = criterion(outputs, labels)

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--&gt; 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

&lt;ipython-input-138-f35b0d1715f8&gt; in forward(self, x)
     21         x = self.pool(F.relu(self.conv2(x)))
     22         x = x.view(x.size(0), -1)
---&gt; 23         x = F.relu(self.fc1(x))
     24         x = F.relu(self.fc2(x))
     25         x = self.fc3(x)

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
    887             result = self._slow_forward(*input, **kwargs)
    888         else:
--&gt; 889             result = self.forward(*input, **kwargs)
    890         for hook in itertools.chain(
    891                 _global_forward_hooks.values(),

/usr/local/lib/python3.7/dist-packages/torch/nn/modules/linear.py in forward(self, input)
     92 
     93     def forward(self, input: Tensor) -&gt; Tensor:
---&gt; 94         return F.linear(input, self.weight, self.bias)
     95 
     96     def extra_repr(self) -&gt; str:

/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in linear(input, weight, bias)
   1751     if has_torch_function_variadic(input, weight):
   1752         return handle_torch_function(linear, (input, weight), input, weight, bias=bias)
-&gt; 1753     return torch._C._nn.linear(input, weight, bias)
   1754 
   1755 

RuntimeError: mat1 dim 1 must match mat2 dim 0

</code></pre>
<p>With:</p>
<pre><code class="lang-auto">class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 8)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(x.size(0), -1)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


CNNModel = Net()
</code></pre>

username: Tejan_Mehndiratta
cooked: <p>Do this:</p>
<p>class Net(nn.Module):</p>
<pre><code>def __init__(self):
    super(Net, self).__init__()
    self.conv1 = nn.Conv2d(3, 6, 5)
    self.conv2 = nn.Conv2d(6, 16, 5)
    self.pool = nn.MaxPool2d(2, 2)
    self.fc1 = nn.Linear(16 * 5 * 5, 120)
    self.fc2 = nn.Linear(120, 84)
    self.fc3 = nn.Linear(84, 8)

def forward(self, x):
    x = self.pool(F.relu(self.conv1(x)))
    x = self.pool(F.relu(self.conv2(x)))
    #x = x.view(x.size(0), -1)
    #x = F.relu(self.fc1(x))
    #x = F.relu(self.fc2(x))
    #x = self.fc3(x)
    return x
</code></pre>
<p>CNNModel = Net()</p>
<pre><code class="lang-auto">random_input = torch.randn(32, 3, 100, 100) (where 100x100 is your image dimension)

out = CNNModel(random_input)
out.shape
</code></pre>
<p>your out shape would be something like [32, C, W, H] and this C * W * H should be given as input to your self.fc1.</p>

username: Jbrec
cooked: <p>Wow amazing! Thank you so much!</p>
<p>my output was:<br>
torch.Size([32, 16, 22, 22])</p>
<p>why do I get the 22, 22?</p>

username: Tejan_Mehndiratta
cooked: <p>Because of the two conv layers and the pooling you are using. Check the math.<br>
Now, give 16x22x22 as input to self.fc1.</p>

username: Jbrec
cooked: <p>Apologies for my ignorance, but what numbers give me the product 22? I thought it was conv1 kernel* conv2 kernel?</p>

username: Tejan_Mehndiratta
cooked: <p>No, it’s not like that. Understand the math of convolution<br>
Check this link for conv documentation:</p>
<p><a href="https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d" class="onebox" target="_blank" rel="noopener nofollow ugc">https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d</a></p>