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

我在询问关于NLLLoss损失函数的C类。

文档中说明:

负对数似然损失。它对于训练具有C个类别的分类问题很有用。

基本上,之后的所有内容都取决于你是否知道什么是C类,我以为我知道什么是C类,但文档对我来说不太清楚。特别是当它描述期望的输入为(N, C) 其中C = 类别数时。我感到困惑,因为我以为C类仅指输出。我的理解是C类是一个分类的一热向量。我经常在教程中发现NLLLoss通常与LogSoftmax配对来解决分类问题。

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

# 一些随机训练数据input = torch.randn(5, requires_grad=True)print(input)  # tensor([-1.3533, -1.3074, -1.7906,  0.3113,  0.7982], requires_grad=True)# 构建我的神经网络(这里只是一个LogSoftmax)m = nn.LogSoftmax(dim=0)# 使用数据训练我的神经网络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: 期望2个或更多维度(得到1)

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

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

随机一维数组与一热向量[1, 0, 0]配对用于训练。我试图将二进制位转换为一热向量的十进制数。

m = nn.LogSoftmax(dim=0)

LogSoftmax的文档说明输出将与输入的形状相同,但我只看到LogSoftmax(dim=1)的示例,因此我一直试图让它工作,因为我找不到相关的示例。

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

所以现在我有神经网络的输出,我想知道我的分类[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)

同样,我们在LogSoftmax上使用dim=1,这让我现在感到困惑,因为看看input数据。它是一个3x5的张量,我迷失了。

这是NLLLoss函数的第一个输入的文档:

输入:(N, C)(N,C) 其中C = 类别数

输入是按类别数分组的吗?

所以张量输入的每一都与训练张量的每一元素相关联吗?

如果我更改输入张量的第二维度,那么什么都不会坏,我不知道发生了什么。

input = torch.randn(3, 100, requires_grad=True)# 3 x 100 仍然有效?

所以我不知道这里的C类是什么,我以为C类是分类(如标签)且仅在神经网络的输出上有意义。

我希望你能理解我的困惑,因为神经网络输入的形状不应该是独立于用于分类的热向量的形状吗?

代码示例和文档都说输入的形状由分类数定义,我不太明白为什么会这样。

我尝试研究文档和教程来理解我错过了什么,但在几天无法突破这个点后,我决定提出这个问题。这让我感到谦卑,因为我以为这是最容易学的东西之一。


回答:

基本上你缺少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(1, 5, requires_grad=True)

LogSoftmax

LogSoftmax是在特征维度上进行的,你是在批次上进行的。

m = nn.LogSoftmax(dim=1) # 在特征上应用m = nn.LogSoftmax(dim=0) # 在批次上应用

这种操作通常对样本没有意义,因为样本是相互独立的。

目标

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

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

我假设你也想传递一热向量作为目标。PyTorch不是这样工作的,因为它内存效率低(为什么要将一切存储为一热编码,当你可以只精确定位类别时,在你的情况下它将是0)。

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

最终

你不应该在这个任务中使用torch.nn.LogSoftmax完全。只需使用torch.nn.Linear作为最后一层,并使用torch.nn.CrossEntropyLoss与你的目标。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注