pytorch 错误:CrossEntropyLoss() 中不支持多目标
Posted
技术标签:
【中文标题】pytorch 错误:CrossEntropyLoss() 中不支持多目标【英文标题】:pytorch error: multi-target not supported in CrossEntropyLoss() 【发布时间】:2018-08-18 18:43:33 【问题描述】:我正在使用加速度数据来预测某些活动的项目。
但是我在损失计算上有问题。我正在使用CrossEntropyLoss
。
数据用于它,如下所示 我使用每行的前 4 个数据来预测索引,就像每行的最后一个一样。
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's 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%)]\tLoss: :.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('\nTest set: Average loss: :.4f, Accuracy: / (:.0f%)\n'.format(test_loss, correct, len(test_loader.dataset), 100.* correct / len(test_loader.dataset)))
for epoch in range(1,7):
train(epoch)
test()
【问题讨论】:
【参考方案1】:好的。所以我重现了你的问题,经过一番搜索和阅读CrossEntropyLoss()
的API,我发现这是因为你的标签尺寸错误。
Offical docs of CrossEntropyLoss 在这里。你可以看到
输入:(N,C) 其中 C = 类数 目标:(N) 其中每个值为 0≤targets[i]≤C−1
此时,在您的criterion()
函数中,您有一个batchSize x 7
输入和batchSize x 1
标签。令人困惑的一点是,假设你的 batchSize 是 10,一个 10x1 的张量不能被视为一个 size-10 的张量,这是损失函数所期望的。您必须明确地进行大小转换。
解决方案:
在调用 loss = criterion(y_pred, labels)
之前添加 labels = labels.squeeze_()
并在测试代码中执行相同的操作。 squeeze_()
函数在原地删除 size-1 尺寸。所以你现在有一个batchSize
-size 标签。
【讨论】:
非常感谢您的帮助!! @MinohKim 没关系。 Pytorch 论坛也是提问的好地方。祝你有美好的一天。 @lincr 感谢您的解决方案!小修正:labels.squeeze_()
或 labels = labels.squeeze()
可以使用,因为 squeeze_()
就地作用以上是关于pytorch 错误:CrossEntropyLoss() 中不支持多目标的主要内容,如果未能解决你的问题,请参考以下文章