Pytorch
NLLLoss
loss function
C classes
machine learning

What are C classes for a NLLLoss loss function in Pytorch?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In torch.nn.NLLLoss, the letter C means the number of classes the model can predict. If your classifier chooses among ten labels, then C = 10, and the model output must contain one log-probability per class.

This is one of the most common sources of shape mistakes in PyTorch. Once you understand what C stands for, the expected input and target tensors become much easier to reason about.

What C Means in Practice

NLLLoss stands for negative log likelihood loss. It expects the model output to already be in log-probability space, which is why it is usually paired with log_softmax.

For a standard batch classification problem:

  • input shape is [N, C]
  • target shape is [N]
  • each target value is an integer class index from 0 to C - 1

N is the batch size. C is the number of classes.

If a model predicts three classes named cat, dog, and bird, then C is 3. The model output for one example might look like this:

python
1import torch
2import torch.nn.functional as F
3
4logits = torch.tensor([[2.0, 0.5, -1.0]])
5log_probs = F.log_softmax(logits, dim=1)
6print(log_probs)

That tensor has shape [1, 3], so C = 3.

Correct Pairing of Input and Target

The target tensor for NLLLoss is not one-hot encoded. It contains class indices.

Here is a complete runnable example:

python
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4
5logits = torch.tensor([
6    [2.0, 0.5, -1.0],
7    [0.1, 1.2, 0.3],
8    [-0.5, 0.2, 2.4],
9], dtype=torch.float32)
10
11targets = torch.tensor([0, 1, 2], dtype=torch.long)
12
13loss_fn = nn.NLLLoss()
14log_probs = F.log_softmax(logits, dim=1)
15loss = loss_fn(log_probs, targets)
16
17print("shape:", log_probs.shape)
18print("loss:", float(loss))

In that example:

  • batch size N is 3
  • number of classes C is 3
  • each target is a single integer telling PyTorch which class is correct

If you pass a target like [1, 0, 0] for one sample, that is the wrong format for NLLLoss.

Why log_softmax Matters

NLLLoss does not apply softmax for you. It expects log-probabilities as input.

That means this combination is correct:

python
output = F.log_softmax(logits, dim=1)
loss = nn.NLLLoss()(output, targets)

If you want a loss that combines both steps, use nn.CrossEntropyLoss instead. CrossEntropyLoss internally applies the log-softmax step before computing the negative log likelihood.

This pair of snippets shows the difference:

python
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4
5logits = torch.tensor([[1.0, 2.0, 0.5]])
6target = torch.tensor([1])
7
8nll = nn.NLLLoss()(F.log_softmax(logits, dim=1), target)
9ce = nn.CrossEntropyLoss()(logits, target)
10
11print(float(nll), float(ce))

The values match because CrossEntropyLoss wraps the extra transformation for you.

What Changes for Images or Sequences

For segmentation or sequence labeling, C still means number of classes, but the tensor gets extra dimensions.

For example, semantic segmentation often uses input shaped like [N, C, H, W] and targets shaped like [N, H, W]. Each pixel stores one class index. C is still just the count of possible labels.

Example:

python
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4
5logits = torch.randn(2, 4, 3, 3)
6targets = torch.randint(0, 4, (2, 3, 3))
7
8loss = nn.NLLLoss()(F.log_softmax(logits, dim=1), targets)
9print(float(loss))

Here the model predicts four classes for every pixel, so C = 4.

Class Weights and Ignored Labels

Because C is the class count, any class-weight tensor must also have length C.

python
weights = torch.tensor([1.0, 2.0, 0.5], dtype=torch.float32)
loss_fn = nn.NLLLoss(weight=weights)

This is useful for imbalanced datasets.

You can also skip a label with ignore_index, which is common in segmentation when some pixels should not contribute to the loss:

python
loss_fn = nn.NLLLoss(ignore_index=255)

The ignored label is not part of C. It is just a sentinel value in the target tensor.

Common Pitfalls

The most common bug is feeding raw logits directly into NLLLoss. That gives the wrong numeric interpretation because NLLLoss expects log-probabilities.

Another common mistake is supplying one-hot targets. NLLLoss wants integer class indices stored in a torch.long tensor, not vectors of zeros and ones.

Shape mismatches are also frequent. If the model output is [N, C], the target must be [N]. If the model output is [N, C, H, W], the target must be [N, H, W].

Finally, many people confuse C with batch size or feature count. In NLLLoss, C always refers to the number of mutually exclusive classes being predicted.

Summary

  • In NLLLoss, C means number of classes.
  • Standard classification input shape is [N, C], with target shape [N].
  • Targets are integer class indices, not one-hot vectors.
  • 'NLLLoss expects log-probabilities, so use log_softmax first.'
  • 'CrossEntropyLoss is the combined alternative when you have raw logits.'
  • For segmentation and sequence tasks, C stays the class count even when extra dimensions are present.

Course illustration
Course illustration

All Rights Reserved.