Understanding Logits and Class Scores
Argmax on raw logits is a direct route to class labels. Softmax can be added for interpretability when you want probabilities, but it does not change which position wins.
Why a Classifier Needs a Single Label
A classifier rarely answers with a class name. For each input it produces a row of numbers, one number for each possible class. Each number describes how strongly the model leans toward that class. A row might say that the first class is the most likely, but before anyone can count how many predictions were right, that row has to be turned into one decision. This article follows the step that makes that decision: picking the position of the largest value in each row.
What do you think happens?
Given a row of three scores such as [2.0, 0.5, -1.0], which position would a function that picks the largest value report?
Reveal answer
Position 0, because 2.0 is the largest value and it sits at index 0.
Argmax returns the position (index) of the largest value, not the value itself. Positions start counting at 0, so the first entry is position 0.
Reading One Row at a Time
The function torch.argmax with dim=1 returns the index of the highest value in each row. Each row of scores becomes a single integer, and that integer is the class label for that row. The dim argument decides the direction of the search. With dim=1 the function scans each row from left to right and reports where its largest value sits.
tensor([0, 1, 1])- logits has three rows (samples) and three columns (classes)
- dim=1 tells argmax to scan across each row
- The result has one integer per row, so it has three entries
Read the output row by row. Row 0 has its largest score, 2.0, at position 0, so its label is 0. Row 1 has its largest score, 3.0, at position 1, so its label is 1. Row 2 has its largest score, 1.5, at position 1, so its label is 1. The third row shows that two different samples can share the same label, which is normal for a classifier.
Finding the label for row 1
Row 1 of logits is [0.1, 3.0, 0.2]. What class label does argmax with dim=1 return for this row?
- 1List the scores
The row holds three scores: 0.1 at position 0, 3.0 at position 1, and 0.2 at position 2.
- 2Find the largest value
The largest value is 3.0.
- 3Report its position
3.0 sits at position 1, so argmax returns 1 for this row.
The class label for row 1 is 1.
Choosing the Axis with dim
Changing dim from 1 to 0 changes the question entirely. With dim=0 the function scans down each column instead of across each row, and it returns, for every column, the row position of its largest value. That second result answers a different question. It does not give one label per sample, so using the wrong dimension is one of the most common ways to get label predictions that look plausible but mean something else.
tensor([0, 1, 2])- The same logits tensor is used, but the scan now runs down columns
- The output has three entries, one per column, not one per sample
- These numbers are row positions inside each column, so they are not class labels for the samples
Skipping Softmax for Labels
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. It is not required, however, because the position of the largest value is the same whether you look at the logits or at the probabilities computed from them. Softmax changes the numbers, but it keeps their order within a row, so the winning position does not move.
tensor([0, 1, 1])
tensor([0, 1, 1])- probs contains values between 0 and 1 that sum to 1 within each row
- argmax on the probabilities and argmax on the logits give the same labels
- Softmax is therefore optional when the goal is only the predicted label
Argmax on raw logits is a direct route to class labels. Softmax can be added for interpretability when you want probabilities, but it does not change which position wins.
Matching Predictions to True Labels
Once you have predicted labels, the next question is whether they match the true labels. For a small set you could compare the two tensors by eye. The equality operator makes this exact. The == operator compares two tensors element by element and returns a tensor of booleans, one for each position. True means the prediction at that position matched the true label.
tensor([ True, True, False])
tensor(2)- predicted is
tensor([0, 1, 1])andtrue_labelsistensor([0, 1, 0]) - The third position is False because 1 does not equal 0
- torch.sum counts the True entries, giving 2
From Count to Accuracy
The count of correct predictions becomes accuracy by dividing it by the total number of examples and multiplying by 100 to express the result as a percentage. The rule is the same for any dataset.
Accuracy for the small batch
The comparison produced two True values out of three examples. What is the accuracy?
- 1Count correct predictions
torch.sum returned 2, so there are 2 correct predictions.
- 2Count total examples
There are 3 entries in the true labels, so there are 3 examples.
- 3Divide
$2 / 3$ is about 0.6667.
- 4Convert to a percentage
Multiply by 100 to get about 66.67 percent.
The accuracy is about 66.67 percent.
The source's own training set has five examples, and all five predictions are correct. Five correct out of five gives an accuracy of 100 percent. If a comparison had produced three matches out of four positions, the accuracy would be three quarters, or 75 percent.
Tracing a Surprising 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 chain in that order, because each step depends on the one before it.
Common mistake Using dim=0 when you want one label per sample
What it looks liketorch.argmax(logits, dim=0) returns tensor([0, 1, 2]) for the logits above, which has three entries but is not one label per row.
Why it failsdim=0 scans down columns, so it reports row positions inside each column.
Do this insteadUse dim=1 when each row is one sample and each column is one class.
Common mistake Reading the count before checking the predicted labels
Why it failsA wrong count is usually a symptom of a wrong label tensor upstream, so the count alone cannot show where the error started.
Do this insteadPrint the predicted labels first and confirm there is exactly one integer per example. Then print the comparison and confirm its length matches the number of examples.
Common mistake Thinking softmax is required before argmax
Why it failsSoftmax keeps the order of values within a row, so the position of the largest value does not change.
Do this insteadApply argmax directly to the logits when you only need class labels.
Practice on a New Batch
Given logits = torch.tensor([[0.2, 1.8, -0.5], [2.4, 0.1, 0.3], [-1.0, 0.7, 0.9]]) and true_labels = torch.tensor([1, 2, 1]), predict the predicted labels with argmax dim=1, then determine how many predictions match and what the accuracy is as a percentage.
Hints
- Find the largest value in each row and note its position. Row 0's largest is 1.8 at position 1.
- Compare the three predicted labels with the three true labels position by position, then count the True entries.
- Divide the count by 3 and multiply by 100.
Key Takeaways
- torch.argmax with dim=1 returns the index of the highest value in each row, turning a row of class scores into one class label.
- Argmax can be applied directly to logits; softmax is not needed to get labels because it preserves the order of values within a row.
- The == operator compares predicted and true labels element by element, and torch.sum counts the True entries.
- Accuracy equals the number of correct predictions divided by the total number of examples, expressed as a percentage.
- When accuracy looks wrong, check the dim argument, then the predicted labels, then the comparison, before trusting the count.