【问题标题】:Do I need to match the representation of my output layer and the target labels in PyTorch Nllloss?我是否需要匹配输出层的表示和 PyTorch Nllloss 中的目标标签?
【发布时间】:2019-09-17 16:52:44
【问题描述】:

我正在尝试使用 3 个可能的输出来解决分类问题:0, 1, or 2。 我的输出层最终为每个标签输出一个概率向量,比如[0.3,0.4,0.3]

我的损失函数是这样定义的:

loss = criterion(output_batch, label_batch) #criterion = nn.NLLLoss()

现在我的问题与存储数据方式不匹配的输出和标签有关。输出采用 size=3 概率向量的形式(使用 soft max 加到 1),我的目标标签是简单的标量。

我可以在计算损失函数时将我的标签转换为向量,但我不确定这是否有必要

0 ==> [1,0,0]
1 ==> [0,1,0]
2 ==> [0,0,1]

有人可以解释一下这个问题吗?谢谢!

【问题讨论】:

  • 如果您使用的是torch.nn.functional.nll_losstorch.nn.functional.cross_entropy,则无需将目标编码为one-hot。
  • 这太令人困惑了!那么torch如何评估它得到的向量呢?
  • 为什么要输入 one-hot 编码的目标?
  • 确实很不方便,因为有时候我们想用soft-target来计算loss。看来如果要输入一个软目标,我们需要自己实现逻辑。

标签: pytorch


【解决方案1】:

假设你的班级是:猫、狗和 capibara。

你有所谓的softmax 预测。

[0.3,0.4,0.3]

softmax 函数在顶部抽取一个结果。在这种情况下,如果 dog 低于 0.4,我们的输出就是预测狗。

注意预测的总和如何等于 1 = 0.3+0.4+0.3。

现在你需要计算 log softmax 的 log,然后 NLL 只是它的负数。

我可以在计算损失函数时将我的标签转换为向量,但我不确定这是否有必要?

0 ==> [1,0,0]
1 ==> [0,1,0]
2 ==> [0,0,1]

在您的情况下,这不是必需的。这意味着我们有三种不同的估计值 (bs=3),而您只显示了一种。


这是一个小练习:

batch_size, n_classes = 10, 5
x = torch.randn(batch_size, n_classes)
print("x:",x)

target = torch.randint(n_classes, size=(batch_size,), dtype=torch.long)
print("target:",target)


def log_softmax(x): 
    return x - x.exp().sum(-1).log().unsqueeze(-1)

def nll_loss(p, target):
    return -p[range(target.shape[0]), target].mean()

pred = log_softmax(x)
print ("pred:", pred)
ohe = torch.zeros(batch_size, n_classes)
ohe[range(ohe.shape[0]), target]=1
print("ohe:",ohe)

pe = pred[range(target.shape[0]), target]
print("pe:",pe)

mean = pred[range(target.shape[0]), target].mean()
print("mean:",mean)

negmean = -mean
print("negmean:", negmean)

loss = nll_loss(pred, target)
print("loss:",loss)

输出:

x: tensor([[ 1.5837, -1.3132,  1.5513,  1.4422,  0.8072],
        [ 1.1740,  1.9250,  0.4258, -1.0320, -0.4650],
        [-1.2447, -0.5360, -1.4950,  1.2020,  1.2724],
        [ 0.2300,  0.2587, -0.4463, -0.1397, -0.3617],
        [-0.7983,  0.7742,  0.0035,  0.9963, -0.7926],
        [ 0.7575, -0.8008,  0.7995,  0.0448,  0.6621],
        [-1.7153,  0.7672, -0.6841, -0.4826, -0.8614],
        [ 0.0263,  0.7244,  0.8751, -1.0226, -1.3762],
        [ 0.0192, -0.4368, -0.4010, -1.0660,  0.0364],
        [-0.5120, -1.4871,  0.6758,  1.2975,  0.2879]])
target: tensor([0, 4, 3, 0, 0, 4, 1, 2, 4, 2])
pred: tensor([[-1.2094, -4.1063, -1.2418, -1.3509, -1.9859],
        [-1.3601, -0.6091, -2.1083, -3.5661, -2.9991],
        [-3.3233, -2.6146, -3.5736, -0.8766, -0.8063],
        [-1.3302, -1.3015, -2.0065, -1.7000, -1.9220],
        [-2.7128, -1.1403, -1.9109, -0.9181, -2.7070],
        [-1.2955, -2.8538, -1.2535, -2.0081, -1.3909],
        [-3.0705, -0.5881, -2.0394, -1.8379, -2.2167],
        [-1.7823, -1.0841, -0.9334, -2.8311, -3.1847],
        [-1.2936, -1.7496, -1.7138, -2.3788, -1.2764],
        [-2.5641, -3.5393, -1.3764, -0.7546, -1.7643]])
ohe: tensor([[1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 1.],
        [0., 0., 0., 1., 0.],
        [1., 0., 0., 0., 0.],
        [1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 1.],
        [0., 1., 0., 0., 0.],
        [0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 1.],
        [0., 0., 1., 0., 0.]])
pe: tensor([-1.2094, -2.9991, -0.8766, -1.3302, -2.7128, -1.3909, -0.5881, -0.9334,
        -1.2764, -1.3764])
mean: tensor(-1.4693)
negmean: tensor(1.4693)
loss: tensor(1.4693)

【讨论】:

  • 这个答案很明确!!我的困惑是关于 Nllloss 函数“幕后”发生的事情,这一行完全揭开了它的神秘面纱:return -p[range(target.shape[0]), target].mean() #i.e.第(目标)列的所有行(批次中的每个数据点)的平均值。非常感谢!!
猜你喜欢
  • 2020-05-24
  • 1970-01-01
  • 2012-02-02
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2013-12-27
  • 2010-11-03
相关资源
最近更新 更多