Pytorch中NLLLoss损失函数的C类是什么?

2024-09-26 18:01:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我问的是关于NLLLoss损失函数的C类

文件规定:

The negative log likelihood loss. It is useful to train a classification problem with C classes.

基本上,这一点之后的一切都取决于你是否知道什么是C类,我想我知道什么是C类,但是文档对我来说没有多大意义。特别是当它描述了(N, C) where C = number of classes的预期输入时。这就是我感到困惑的地方,因为我认为C类只引用输出。我的理解是C类是一个热门的分类向量。我经常在教程中发现NLLLoss经常与LogSoftmax配对以解决分类问题

我希望在以下示例中使用NLLLoss

# Some random training data
input = torch.randn(5, requires_grad=True)
print(input)  # tensor([-1.3533, -1.3074, -1.7906,  0.3113,  0.7982], requires_grad=True)
# Build my NN (here it's just a LogSoftmax)
m = nn.LogSoftmax(dim=0)
# Train my NN with the data
output = m(input)
print(output)  # tensor([-2.8079, -2.7619, -3.2451, -1.1432, -0.6564], grad_fn=<LogSoftmaxBackward>)
loss = nn.NLLLoss()
print(loss(output, torch.tensor([1, 0, 0])))

以上内容在最后一行引发了以下错误:

ValueError: Expected 2 or more dimensions (got 1)

我们可以忽略错误,因为很明显我不明白我在做什么。在这里,我将解释我对上述源代码的意图

input = torch.randn(5, requires_grad=True)

随机1D数组与一个热向量[1, 0, 0]配对进行训练。我试着对一个十进制数的热向量进行二进制位运算

m = nn.LogSoftmax(dim=0)

关于LogSoftmax的文档说,输出的形状将与输入的形状相同,但我只看到了LogSoftmax(dim=1)的示例,因此我一直在努力实现这一点,因为我找不到相关的示例

print(loss(output, torch.tensor([1, 0, 0])))

现在我有了NN的输出,我想知道分类[1, 0, 0]的损失。在这个例子中,数据是什么并不重要。我只想要一个表示分类的单热向量的损失

在这一点上,我陷入了试图解决与预期输出和输入结构相关的损失函数错误的困境。我尝试在输出和输入上使用view(...)来修复形状,但这只会导致其他错误

这又回到了我最初的问题,我将展示文档中的示例来解释我的困惑:

m = nn.LogSoftmax(dim=1)
loss = nn.NLLLoss()
input = torch.randn(3, 5, requires_grad=True)
train = torch.tensor([1, 0, 4])
print('input', input)  # input tensor([[...],[...],[...]], requires_grad=True)
output = m(input)
print('train', output, train)  # tensor([[...],[...],[...]],grad_fn=<LogSoftmaxBackward>) tensor([1, 0, 4])
x = loss(output, train)

同样,我们在{}上有{},这让我现在很困惑,因为看看{}数据。这是一个3x5张量,我迷路了

以下是关于NLLLoss函数的第一个输入的文档:

Input: (N, C)(N,C) where C = number of classes

输入按类数分组

那么,张量输入的每一行都与训练张量的每一个元素相关联

如果我改变输入张量的第二维度,那么没有任何东西会中断,我不明白发生了什么

input = torch.randn(3, 100, requires_grad=True)
# 3 x 100 still works?

所以我不明白这里的C类是什么,我认为C类是一种分类(就像一个标签),只对NN的输出有意义

我希望你们理解我的困惑,因为NN输入的形状不应该独立于用于分类的一个热向量的形状吗

代码示例和文档都说输入的形状是由分类的数量定义的,我真的不明白为什么

我曾试图研究文档和教程,以了解我遗漏了什么,但在几天未能克服这一点后,我决定问这个问题。这让我很谦卑,因为我认为这将是一件更容易学习的事情


Tags: 文档trueinputoutput分类traintorch形状
2条回答

我同意你所说的nn.NLLLoss()的文档远远不够理想,但我认为我们可以在这里澄清你的问题,首先,澄清“类”在机器学习环境中经常被用作“类别”的同义词

因此,当PyTorch谈论C类时,它实际上指的是你试图训练你的网络的不同类别的数量。 因此,在分类神经网络试图在“猫”和“狗”之间分类的经典示例中,C = 2,因为它是猫或狗

特别是对于这个分类问题,它还认为我们在类别数组上只有一个真值(图片不能同时描绘猫和狗,但总是只描绘其中一个),这就是为什么我们可以通过索引方便地指示图像的相应类别(比如说^{)表示猫和狗)。现在,我们可以简单地将网络输出与我们想要的类别进行比较

但是,为了实现这一点,我们还需要弄清楚这些损失值(在我们的网络输出中)指的是什么,因为我们的网络通常会通过softmax对不同的输出神经元进行预测,这意味着我们通常不止一个值。幸运的是,PyTorch的nn.NLLLoss会自动为您实现这一点

上面的LogSoftmax示例实际上只生成一个输出值,这是本示例的关键情况。这样,您基本上只知道某个东西是否存在,但在分类示例中使用它没有多大意义,在回归案例中更是如此(但这需要一个完全不同的损失函数开始)

最后,但并非最不重要的是,你也应该考虑这样的事实,我们通常有2D张量作为输入,因为批量(多个样本的同时计算)通常被认为是匹配性能的必要步骤。即使选择批量大小为1,这仍然要求输入的维度为(batch_size, input_dimensions),因此输出张量的形状为(batch_size, number_of_categories)

这解释了为什么您在网上找到的大多数示例都是在dim=1上执行LogSoftmax(),因为这是“分布轴”,而不是批处理轴(即dim=0

如果您只是想解决问题,最简单的方法是将随机张量扩展一个额外的维度(torch.randn([1, 5], requires_grad=True)),然后只比较输出张量中的一个值(print(loss(output, torch.tensor([1]))

基本上,您缺少了batch的概念

长话短说,丢失的每个输入(以及通过网络的输入)都需要batch维度(即使用了多少个样本)

逐步分解:

您的示例与文档

每一步都将是每一步的比较,以使其更清晰(顶部的文档,下面的示例)

投入

input = torch.randn(3, 5, requires_grad=True)
input = torch.randn(5, requires_grad=True)

在第一种情况下(文档),创建带有5特征的输入,并使用3样本。在您的情况下,只有batch维度(5样本),您没有所需的功能。如果您想要一个具有5功能的示例,您应该执行以下操作:

input = torch.randn(5, requires_grad=True)

LogSoftmax

LogSoftmax是跨功能维度完成的,您是跨批完成的

m=nn.LogSoftmax(尺寸=1)#适用于特征 m=nn.LogSoftmax(dim=0)#批量应用

由于样本彼此独立,因此此操作通常没有意义

目标

因为这是多类分类,向量中的每个元素代表一个样本,所以可以传递任意数量的数字(只要它小于特征的数量,在文档示例中它是5,因此[0-4]就可以了)

train = torch.tensor([1, 0, 4])
train = torch.tensor([1, 0, 0])

我想,你也希望传递一个热向量作为目标。PyTorch不是这样工作的,因为它的内存效率很低(既然您可以精确定位类,那么为什么要将所有内容存储为一个热编码,在您的情况下,它应该是^{

只有神经网络的输出是一个热编码,以便通过所有输出节点反向传播误差,目标不需要

决赛

您不应该使用torch.nn.LogSoftmax来执行此任务。只需使用torch.nn.Linear作为最后一层,并对目标使用torch.nn.CrossEntropyLoss

相关问题 更多 >

    热门问题