Can't find RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of dimension: 1

Maxim_Stuff: <p>Hello, I’ve got a following error:</p>
<pre><code class="lang-python">    RuntimeError                              Traceback (most recent call last)
    &lt;timed exec&gt; in &lt;module&gt;

    /var/folders/m8/5njk8q3d30v78xxjn6n610km0000gn/T/ipykernel_12796/1284205556.py in train(model,              opt, n_epochs)
     63     for epoch in range(n_epochs):
     64         print("Epoch {} of {}".format(epoch, n_epochs))
---&gt; 65         train_loss, train_acc = train_epoch(model, opt, batchsize=batchsize)
     66 
     67         val_loss, val_acc = test(model)

    /var/folders/m8/5njk8q3d30v78xxjn6n610km0000gn/T/ipykernel_12796/1284205556.py in     train_epoch(model, optimizer, batchsize)
     15         acc_log.append(acc)
     16 
---&gt; 17         loss = F.nll_loss(output, target)
     18         loss.backward()
     19         optimizer.step()

~/opt/anaconda3/lib/python3.9/site-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
   2530     if size_average is not None or reduce is not None:
   2531         reduction = _Reduction.legacy_get_string(size_average, reduce)
-&gt; 2532     return torch._C._nn.nll_loss_nd(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   2533 
   2534 

RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of dimension: 1
</code></pre>
<p>My model is:</p>
<pre><code>class ConvNet(nn.Module):
    def __init__(self):
        super().__init__()
    
    self.features = nn.Sequential(
        nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1),
        nn.ReLU(),
        nn.MaxPool2d((2, 2)),
        nn.Conv2d(in_channels=6, out_channels=4, kernel_size=5, stride=1),
        nn.ReLU(),
        nn.MaxPool2d((2, 2)),
        nn.Linear(4, 4 * 4 * 16),
    )
    
    self.classifier = nn.Linear(4 * 4 * 16, 10)

    
def forward(self, x):
    print(x.size())
    x = x.reshape(32, 28, 28)[:, None, :, :]
    print(x.size())
    x = self.features(x)
    #x = torch.flatten(x, 1)
    print(x.size())
    out = self.classifier(x)
    print(out.size())

    return F.log_softmax(out, dim=-1)
</code></pre>
<p>With the following code:</p>
<p>from util import iterate_minibatches</p>
<pre><code>def train_epoch(model, optimizer, batchsize=32):
loss_log, acc_log = [], []
model.train()
    for x_batch, y_batch in iterate_minibatches(X_train, y_train, batchsize=batchsize, shuffle=True):
        data = torch.from_numpy(x_batch.astype(np.float32))
        target = torch.from_numpy(y_batch.astype(np.int64))

        optimizer.zero_grad()
        output = model(data)
    
        pred = torch.max(output, 1)[1].numpy()
        acc = np.mean(pred == y_batch)
        acc_log.append(acc)
    
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        loss = loss.item()
        loss_log.append(loss)
    return loss_log, acc_log

def test(model):
    loss_log, acc_log = [], []
    model.eval()
    for x_batch, y_batch in iterate_minibatches(X_val, y_val, batchsize=32, shuffle=True):
        data = torch.from_numpy(x_batch.astype(np.float32))
        target = torch.from_numpy(y_batch.astype(np.int64))

        output = model(data)
        loss = F.nll_loss(output, target)
    
        pred = torch.max(output, 1)[1].numpy()
        acc = np.mean(pred == y_batch)
        acc_log.append(acc)
    
        loss = loss.item()
        loss_log.append(loss)
    return loss_log, acc_log

def plot_history(train_history, val_history, title='loss'):
    plt.figure()
    plt.title('{}'.format(title))
    plt.plot(train_history, label='train', zorder=1)

    points = np.array(val_history)

    plt.scatter(points[:, 0], points[:, 1], marker='+', s=180, c='orange', label='val', zorder=2)
    plt.xlabel('train steps')
    
    plt.legend(loc='best')
    plt.grid()

    plt.show()

