nn.CrossEntropyLoss()的Pytorch输入

nn.CrossEntropyLoss()的Pytorch输入,pytorch,logistic-regression,Pytorch,Logistic Regression,我试图在PyTorch中对一个简单的0,1标记数据集执行逻辑回归。标准或损失定义为:criteria=nn.CrossEntropyLoss()。模型为:model=logistic回归(1,2) 我有一个成对的数据点:dat=(-3.5,0),第一个元素是数据点,第二个是相应的标签。 然后我将输入的第一个元素转换成张量:tensor\u input=torch.tensor([dat[0]]) 然后我将模型应用于张量输入:outputs=model(张量输入) 然后我将标签转换为张量:tens

我试图在PyTorch中对一个简单的0,1标记数据集执行逻辑回归。标准或损失定义为:
criteria=nn.CrossEntropyLoss()
。模型为:
model=logistic回归(1,2)

我有一个成对的数据点:
dat=(-3.5,0)
,第一个元素是数据点,第二个是相应的标签。
然后我将输入的第一个元素转换成张量:
tensor\u input=torch.tensor([dat[0]])

然后我将模型应用于张量输入:
outputs=model(张量输入)

然后我将标签转换为张量:
tensor\u label=torch.tensor([dat[1]])

现在,当我尝试这样做时,事情发生了变化:
loss=criteria(输出,张量标签)
。它给出和错误:
RuntimeError:Dimension超出范围(预期在[-1,0]范围内,但得到1)


我一辈子都搞不懂它。

在大多数情况下,PyTorch文档在解释不同功能方面做得非常出色;它们通常包括预期的输入维度,以及一些简单的示例。
您可以找到
nn.CrossEntropyLoss()
的说明

要浏览您的特定示例,让我们从查看预期的输入维度开始:

输入:(N,C),其中C=类数。[……]

此外,N通常指批量大小(样本数量)。要将其与您当前拥有的进行比较,请执行以下操作:

outputs.shape
>>> torch.Size([2])
也就是说,目前我们的输入维度只有
(2,)
,而不是PyTorch预期的
(1,2)
。我们可以通过在当前张量中添加一个“假”维度来缓解这种情况,只需使用
.unsqueze()
如下:

outputs = binary_model(tensor_input).unsqueeze(dim=0)
outputs.shape
>>> torch.Size([1,2])
现在我们了解了这一点,让我们看看目标的预期投入:

目标:(N)[……]

所以我们已经找到了合适的形状。但是,如果我们尝试这样做,我们仍然会遇到一个错误:

RuntimeError: Expected object of scalar type Long but got scalar type Float 
              for argument #2 'target'.
同样,错误消息非常有表现力。这里的问题是PyTorch张量(默认情况下)被解释为
torch.FloatTensors
,但输入应该是整数(或
Long
)。我们只需在张量创建期间指定确切的类型即可:

tensor_label = torch.LongTensor([dat[1]])

我正在Linux下使用PyTorch 1.0供参考。

要在PyTorch中执行逻辑回归,您需要3件事:

  • 编码为0或1的标签(目标)
  • 最后一层上的Sigmoid激活,因此输出数为1
  • 二元交叉熵作为损失函数
以下是最简单的例子:

import torch
import torch.nn as nn


class LogisticRegression(nn.Module):
    def __init__(self, n_inputs, n_outputs):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_inputs, n_outputs)
        self.sigmoid = nn.Sigmoid()


    def forward(self, x):
        x = self.linear(x)
        return self.sigmoid(x)


# Init your model
# Attention!!! your num_output will be 1, because logistic function returns one value in range (0, 1) 
model = LogisticRegression(n_inputs=1, n_outputs=1)
# Define Binary Cross Entropy Loss:
criterion = nn.BCELoss()

# dummy data
data = (42.0, 0)
tensor_input = torch.Tensor([data[0]])
tensor_label = torch.Tensor([data[1]])

outputs = model(tensor_input)

loss = criterion(outputs, tensor_label)

print(loss.item())

请注意:您在示例代码中只定义了
模型
,但稍后将使用
二进制模型
进行正向传递。可能只是打字错误,但我不知道你的代码。我部分不同意这个答案。因为这个问题是关于
nn.CrossEntropyLoss()
,而不是
nn.BCELoss()
,所以它稍微有点偏离,即使它正确地解决了逻辑回归的问题,正如您所提到的。此外,尽管,`nn.Sigmoid()将按元素应用,即输出与输入的形状相同;你必须确保只有一个因素会影响到你自己。
import torch
import torch.nn as nn


class LogisticRegression(nn.Module):
    def __init__(self, n_inputs, n_outputs):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_inputs, n_outputs)
        self.sigmoid = nn.Sigmoid()


    def forward(self, x):
        x = self.linear(x)
        return self.sigmoid(x)


# Init your model
# Attention!!! your num_output will be 1, because logistic function returns one value in range (0, 1) 
model = LogisticRegression(n_inputs=1, n_outputs=1)
# Define Binary Cross Entropy Loss:
criterion = nn.BCELoss()

# dummy data
data = (42.0, 0)
tensor_input = torch.Tensor([data[0]])
tensor_label = torch.Tensor([data[1]])

outputs = model(tensor_input)

loss = criterion(outputs, tensor_label)

print(loss.item())