22

I have my label tensor of shape (1,1,128,128,128) in which the values might range from 0,24. I want to convert this to one hot encoded tensor, using the nn.fucntional.one_hot function

n = 24
one_hot = torch.nn.functional.one_hot(indices, n)

but this expects a tensor of indices, honestly, I am not sure how to get those. The only tensor I have is the label tensor of the shape described above and it contains values ranging from 1-24, not the indices

How can I get a tensor of indices from my tensor? Thanks in advance.

Umang Gupta
  • 15,022
  • 6
  • 48
  • 66
Ryan
  • 8,459
  • 14
  • 40
  • 66

3 Answers3

50

If the error you are getting is this one:

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
RuntimeError: one_hot is only applicable to index tensor.

Maybe you just need to convert to int64:

import torch

# random Tensor with the shape you said
indices = torch.Tensor(1, 1, 128, 128, 128).random_(1, 24)
# indices.shape => torch.Size([1, 1, 128, 128, 128])
# indices.dtype => torch.float32

n = 24
one_hot = torch.nn.functional.one_hot(indices.to(torch.int64), n)
# one_hot.shape => torch.Size([1, 1, 128, 128, 128, 24])
# one_hot.dtype => torch.int64

You can use indices.long() too.

Berriel
  • 12,659
  • 4
  • 43
  • 67
  • 3
    Note that the precision of the integer that you need to cast to, is indeed important. If you cast to int8 or int16 or int32 etc. (maybe thinking that 64 bits is too much for a class index) you'll still be getting the error. – Giorgos Sfikas Dec 09 '21 at 13:14
1

The torch.as_tensor function can also be helpful if your labels are stored in a list or numpy array:

import torch
import random

n_classes = 5
n_samples = 10

# Create list n_samples random labels (can also be numpy array)
labels = [random.randrange(n_classes) for _ in range(n_samples)]
# Convert to torch Tensor
labels_tensor = torch.as_tensor(labels)
# Create one-hot encodings of labels
one_hot = torch.nn.functional.one_hot(labels_tensor, num_classes=n_classes)
print(one_hot)

The output one_hot has shape (n_samples, n_classes) and should look something like:

tensor([[0, 0, 0, 1, 0],
        [0, 1, 0, 0, 0],
        [0, 1, 0, 0, 0],
        [0, 0, 0, 1, 0],
        [0, 0, 0, 1, 0],
        [0, 0, 0, 1, 0],
        [1, 0, 0, 0, 0],
        [1, 0, 0, 0, 0],
        [0, 0, 0, 1, 0],
        [1, 0, 0, 0, 0]])
adamconkey
  • 4,104
  • 5
  • 32
  • 61
0

Usually, this issue can be solved by adding long(). for example,

import torch
import torch.nn.functional as F
labels=torch.Tensor([[0, 2, 1]])
n_classes=3
encoded=F.one_hot(labels, n_classes)

It gives an error as: RuntimeError: one_hot is only applicable to index tensor. To solve this issue, use long().

import torch
import torch.nn.functional as F
labels=torch.Tensor([[0, 2, 1]]).long()
n_classes=3
encoded=F.one_hot(labels, n_classes)

Now it would be executed without errors.