Pytorch不支持一键热矢量?

Rav*_*euk 4 python machine-learning pytorch

我对Pytorch如何处理一键向量感到非常困惑。在本教程中,神经网络将生成一个热向量作为其输出。据我了解,本教程中神经网络的示意图结构应类似于:

在此处输入图片说明

但是,labels它们不是一站式矢量格式。我得到以下size

print(labels.size())
print(outputs.size())

output>>> torch.Size([4]) 
output>>> torch.Size([4, 10])
Run Code Online (Sandbox Code Playgroud)

神奇的是,我将outputs和传递labelscriterion=CrossEntropyLoss(),完全没有错误。

loss = criterion(outputs, labels) # How come it has no error?
Run Code Online (Sandbox Code Playgroud)

我的假设:

也许pytorch会自动将其转换labels为一键式矢量形式。因此,在将标签传递给损失函数之前,我尝试将标签转换为单热矢量。

def to_one_hot_vector(num_class, label):
    b = np.zeros((label.shape[0], num_class))
    b[np.arange(label.shape[0]), label] = 1

    return b

labels_one_hot = to_one_hot_vector(10,labels)
labels_one_hot = torch.Tensor(labels_one_hot)
labels_one_hot = labels_one_hot.type(torch.LongTensor)

loss = criterion(outputs, labels_one_hot) # Now it gives me error
Run Code Online (Sandbox Code Playgroud)

但是,出现以下错误

RuntimeError:/opt/pytorch/pytorch/aten/src/THCUNN/generic/ClassNLLCriterion.cu:15不支持多目标

因此,Pytorch?中不支持一键向量。如何Pytorch计算cross entropy两个张量outputs = [1,0,0],[0,0,1]labels = [0,2]?此刻对我来说根本没有意义。

pro*_*sti 11

此代码将帮助您进行单热编码多热编码

import torch
batch_size=10
n_classes=5
target = torch.randint(high=5, size=(1,10)) # set size (2,10) for MHE
print(target)
y = torch.zeros(batch_size, n_classes)
y[range(y.shape[0]), target]=1
y
Run Code Online (Sandbox Code Playgroud)

OHE 中的输出

tensor([[4, 3, 2, 2, 4, 1, 1, 1, 4, 2]])

tensor([[0., 0., 0., 0., 1.],
        [0., 0., 0., 1., 0.],
        [0., 0., 1., 0., 0.],
        [0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 1.],
        [0., 1., 0., 0., 0.],
        [0., 1., 0., 0., 0.],
        [0., 1., 0., 0., 0.],
        [0., 0., 0., 0., 1.],
        [0., 0., 1., 0., 0.]])
Run Code Online (Sandbox Code Playgroud)

我设置时 MHE 的输出 target = torch.randint(high=5, size=(2,10))

tensor([[3, 2, 4, 4, 2, 4, 0, 4, 4, 1],
        [4, 1, 1, 3, 2, 2, 4, 2, 4, 3]])

tensor([[0., 0., 0., 1., 1.],
        [0., 1., 1., 0., 0.],
        [0., 1., 0., 0., 1.],
        [0., 0., 0., 1., 1.],
        [0., 0., 1., 0., 0.],
        [0., 0., 1., 0., 1.],
        [1., 0., 0., 0., 1.],
        [0., 0., 1., 0., 1.],
        [0., 0., 0., 0., 1.],
        [0., 1., 0., 1., 0.]])
Run Code Online (Sandbox Code Playgroud)

如果您需要多个 OHE:

torch.nn.functional.one_hot(target)

tensor([[[0, 0, 0, 1, 0],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 1],
         [0, 0, 0, 0, 1],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 1],
         [1, 0, 0, 0, 0],
         [0, 0, 0, 0, 1],
         [0, 0, 0, 0, 1],
         [0, 1, 0, 0, 0]],

        [[0, 0, 0, 0, 1],
         [0, 1, 0, 0, 0],
         [0, 1, 0, 0, 0],
         [0, 0, 0, 1, 0],
         [0, 0, 1, 0, 0],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 1],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 1],
         [0, 0, 0, 1, 0]]])
Run Code Online (Sandbox Code Playgroud)


Jat*_*aki 6

我对你的困惑感到困惑。PyTorch在其文档中明确指出了CrossEntropyLoss这一点

此标准期望将类别索引(0到C-1)作为大小为minibatch的一维张量的每个值的目标

换句话说,它在to_one_hot_vector概念上内置了您的功能,CEL并且不公开一站式API。请注意,与存储类标签相比,单热向量的内存效率低下。

如果为您提供了一个热门矢量,并且需要使用类标签格式(例如与兼容CEL),则可以使用argmax如下所示:

import torch

labels = torch.tensor([1, 2, 3, 5])
one_hot = torch.zeros(4, 6)
one_hot[torch.arange(4), labels] = 1

reverted = torch.argmax(one_hot, dim=1)
assert (labels == reverted).all().item()
Run Code Online (Sandbox Code Playgroud)