Skip to content

← Indexing and Selection step 9 of 9

Medium Primitives

Labels to one-hot

Jump to the task

A one-hot encoding gives each label its own row, with one at the label's column and zero everywhere else. For labels [2, 0, 1] and four classes:

[[0, 0, 1, 0],
 [1, 0, 0, 0],
 [0, 1, 0, 0]]

Create a zero matrix, then scatter a one into each selected column:

import torch

labels = torch.tensor([2, 0, 1], dtype=torch.long)
out = torch.zeros(3, 4)
out.scatter_(1, labels.unsqueeze(1), 1.0)
print(out.tolist())
# [[0.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0]]

Read the index shape

The destination has shape (rows, classes). Scattering along dimension 1 selects a column while retaining the row position. labels.unsqueeze(1) has shape (rows, 1), so it specifies one destination per row. The scalar source 1.0 supplies the value for every selected destination.

Repeated labels do not collide here: two rows with label 1 write to out[0, 1] and out[1, 1], which are different elements. Collision behavior depends on the full destination coordinates, not merely repeated numbers in the index tensor. Ordinary scatter_ is sufficient for this construction.

In application code

torch.nn.functional.one_hot(labels, num_classes=n_classes) provides a direct encoding operation and returns an int64 tensor. Convert its dtype if you need floating-point indicators. This exercise uses scatter to make the relationship between row positions, column indices and written values explicit. More elaborate targets, such as multiple labels per row, require you to decide how repeated destinations should behave.

Your task

def one_hot(labels: torch.Tensor, n_classes: int) -> torch.Tensor

labels is a one-dimensional CPU int64 tensor. n_classes is positive, and each label is in 0 .. n_classes-1. Return a floating-point tensor of shape (len(labels), n_classes) with one at each row's label and zero elsewhere.

Do not call torch.nn.functional.one_hot. Use at most three operations counted by the harness's TorchDispatchMode. That count includes creating the output, reshaping the indices and scattering; it does not measure runtime.