简体   繁体   English

Pytorch:需要一维目标张量,不支持多目标

[英]Pytorch: 1D target tensor expected, multi-target not supported

I want to train a 1D CNN on time series.我想在时间序列上训练一维 CNN。 I get the following error message 1D target tensor expected, multi-target not supported我收到以下错误消息1D target tensor expected, multi-target not supported

Here is the code with simulated data corresponding to the structures of my data as well as the error message这是带有与我的数据结构相对应的模拟数据的代码以及错误消息

import torch
from torch.utils.data import DataLoader
import torch.utils.data as data
import torch.nn as nn

import numpy as np
import random
from tqdm.notebook import tqdm

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)


train_dataset = []
n_item = 20
for i in range(0,n_item):
    train_data = np.random.uniform(-10, 10, 500)
    train_dataset.append(train_data)
train_dataset = np.asarray(train_dataset)
train_dataset.shape
ecg_train = torch.from_numpy(train_dataset).float()
labels_train = np.random.randint(2, size=n_item)
labels_train = torch.from_numpy(labels_train).long()


val_dataset = []
n_item = 10
for i in range(0,n_item):
    val_data = np.random.uniform(-10, 10, 500)
    val_dataset.append(val_data)
val_dataset = np.asarray(val_dataset)
val_dataset.shape
ecg_validation = torch.from_numpy(val_dataset).float()
labels_validation = np.random.randint(2, size=n_item)
labels_validation = torch.from_numpy(labels_validation).long()

class ECGNet(data.Dataset):
    """ImageNet Limited dataset."""
    
    def __init__(self, ecgs, labls, transform=None):
            self.ecg = ecgs
            self.target = labls
            self.transform = transform

    def __getitem__(self, idx):
        ecgVec = self.ecg[idx] #.reshape(10, -1)
        labelID = self.target[idx].reshape(1)

        return ecgVec,labelID

    def __len__(self):
        return len(self.ecg)


train_data = ECGNet(ecg_train, 
                             labels_train, 
                   )
print("size of Training dataset: {}".format(len(train_data)))

validation_data = ECGNet(ecg_validation, 
                             labels_validation, 
                   )
print("size of Training dataset: {}".format(len(validation_data)))


batch_size = 1
train_dataloader = DataLoader(dataset = train_data,
                              batch_size=batch_size, 
                              shuffle = True, 
                              num_workers = 0)

val_dataloader = DataLoader(dataset = validation_data,
                              batch_size=batch_size, 
                              shuffle = True, 
                              num_workers = 0)


def train_epoch(model, train_dataloader, optimizer, loss_fn):
    losses = []
    correct_predictions = 0
    # Iterate mini batches over training dataset
    for images, labels in tqdm(train_dataloader):
        images = images.to(device)
    #labels = labels.squeeze_()
        labels = labels.to(device)

        #labels = labels.to(device=device, dtype=torch.int64)
        # Run predictions
        output = model(images)
        # Set gradients to zero
        optimizer.zero_grad()
        # Compute loss
        loss = loss_fn(output, labels)
        # Backpropagate (compute gradients)
        loss.backward()
        # Make an optimization step (update parameters)
        optimizer.step()
        # Log metrics
        losses.append(loss.item())
        predicted_labels = output.argmax(dim=1)
        correct_predictions += (predicted_labels == labels).sum().item()
    accuracy = 100.0 * correct_predictions / len(train_dataloader.dataset)
    # Return loss values for each iteration and accuracy
    mean_loss = np.array(losses).mean()
    return mean_loss, accuracy

def evaluate(model, dataloader, loss_fn):
    losses = []
    correct_predictions = 0
    with torch.no_grad():
        for images, labels in dataloader:
            images = images.to(device)
            #labels = labels.squeeze_()
            labels = labels.to(device=device, dtype=torch.int64)
            # Run predictions
            output = model(images)
            # Compute loss
            loss = loss_fn(output, labels)
            # Save metrics
            predicted_labels = output.argmax(dim=1)
            correct_predictions += (predicted_labels == labels).sum().item()
            losses.append(loss.item())
    mean_loss = np.array(losses).mean()
    accuracy = 100.0 * correct_predictions / len(dataloader.dataset)
    # Return mean loss and accuracy
    return mean_loss, accuracy

