Concepts / Converting Logits to Class Labels

Converting Logits to Class Labels

Softmax changes the values in a row, but it does not change which position holds the largest value. If the only goal is a predicted label, argmax on the logits gives the same label as argmax on the probabilities.

  • Programming

Why One Prediction Is Not Enough

Earlier, a model's outputs were turned into class labels one example at a time. That works for a single example, but a training set or test set contains many examples, and what we usually want is one number that summarizes how often the model is right across all of them. This article builds the pieces that produce that number: first a way to turn each row of model outputs into a single class label, then a reusable function that counts correct predictions over an entire dataset.

A classifier does not usually answer with a class name. For each input it produces a row of numbers, one number per possible class, describing how strongly the model leans toward each class. Before reading the explanation, try the following question. Given the row of scores below, which position would you pick as the model's decision?

What do you think happens?

For the row of logits [2.1, 0.3, 1.7], which position does torch.argmax return when it scans the row?

  • Position 0

  • Position 1

  • Position 2

Reveal answer
Answer:

Position 0

Argmax returns the position of the largest value in the row. The largest value here is 2.1, which sits at position 0.

Picking the Largest Score in Each Row

The function torch.argmax returns the index of the highest value in a tensor. With dim=1, it scans each row and returns, for every row, the position of that row's largest value. Turning a row of class scores into a single class label is exactly what this does: the returned position is the predicted class.

Position 02.1Argmax result0Position 10.3Position 21.7largest value
Given one row of three logits, which position does argmax return, and how does that position become the predicted class?
Worked example

Reading one row of logits

A model produces the row [2.1, 0.3, 1.7] for one example. Use torch.argmax with dim=1 to find the predicted class label.

  1. 1
    Identify the row

    The row has three numbers, one per possible class: 2.1 at position 0, 0.3 at position 1, and 1.7 at position 2.

  2. 2
    Find the largest value

    Comparing the three values, 2.1 is the largest.

  3. 3
    Return its position

    2.1 sits at position 0, so argmax with dim=1 returns 0. The predicted class label for this example is 0.

Result

The predicted class label is 0.

Notice what argmax does not return. It does not return the value 2.1. It returns the position of that value. The class label is the position, which is why the output of argmax is a set of integers, one per row.

Why the Dimension Argument Sets the Direction

The dimension argument decides the direction of the search. With dim=1, the function scans each row. Changing it to dim=0 scans down each column instead and returns, for every column, the row position of its largest value. That second result answers a different question, so using the wrong dimension is one of the most common ways to get label predictions that look plausible but mean something else.

Logits Versus Softmax Probabilities

The same argmax operation applies to probabilities and to the raw outputs of the network. Computing softmax first and then calling argmax is a valid path, but it is not required to obtain class labels. The position of the largest value is the same whether you look at the logits or at the probabilities computed from them, so argmax can be applied to the logits directly.

Logits row2.1, 0.3, 1.7Argmax position0Probabilities rowsoftmax of the logitsArgmax position0argmaxargmax
Both paths produce a position for the same example. The values differ between the two columns, but the position of the largest value is the same.
Key point

Softmax changes the values in a row, but it does not change which position holds the largest value. If the only goal is a predicted label, argmax on the logits gives the same label as argmax on the probabilities.

Comparing Predictions With the True Labels

Once there are predicted labels, the next question is whether they match the true labels. The == operator compares two tensors element by element and returns a tensor of booleans, one for each position, where True means the prediction matched the true label at that position. Adding up the True values then counts the correct predictions. The source does this with torch.sum, which counts the True entries in the boolean tensor produced by the comparison.

Code walkthrough
import torch

predicted = torch.tensor([0, 2, 1, 1, 0])
true_labels = torch.tensor([0, 2, 1, 1, 0])

matches = predicted == true_labels
print(matches)

correct = torch.sum(matches)
print(correct)
  1. 1
    The predicted tensor and the true-label tensor each hold one integer per example, so their positions line up.
  2. 2
    The == operator returns a boolean tensor. Each position is True where the predicted label equals the true label.
  3. 3
    torch.sum adds the True entries, treating each True as 1, which gives the number of correct predictions.
  • predicted holds one integer label per example
  • == compares the two tensors position by position
  • torch.sum counts the True entries
Output
tensor([True, True, True, True, True])
tensor(5)

The source uses a training set of five examples in which all five predictions are correct. In that case the comparison is all True and the count is 5.

Turning a Count into Accuracy

Accuracy is the fraction of predictions that were correct. Because the correct count can never exceed the total count of examples, the fraction always falls between 0 and 1. A result of 0 means no predictions matched, and a result of 1 means all of them matched. Expressed as a percentage, the same fraction is multiplied by 100.

Rule

Rule

Worked example

Accuracy from a count of matches

The comparison produces three True values out of four positions. What is the accuracy, as a fraction and as a percentage?

  1. 1
    Identify the counts

    The number of correct predictions is 3, and the total number of examples is 4.

  2. 2
    Divide

    The fraction is $\frac{3}{4}$.

  3. 3
    Convert to a percentage

    Multiplying by 100 gives $\frac{3}{4} \times 100 = 75$.

Result

The accuracy is three quarters, or 75 percent.

Looping Over Batches in compute_accuracy

