pytorch 错误:CrossEntropyLoss() 不支持多目标 [英] pytorch error: multi-target not supported in CrossEntropyLoss()

查看:23
本文介绍了pytorch 错误:CrossEntropyLoss() 不支持多目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在进行一个使用加速度数据来预测一些活动的项目.但是我在损失计算上有问题.我正在为它使用 CrossEntropyLoss.

I am on a project using acceleration data to predict some activities. But I have problems on the loss calculation. I am using CrossEntropyLoss for it.

数据用于它,如下所示我使用每行的前 4 个数据来预测索引,就像每行的最后一个一样.

Data is used for it like below I use the first 4 data of each rows to predict the index like the last one of each rows.

1 84 84 81 4
81 85 85 80 1
81 82 84 80 1
1 85 84 2 0
81 85 82 80 1
81 82 84 80 1
81 25 84 80 5

错误信息如下.

minoh@minoh-VirtualBox:~/cow$ python lec5.py
Traceback (most recent call last):
  File "lec5.py", line 97, in <module>
    train(epoch)
  File "lec5.py", line 74, in train
    loss = criterion(y_pred, labels)
  File "/home/minoh/anaconda3/lib/python3.6/site-packages/torch/nn/modules/module.py", line 357, in __call__
    result = self.forward(*input, **kwargs)
  File "/home/minoh/anaconda3/lib/python3.6/site-packages/torch/nn/modules/loss.py", line 679, in forward
    self.ignore_index, self.reduce)
  File "/home/minoh/anaconda3/lib/python3.6/site-packages/torch/nn/functional.py", line 1161, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, size_average, ignore_index, reduce)
  File "/home/minoh/anaconda3/lib/python3.6/site-packages/torch/nn/functional.py", line 1052, in nll_loss
    return torch._C._nn.nll_loss(input, target, weight, size_average, ignore_index, reduce)
RuntimeError: multi-target not supported at /opt/conda/conda-bld/pytorch_1518243271935/work/torch/lib/THNN/generic/ClassNLLCriterion.c:22

我的代码基于 Sung Kim 的 pytorch

import numpy as np
import torch    
from torch.autograd import Variable    
import torch.nn.functional as F    
from torch.utils.data import Dataset, DataLoader    
import torch.nn as nn    
import torch.optim as optim    
from torchvision import datasets, transforms    

class CowDataset(Dataset):    
    def __init__(self):    
        xy_str = np.loadtxt('cow_test', delimiter = ' ', dtype = np.str)    
        xy = xy_str.astype(np.float32)    
        xy_int = xy_str.astype(np.int)    
        self.len = xy.shape[0]    
        self.x_data = torch.from_numpy(xy[:, 0:4])    
        self.y_data = torch.from_numpy(xy_int[:, [4]])    

    def __getitem__(self, index):    
        return self.x_data[index], self.y_data[index]    

    def __len__(self):    
        return self.len    

dataset = CowDataset()    
train_loader = DataLoader(dataset = dataset, batch_size = 32, shuffle = True)    

class CowTestset(Dataset):    
        def __init__(self):    
                xy_str = np.loadtxt('cow_test2', delimiter = ' ', dtype =np.str)    
                xy = xy_str.astype(np.float32)    
                xy_int = xy_str.astype(np.int)    
                self.len = xy.shape[0]    
                self.x_data = torch.from_numpy(xy[:, 0:4])    
                self.y_data = torch.from_numpy(xy_int[:, [4]])    

        def __getitem__(self, index):    
                return self.x_data[index], self.y_data[index]    

        def __len__(self):    
                return self.len    

testset = CowTestset()    
test_loader = DataLoader(dataset = testset, batch_size = 32, shuffle = True)    

class Model(torch.nn.Module):    
    def __init__(self):    
        super(Model, self).__init__()    
        self.l1 = torch.nn.Linear(4,5)    
        self.l2 = torch.nn.Linear(5,7)    
        self.l3 = torch.nn.Linear(7,6)    
        self.sigmoid = torch.nn.Sigmoid()    

    def forward(self, x):    
        out1 = self.sigmoid(self.l1(x))    
        out2 = self.sigmoid(self.l2(out1))    
        y_pred = self.sigmoid(self.l3(out2))    
        return y_pred    

model = Model()    
criterion = nn.CrossEntropyLoss()    
optimizer = optim.SGD(model.parameters(), lr = 0.1, momentum = 0.5)    

def train(epoch):    
    model.train()    
    for batch_idx, (inputs, labels) in enumerate(train_loader):    
        inputs, labels = Variable(inputs), Variable(labels)    
        optimizer.zero_grad()    
        y_pred = model(inputs)    
        loss = criterion(y_pred, labels)    
        loss.backward()    
        optimizer.step()    
        if batch_idx % 10 == 0:    
            print('Train Epoch: {} [{}/{} ({:.0f}%)]	Loss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.data[0]))    

def test():    
    model.eval()    
    test_loss = 0    
    correct = 0    
    for data, target in test_loader:    
        data, target = Variable(data, volatile = True), Variable(target)    
        print(target)    
        output = model(data)    
        test_loss += criterion(output, target).data[0]    
        pred = output.data.max(1, keepdim = True)[1]    
        correct += pred.eq(target.data.view_as(pred)).cpu().sum()    
    test_loss /= len(test_loader.dataset)    
    print('
Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)
'.format(test_loss, correct, len(test_loader.dataset), 100.* correct / len(test_loader.dataset)))    

for epoch in range(1,7):    
    train(epoch)    
    test()    

推荐答案

好的.所以我重现了你的问题,在搜索并阅读了 CrossEntropyLoss() 的 API 之后,我发现这是因为你的标签尺寸错误.

Ok. So I reproduced your problem and after some search and reading the API of CrossEntropyLoss(), I have found it's because you have a wrong label dimension.

CrossEntropyLoss 的官方文档在这里.你可以看到

输入:(N,C) 其中 C = 类数
目标:(N) 其中每个值是 0≤targets[i]≤C−1

Input: (N,C) where C = number of classes
Target: (N) where each value is 0≤targets[i]≤C−1

虽然在这里,在您的 criterion() 函数中,您有一个 batchSize x 7 输入和 batchSize x 1 标签.令人困惑的一点是,假设您的 batchSize 为 10,则不能将 10x1 张量视为大小为 10 的张量,这是损失函数所期望的.您必须明确进行大小转换.

While here, in your criterion() function, you have a batchSize x 7 input and batchSize x 1 label. The confusing point is, say your batchSize is 10, a 10x1 tensor can not be regarded as a size-10 tensor, which is what the loss function expectes. You must explictly do the size conversion.

解决方案:
在调用 loss = criteria(y_pred, labels) 之前添加 labels = labels.squeeze_() 并在测试代码中执行相同的操作.squeeze_() 函数就地删除大小为 1 的维度.所以你现在有一个 batchSize 大小的标签.

Solution:
Add labels = labels.squeeze_() before you call loss = criterion(y_pred, labels) and do the same thing in your test code. The squeeze_() funciton removes size-1 dimensions inplace. So you have a batchSize-size label now.

这篇关于pytorch 错误:CrossEntropyLoss() 不支持多目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