def train(model, opt, n_epochs):
    train_log, train_acc_log = [], []
    val_log, val_acc_log = [], []

    batchsize = 32

    for epoch in range(n_epochs):
        print("Epoch {} of {}".format(epoch, n_epochs))
        train_loss, train_acc = train_epoch(model, opt, batchsize=batchsize)

       val_loss, val_acc = test(model)

        train_log.extend(train_loss)
        train_acc_log.extend(train_acc)

        steps = len(X_train) / batchsize
        val_log.append((steps * (epoch + 1), np.mean(val_loss)))
        val_acc_log.append((steps * (epoch + 1), np.mean(val_acc)))

        clear_output()
        plot_history(train_log, val_log)    
        plot_history(train_acc_log, val_acc_log, title='accuracy')
        print("Epoch {} error = {:.2%}".format(epoch, 1 - val_acc_log[-1][1]))
        
    print("Final error: {:.2%}".format(1 - val_acc_log[-1][1]))
</code></pre>
<p>I am running model with:</p>
<p>model = ConvNet()<br>
opt = torch.optim.RMSprop(model.parameters(), lr=0.001)<br>
train(model, opt, 5)</p>
<p>Dataset is MNIST:</p>
<pre><code>  from util import load_mnist
  X_train, y_train, X_val, y_val, X_test, y_test = load_mnist(flatten=True)

  plt.figure(figsize=[6, 6])
  for i in range(4):
     plt.subplot(2, 2, i + 1)
     plt.title("Label: %i" % y_train[i])
     plt.imshow(X_train[i].reshape([28, 28]), cmap='gray');
</code></pre>
<p>I can’t find an answer in other topics <img src="https://discuss.pytorch.org/images/emoji/apple/frowning.png?v=12" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p>

ptrblck: <p>Based on the error message it seems your model output might be 4-dimensional as seen here:</p>
<pre><code class="lang-python">criterion = nn.NLLLoss()

output = torch.randn(2, 3, 4, 4, requires_grad=True)
target = torch.randint(0, 3, (2,))
loss = criterion(output, target)
# RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of dimension: 1

output = torch.randn(2, 3, requires_grad=True)
loss = criterion(output, target) # works
</code></pre>
<p>However, I cannot find any obvious issues in your code as it seems you are properly flattening the activation, so could you post a minimal, executable code snippet reproducing the error, please?</p>

Maxim_Stuff: <p>I have updated and posted literally all the code that I have</p>

ptrblck: <p>Your code is unfortunately still not executable, but I just saw that you’ve commented out the flattening operation:</p>
<pre><code class="lang-python">#x = torch.flatten(x, 1)
</code></pre>
<p>Use it again, check for shape mismatches in linear layers, fix these (if applicable), and it should work.</p>

Maxim_Stuff: <aside class="quote no-group" data-username="ptrblck" data-post="4" data-topic="162741">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p><code>flatten</code></p>
</blockquote>
</aside>
<p>I realized that I’ve got 2 dense layers and I deleted the raw</p>
<blockquote>
<p>nn.Linear(4, 4 * 4 * 16),</p>
</blockquote>
<p>in my model.</p>
<p>But now I have with matrices:<br>
RuntimeError: mat1 and mat2 shapes cannot be multiplied (672x7 and 256x10)</p>
<p>How should I choose parameters to fix it? I haven’t been able to select them for quite a while now.</p>

ptrblck: <p>The shape sounds wrong, since you were previously using a batch size of 32 based on your code.<br>
You should also not use a linear layer in the <code>features</code> pat without flattening the activation unless you really want to apply the linear layer sequentially only on the width dimension of the forward activation.<br>
This code should work:</p>
<pre><code class="lang-python">class ConvNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1),
            nn.ReLU(),
            nn.MaxPool2d((2, 2)),
            nn.Conv2d(in_channels=6, out_channels=4, kernel_size=5, stride=1),
            nn.ReLU(),
            nn.MaxPool2d((2, 2)),
        )
        self.classifier = nn.Linear(64, 10)
        
    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, 1)
        out = self.classifier(x)
        return F.log_softmax(out, dim=-1)
    
model = ConvNet()
x = torch.randn(32, 1, 28, 28)
out = model(x)
</code></pre>

Maxim_Stuff: <p>Yeah, this works! Thanks a lot!</p>