The accuracy function does not send the whole dataset through the model at once. A dataset may be far too large for memory, so the function gives the model only one chunk at a time. Each chunk has the same size as the batch size used during training. The function does its work in a single loop over the data loader. On each pass, one batch of features and labels arrives, the model produces logits for that batch, and those logits are converted into predicted labels. The predicted labels are compared with the true labels, and the count of matches is added to a running total of correct predictions. The number of examples in the batch is added to a running count of all examples.

Data loader batchfeatures and labelsModel logitsone row per exampleArgmax dim=1one label per rowCompare with truelabels== gives booleanstorch.sumcount of matchesRunning totalscorrect and totalAccuracycorrect divided by totalmodel callrow maximumpredicted labelsbooleansadd batch countafter last batch
Each batch passes through the same steps, and the counters carry results forward until the loader has no batches left.
Code walkthrough
import torch

def compute_accuracy(model, data_loader):
    correct = 0
    total = 0
    for features, labels in data_loader:
        logits = model(features)
        predictions = torch.argmax(logits, dim=1)
        matches = predictions == labels
        correct += torch.sum(matches)
        total += len(labels)
    accuracy = correct / total
    return float(accuracy)
  1. 1
    The two counters start at zero and carry results across batches.
  2. 2
    The for loop receives one batch of features and labels each time, so the whole dataset is never passed to the model at once.
  3. 3
    The model produces logits for the batch, and argmax with dim=1 converts each row into a predicted class label.
  4. 4
    The == comparison gives a boolean per example, torch.sum counts the True entries, and both counters are updated.
  5. 5
    After the loop ends, the correct count is divided by the total count, and the result is converted to an ordinary Python float.
  • The loop handles one batch per pass
  • argmax with dim=1 runs on the logits directly
  • The final line returns a Python float

Because the counters carry results forward batch by batch, the final accuracy covers the full dataset even though the model never saw all of it in one call. The same function therefore works for datasets of any size, not just the small ones that fit in memory.

Same Function, Training Loader Versus Test Loader

The function is applied to the training data first and then to the test data, using the same model in both calls. Each call prints one value. The two calls differ only in the data loader they receive: the input examples and true labels change, while the function and the model stay the same.

Before you run the two calls, decide what kind of value each one returns and what range that value can take. Because each result is a count of correct predictions divided by a count of all examples, every printed value lies between 0 and 1. A printed value of 0 would mean no predictions matched on that loader, and a printed value of 1 would mean all of them matched. The two printed values can differ because they are computed over different examples.

Mistakes That Produce Wrong Accuracy

  • Common mistake

    Using dim=0 instead of dim=1 in argmax

    What it looks like

    Calling torch.argmax(logits, dim=0) on a tensor with one row per example

    Why it fails

    dim=0 scans down each column and returns, for every column, the row position of its largest value. That answers a different question from the one needed.

    Do this instead

    Use dim=1 so that argmax scans each row and returns one predicted label per example.

  • Common mistake

    Believing softmax is required before argmax

    What it looks like

    Computing softmax on the logits and then calling argmax, while assuming the raw logits cannot be used

    Why it fails

    The position of the largest value is the same in the logits and in the probabilities computed from them.

    Do this instead

    Apply argmax directly to the logits. Softmax is a valid path but is not needed to get labels.

  • Common mistake

    Reporting a count instead of a fraction

    What it looks like

    Printing 3 when the expected value is 3 out of 4

    Why it fails

    The count of correct predictions is not an accuracy. Accuracy is the count divided by the total number of examples.

    Do this instead

    Divide the correct count by the total count, and multiply by 100 only when a percentage is wanted.

  • Common mistake

    Comparing predicted labels against the wrong true-label tensor, which silently produces a plausible but meaningless count

Debugging an Unexpected Accuracy

When an accuracy number surprises you, the mistake almost always sits in one of three places: the dimension passed to argmax, the tensor passed into argmax, or the true labels it is compared against. Work through the pipeline in that order, and check each stage before trusting the final count.

  1. 1
    Print the predicted labels first and check that there is exactly one integer per example.
  2. 2
    Print the comparison result and confirm that its length matches the number of examples.
  3. 3
    Confirm that the true-label tensor lines up position by position with the predictions.
  4. 4
    Only then read the count, because a wrong count is usually a symptom of a wrong label tensor upstream.
  5. 5
    If the batches disagree, trace the counters batch by batch to find where the divergence begins.
EASY

A row of logits is [0.4, 2.8, 1.1]. Predict the label that argmax with dim=1 returns, then say whether softmax would change that answer. Explain your reasoning in terms of which position holds the largest value.

Hints
  • Find the largest of the three values and note its position.
  • Think about whether softmax moves the largest value to a different position.

Key Takeaways

  • torch.argmax with dim=1 returns the position of the largest value in each row, which turns a row of class scores into a predicted class label.
  • Argmax can be applied directly to logits, because softmax does not change which position holds the largest value.
  • compute_accuracy loops over the data loader, compares predicted and true labels with ==, counts matches with torch.sum, and keeps running totals, so it works on datasets too large to pass to the model at once.
  • Accuracy is the number of correct predictions divided by the total number of examples, so it always falls between 0 and 1.
  • When accuracy looks wrong, check the argmax dimension, the predicted-label tensor, and the true-label tensor, in that order.

Related concepts

More concepts starting with C