def train(model, train_dataloader, val_dataloader, optimizer, n_epochs, loss_function):
    # We will monitor loss functions as the training progresses
    train_losses = []
    val_losses = []
    train_accuracies = []
    val_accuracies = []

    for epoch in range(n_epochs):
        model.train()
        train_loss, train_accuracy = train_epoch(model, train_dataloader, optimizer, loss_fn)
        model.eval()
        val_loss, val_accuracy = evaluate(model, val_dataloader, loss_fn)
        train_losses.append(train_loss)
        val_losses.append(val_loss)
        train_accuracies.append(train_accuracy)
        val_accuracies.append(val_accuracy)
        print('Epoch {}/{}: train_loss: {:.4f},        train_accuracy: {:.4f}, val_loss: {:.4f},        val_accuracy: {:.4f}'.format(epoch+1, n_epochs,
                                     train_losses[-1],
                                     train_accuracies[-1],
                                     val_losses[-1],
                                     val_accuracies[-1]))
    return train_losses, val_losses, train_accuracies, val_accuracies


class Simple1DCNN(torch.nn.Module):
    def __init__(self):
        super(Simple1DCNN, self).__init__()
        self.layer1 = torch.nn.Conv1d(in_channels=50, 
                                      out_channels=20, 
                                      kernel_size=5, 
                                      stride=2)
        self.act1 = torch.nn.ReLU()
        self.layer2 = torch.nn.Conv1d(in_channels=20, 
                                      out_channels=10, 
                                      kernel_size=1)
        
        self.fc1 = nn.Linear(10* 3, 2)
    def forward(self, x):
        print(x.shape)
        x = x.view(1, 50,-1)
        print(x.shape)
        x = self.layer1(x)
        print(x.shape)
        x = self.act1(x)
        print(x.shape)
        x = self.layer2(x)
        print(x.shape)
        x = x.view(1,-1)
        print(x.shape)
        x = self.fc1(x)
        print(x.shape)
        print(x)
        
        return x



model_a = Simple1DCNN()
model_a = model_a.to(device)

criterion = nn.CrossEntropyLoss()

loss_fn = torch.nn.CrossEntropyLoss()
n_epochs_a = 50
learning_rate_a = 0.01
alpha_a = 1e-5
momentum_a = 0.9
optimizer = torch.optim.SGD(model_a.parameters(), 
                            momentum = momentum_a,
                            nesterov = True,
                            weight_decay = alpha_a,
                            lr=learning_rate_a)
train_losses_a, val_losses_a, train_acc_a, val_acc_a = train(model_a,
                                                             train_dataloader,
                                                             val_dataloader,
                                                             optimizer,
                                                             n_epochs_a,
                                                             loss_fn
                                                            )



Error message:错误信息:

cpu
size of Training dataset: 20
size of Training dataset: 10
  0%|          | 0/20 [00:00<?, ?it/s]
