【问题标题】:How to predict a label in MultiClass classification model in pytorch?如何在pytorch的MultiClass分类模型中预测标签?
【发布时间】:2019-05-16 06:17:11
【问题描述】:

我目前正在做我的迷你项目,根据海报预测电影类型。所以在我拥有的数据集中,每部电影可以有 1 到 3 种类型,因此每个实例可以属于多个类。我总共有 15 个课程(15 个流派)。所以现在我面临的问题是如何使用 pytorch 对这个特定问题进行预测。

在 pytorch CIFAR-tutorial 中,每个实例只能有一个类(例如,如果图像是汽车,它应该属于汽车类),总共有 10 个类。所以在这种情况下,模型预测的定义方式如下(从pytorch网站复制代码sn-p):

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(2):  # loop over the dataset multiple times

running_loss = 0.0
for i, data in enumerate(trainloader, 0):
    # get the inputs
    inputs, labels = data

    # zero the parameter gradients
    optimizer.zero_grad()

    # forward + backward + optimize
    outputs = net(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    # print statistics
    running_loss += loss.item()
    if i % 2000 == 1999:    # print every 2000 mini-batches
        print('[%d, %5d] loss: %.3f' %
              (epoch + 1, i + 1, running_loss / 2000))
        running_loss = 0.0

print('完成训练')

问题1(训练部分)。您可以建议将什么用作激活函数。我在考虑 BCEWithLogitsLoss() 但我不确定它会有多好。

然后测试集的预测精度定义如下: 整个网络:

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

对于每个班级:

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

其中输出如下:

Accuracy of plane : 36 % 
Accuracy of   car : 40 % 
Accuracy of  bird : 30 % 
Accuracy of   cat : 19 % 
Accuracy of  deer : 28 % 
Accuracy of   dog : 17 % 
Accuracy of  frog : 34 % 
Accuracy of horse : 43 % 
Accuracy of  ship : 57 % 
Accuracy of truck : 35 % 

现在是问题 2: 如何确定准确性,使其看起来如下:

例如:

The Matrix (1999)                ['Action: 91%', 'Drama: 25%', 'Adventure: 13%']
The Others (2001)                ['Drama: 76%', 'Horror: 65%', 'Action: 41%']
Alien: Resurrection (1997)       ['Horror: 67%', 'Action: 64%', 'Drama: 43%']
The Martian (2015)               ['Drama: 95%', 'Adventure: 81%']

考虑到每部电影并不总是有 3 种类型,有时是 2,有时是 1。所以在我看来,我应该在输出列表中找到 3 个最大值、2 个最大值或 1 个最大值,即 list 15 种类型,例如,如果

我预测的类型是[电影,冒险]然后

some_kind_of_function(outputs) 应该给我输出

[1 0 0 0 0 0 0 0 0 0 0 1 0 0 0],

之后我可以将其与 ground_truth 进行比较。 我不认为 torchmax 在这种情况下会起作用,因为它只给出 [weigts array] 中的一个最大值,所以

实现它的最佳方式是什么?

提前谢谢你,感谢任何帮助或建议:)

【问题讨论】:

  • 我不确定你的迷你项目的损失函数,但我建议你多了解一下 CIFAR-10。这样想,CIFAR-10 CNN 正在计算输入图像成为 10 个类别之一的概率。最后,您只需打印 10 中的最大数字,并希望这是真的。因此,在您的情况下,您将有 15 个类(对应于 15 个流派)。成功训练后,您的模型将为每个输入海报生成一个包含 15 个概率的数组。您可以选择前 3 个以显示最佳 3 类型或 5 个用于前 5。其他方法是设置截止概率,例如 0.6 并显示所有类别 > 0.6。
  • 嗨@MohanaRao,谢谢你的解释,我知道概率是如何计算的,但是由于我的标签并不总是有一个值,它是一个最多可以有3个元素的张量,我无法正确训练我的数据,因为我的损失没有正确计算,并且我收到类似 ValueError: Target size (torch.Size([4, 3])) must be the same as input size (torch.Size([4 , 15]))

标签: conv-neural-network pytorch multilabel-classification multiclass-classification


【解决方案1】:
  1. 您是对的,您正在寻找对每个海报类型对执行二元分类(海报 X 是否是戏剧电影?是不是动作片?)。 BinaryCrossEntropy(WithLogits) 是要走的路。
  2. 关于评估结果算法的最佳指标,这取决于您,在寻找什么。但是您可能想调查precision and recallf1 score 之类的想法。 就个人而言,我可能会为每种类型选择前 3 名(因为这是分配给每个海报的最大类型数量),并查看预期出现的概率是否很高,以及是否出乎意料(对于具有 2 个“基本事实”类型的电影)显示在最后的位置,分配的概率显着降低。

【讨论】:

  • 嗨@Jatentaki,感谢您的回答。我尝试了 nn.BCEWithLogitsLoss(),但是在这种情况下我有以下错误 ValueError: Target size (torch.Size([4, 3])) must be the same as input size (torch.Size([4, 15] )),因为我有 15 个类作为全连接层的最终输出,但每个标签包含 3 个元素,而我的小批量是 4。那么我该如何进行呢?从每个标签中删除最后两个元素然后进行损失是个好主意吗?会准确吗?或者当我做 loss = criteria(outputs, labels) 时,遍历 label 的每个元素是否更好?
  • 我不确定我是否跟随。如果您有 15 个标签,您的网络还需要输出 15 个 logits - 每个类别一个。如果您想告诉您的网络“看,最多可以有 3 个标签,所以请利用该信息,甚至不要费心输出超过 3 个非零值”,这很难做到。最后,与概率方法相反 - 你知道它最多可以是三个,但仅考虑海报,可能有三个以上是合理的。
  • 我说的是训练网络,我应该让 #of 输入实例等于 #of 我的标签。我的输入是一个包含 30000 个图像的数组,我的标签是 30000 个列表,其中每个列表是 1,2 或 3 个标签。由于我无法从列表中制作适当的批次和张量,我认为,我必须展平列表列表,但我有大约 80000 个标签。所以,我的问题是,我可以将它削减到 30000 以便它与我的输入张量的大小相匹配。这是个好主意吗?还是有更好的解决方案?
  • 我觉得在这种情况下,我什至不需要我的标签,我可以在 [0:15] 范围内均匀分布 30000 个数字
  • 为什么不能从列表中创建张量?您需要为每个唯一标签分配一个数字,例如 0 - 戏剧、1 - 冒险等,并将列表转换为 one-hot 编码向量,正如您在原始帖子中所描述的那样。然后,您的每张海报都与正好 15 个数字的向量相关联,您可以轻松构建形状为 [n_posters, 15] 的张量。对不起,我不明白你的意思是统一分配 30000 个数字
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2019-05-29
  • 2020-07-17
  • 2020-03-08
  • 2019-04-03
  • 2019-03-22
  • 2021-07-01
相关资源
最近更新 更多