pytorch训练过程中出现错误:Assertion input_val >= zero && input_val <= one failed.

文章描述了在使用PyTorch训练模型时遇到CUDA设备侧断言触发的错误,问题出现在计算损失函数的代码行。原因是最后一个batch只有一个样本,导致计算错误。解决方案包括丢弃最后一个batch、补全最后一个batch或调整batchsize。作者通过丢弃最后一个batch解决了问题。
摘要由CSDN通过智能技术生成

pytorch训练过程中出现错误:Assertion input_val >= zero && input_val <= one failed.

详细报错信息如下:

在用服务器跑模型计算loss时,出现如下错误:Assertion input_val >= zero && input_val <= one failed.和 RuntimeError: CUDA error: device-side assert triggered。

../aten/src/ATen/native/cuda/Loss.cu:118: operator(): block: [307,0,0], thread: [31,0,0] Assertion `input_val >= zero && input_val <= one` failed.
130it [00:49,  2.60it/s]
Traceback (most recent call last):

  File "/home/liuchuang/OPTICc/main.py", line 233, in <module>
    main(config)

  File "/home/liuchuang/OPTICc/main.py", line 129, in main
    train_DG.run()

  File "/home/liuchuang/OPTICc/train_DG.py", line 138, in run
    loss_meter.add(loss.sum().item() + 1e-6)

RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.

出现这个报错的原因可能有很多种,刚开始碰到感觉是个比较偏门的错误,很少碰见,而且我的问题和大多数的博客的解决办法也不一样,特此作记录,给出问题的小伙伴一些参考价值。

首先这是我的报错截图:
在这里插入图片描述
在这里插入图片描述
最后错误的提示为:RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.For debugging consider passing CUDA_LAUNCH_BLOCKING=1.

解决办法

1、故障定位

首先定位到出错的位置,我的代码出错的位置为计算损失函数的这一行:

loss = self.seg_cost(pred, y)
self.optimizer.zero_grad()
loss.backward()
# print(loss.sum().item())
**loss_meter.add(loss.sum().item())**
self.optimizer.step()

中间我打花括号的那一行代码出错:loss_meter.add(loss.sum().item()),这个报错奇怪就在我前面的iteration计算都是正确的,到了这最后一个iteration报错了。因此我将pred和y的shape全部打印出来发现问题了,原来我的最后一个batch只有一个sample,维度为(1,2,256,256),这样在计算的时候就会报错,每一个batch至少大于1个样本,才能计算损失函数。

2、故障解决

通过查阅资料有好几种办法可以解决这个问题。以下列举三种:
我的训练样本总数是1041,每个batch的大小是8,这意味着最后一个batch的大小会是1,这可能会导致一些问题,例如如果你在计算损失函数时需要使用到更多的样本,或者在某些层(例如Batch Normalization)需要更多样本的情况。

有几种可能的解决方案:

  1. 丢弃最后一个batch:在许多情况下,简单地丢弃最后一个不完整的batch是可以接受的,尤其是当你有大量的训练数据时。
    方案:在如下数据加载的代码处添加 drop_last = True.
 source_dataloader = DataLoader(dataset=source_dataset,
                                       batch_size=config.batch_size,
                                       shuffle=True,
                                       pin_memory=True,
                                       collate_fn=collate_fn_w_transform,
                                       num_workers=config.num_workers,
                                       drop_last=True)
  1. 补全最后一个batch:你可以通过复制一些样本来补全最后一个batch。虽然这可能会导致一些小的训练偏差,但如果你的数据集足够大,这个影响应该是可以忽略不计的。
    方案:如果你希望在训练时保留最后一个不完整的batch,可以选择填充(padding)来补全这个batch。这种情况下,你需要设定一个固定的填充值或者策略。在PyTorch中,可以使用torch.utils.data.Dataset和torch.nn.utils.rnn.pad_sequence来创建一个可以进行填充操作的数据集。
from torch.nn.utils.rnn import pad_sequence
from torch.utils.data import Dataset, DataLoader

class MyDataset(Dataset):
    def __init__(self, data):
        self.data = data

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

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

def collate_fn(batch):
    batch = pad_sequence(batch, batch_first=True, padding_value=0)
    return batch

# 假设 data 是你的数据
dataset = MyDataset(data)
dataloader = DataLoader(dataset, batch_size=8, collate_fn=collate_fn)

  1. 调整batch size:如果可能,你可以尝试调整你的batch size,使其能够被你的样本总数整除。例如,如果你的样本总数是1041,你可以选择一个能被1041整除的数作为你的batch size,例如1、13、17、23、31、37等。

这是一些可能的解决方案,我是使用第一种方案解决了问题,当然第一种和第三种都非常好实现,第二种我没有试过,感兴趣的朋友可以自行尝试。

完结!撒花!

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值