torch.Size([1, 500])
torch.Size([1, 50, 10])
torch.Size([1, 20, 3])
torch.Size([1, 20, 3])
torch.Size([1, 10, 3])
torch.Size([1, 30])
torch.Size([1, 2])
tensor([[ 0.5785, -1.0169]], grad_fn=<AddmmBackward>)
Traceback (most recent call last):
  File "SO_question.py", line 219, in <module>
    train_losses_a, val_losses_a, train_acc_a, val_acc_a = train(model_a,
  File "SO_question.py", line 137, in train
    train_loss, train_accuracy = train_epoch(model, train_dataloader, optimizer, loss_fn)
  File "SO_question.py", line 93, in train_epoch
    loss = loss_fn(output, labels)
  File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/modules/loss.py", line 961, in forward
    return F.cross_entropy(input, target, weight=self.weight,
  File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/functional.py", line 2468, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
  File "/Users/mymac/Documents/programming/python/mainenv/lib/python3.8/site-packages/torch/nn/functional.py", line 2264, in nll_loss
    ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
RuntimeError: 1D target tensor expected, multi-target not supported

What am I doing wrong?我究竟做错了什么?

You are using nn.CrossEntropyLoss as the criterion for your training.您正在使用nn.CrossEntropyLoss作为训练的标准。 You correctly passed the labels as indices of the ground truth class: 0 s and 1 s.您正确地将标签作为基本事实 class 的索引传递: 0 s 和1 s。 However, as the error message suggests, it needs to be a 1D tensor!但是,正如错误消息所暗示的那样,它需要是一维张量!

Simply remove the reshape in ECGNet 's __getitem__ :只需删除ECGNet__getitem__中的重塑:

def __getitem__(self, idx):
    ecgVec = self.ecg[idx]
    labelID = self.target[idx]
    return ecgVec,labelID

Edit编辑

I want to increase the batch_size to 8 .我想将batch_size增加到8 But now I get the error [...]但是现在我得到了错误[...]

You are doing a lot of broadcasting (flattening) which surely will affect the batch size.您正在进行大量广播(展平),这肯定会影响批量大小。 As a general rule of thumb never fiddle with axis=0 .作为一般经验法则,永远不要摆弄axis=0 For instance, if you have an input shape of (8, 500) , straight off you have a problem when doing x.view(1, 50, -1) .例如,如果您的输入形状为(8, 500) ,那么在执行x.view(1, 50, -1)时就会遇到问题。 Since the resulting tensor will be (1, 50, 80) (the desired shape would have been (8, 50, 10) ).由于生成的张量将是(1, 50, 80) (所需的形状应该是(8, 50, 10) )。 Instead, you could broadcast with x.view(x.size(0), 50, -1) .相反,您可以使用x.view(x.size(0), 50, -1)进行广播。

Same with x.view(1, -1) later down forward .x.view(1, -1) later down forward相同。 You are looking to flatten the tensor, but you should not flatten it along with the batches, they need to stay separated!您希望将张量展平,但不应将其与批次一起展平,它们需要保持分开! It's safer to use torch.flatten , yet I prefernn.Flatten which flattens from axis=1 to axis=-1 by default.使用torch.flatten更安全,但我更喜欢nn.Flatten ,它默认从axis=1扁平化到axis=-1


My personal advice is to start with a simple setup (without train loops etc...) to verify the architecture and intermediate output shapes.我个人的建议是从一个简单的设置开始(没有火车环等......)来验证架构和中间 output 形状。 Then, add the necessary logic to handle the training.然后,添加必要的逻辑来处理训练。

class ECGNet(data.Dataset):
    """ImageNet Limited dataset."""
    
    def __init__(self, ecgs, labls, transform=None):
        self.ecg = ecgs
        self.target = labls
        self.transform = transform

    def __getitem__(self, idx):
        ecgVec = self.ecg[idx]
        labelID = self.target[idx]
        return ecgVec, labelID

    def __len__(self):
        return len(self.ecg)


class Simple1DCNN(nn.Module):
    def __init__(self):
        super(Simple1DCNN, self).__init__()
        self.layer1 = nn.Conv1d(in_channels=50, 
                                out_channels=20, 
                                kernel_size=5, 
                                stride=2)
        self.act1 = nn.ReLU()
        self.layer2 = nn.Conv1d(in_channels=20, 
                                out_channels=10, 
                                kernel_size=1)
        
        self.fc1 = nn.Linear(10*3, 2)
        self.flatten = nn.Flatten()

    def forward(self, x):
        x = x.view(x.size(0), 50, -1)
        x = self.layer1(x)
        x = self.act1(x)
        x = self.layer2(x)
        x = self.flatten(x)
        x = self.fc1(x)
        
        return x

batch_size = 8
train_data = ECGNet(ecg_train, labels_train)
train_dl = DataLoader(dataset=train_data,
                      batch_size=batch_size, 
                      shuffle=True,
                      num_workers=0)

model = Simple1DCNN()
criterion = nn.CrossEntropyLoss()

Then然后

>>> x, y = next(iter(train_dl))
>>> y_hat = model(x)

>>> y_hat.shape
torch.Size([8, 2])

Also, make sure your loss works:另外,确保你的损失有效:

>>> criterion(y_hat, y)
tensor(..., grad_fn=<NllLossBackward>)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何解决这个问题(Pytorch RuntimeError:预期一维目标张量,不支持多目标) - how to solve this (Pytorch RuntimeError: 1D target tensor expected, multi-target not supported) 运行时错误:预期一维目标张量,不支持多目标 Pytorch - RuntimeError: 1D target tensor expected, multi-target not supported Pytorch 如何解决多类分类中的“RuntimeError: 1D target tensor expected, multi-target not supported”? - How to solve “RuntimeError: 1D target tensor expected, multi-target not supported” in multi-class classification? 对于分类 class RuntimeError:预期为 0D 或 1D 目标张量,不支持多目标 - for categorical class RuntimeError: 0D or 1D target tensor expected, multi-target not supported RuntimeError: 1D 目标张量,不支持多目标 - RuntimeError: 1D target tensor expected, multi-target not supported Python: NumPy pytorch错误:CrossEntropyLoss()中不支持多目标 - pytorch error: multi-target not supported in CrossEntropyLoss() pytorch:“不支持多目标”错误消息 - pytorch: “multi-target not supported” error message Pytorch:CrossEntropyLoss 的多目标错误 - Pytorch: multi-target error with CrossEntropyLoss 多目标解决方案构建器 - Multi-target solution builder Pytorch nn.CrossEntropyLoss 给出,ValueError: 预期目标大小 (x, y),得到 3d 张量的 torch.Size([x, z]) - Pytorch nn.CrossEntropyLoss giving, ValueError: Expected target size (x, y), got torch.Size([x, z]) for 3d tensor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM