【问题标题】:Pytorch inputs for nn.CrossEntropyLoss()nn.CrossEntropyLoss() 的 Pytorch 输入
【发布时间】:2019-05-24 22:58:21
【问题描述】:

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

我有一个数据点是一对:dat = (-3.5, 0),第一个元素是数据点,第二个是对应的标签。
然后我将输入的第一个元素转换为张量:tensor_input = torch.Tensor([dat[0]]).
然后我将模型应用到 tensor_input:outputs = model(tensor_input).
然后我将标签转换为张量:tensor_label = torch.Tensor([dat[1]]).
现在,当我尝试这样做时,事情就中断了:loss = criterion(outputs, tensor_label)。它给出了错误:RuntimeError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

import torch
import torch.nn as nn

class LogisticRegression(nn.Module):
    def __init__(self, input_size, num_classes):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(input_size, num_classes) 

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

model = LogisticRegression(1,2)
criterion = nn.CrossEntropyLoss()
dat = (-3.5,0)
tensor_input = torch.Tensor([dat[0]])
outputs = binary_model(tensor_input)
tensor_label = torch.Tensor([dat[1]])
loss = criterion(outputs, tensor_label)

我一辈子都想不通。

【问题讨论】:

  • 附带说明:您在示例代码中只定义了model,但您稍后使用binary_model 进行前向传递。可能只是一个错字,但我不知道你的代码。

标签: pytorch logistic-regression


【解决方案1】:

在大多数情况下,PyTorch 文档在解释不同功能方面做得非常出色;它们通常确实包含预期的输入尺寸,以及一些简单的示例。
你可以找到nn.CrossEntropyLoss()here的描述。

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

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

补充一点,N 一般指的是批量大小(样本数)。将此与您目前拥有的进行比较:

outputs.shape
>>> torch.Size([2])

即目前我们只有(2,) 的输入维度,而不是(1,2),正如 PyTorch 所期望的那样。我们可以通过简单地使用.unsqueeze() 给当前张量添加一个“假”维度来缓解这种情况,如下所示:

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,仅供参考。

【讨论】:

    【解决方案2】:

    要在 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(),因此它有点偏离,即使它正确地解决了LogisticRegression 的问题,正如您所提到的。此外,尽管如此,`nn.Sigmoid() 将应用 element-wise,即输出与输入的形状相同;您必须确保自己只有一个元素。
    猜你喜欢
    • 2018-04-14
    • 2021-11-13
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 2021-07-04
    相关资源
    最近更新 更多