PyTorch图像训练报错:RuntimeError: expected scalar type Long but found Float
PyTorch CrossEntropyLoss 类型错误及UNet训练问题
问题描述
我是PyTorch新手,正在用它做图像处理任务,遇到了CrossEntropyLoss计算时的错误,同时在训练UNet处理[5, 3, 544, 688]尺寸图像时也存在疑问。
错误代码及报错信息
测试代码:
model.to(device) # Specify the loss function and optimizer #criterion = torch.nn.CrossEntropyLoss() criterion = nn.CrossEntropyLoss() output = Variable(torch.randn(10, 120).float()) labels = Variable(torch.FloatTensor(10).uniform_(0, 120).long()) loss = criterion(output, labels.float()) optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.1)
报错信息:
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Cell In[37], line 11 8 output = Variable(torch.randn(10, 120).float()) 9 labels = Variable(torch.FloatTensor(10).uniform_(0, 120).long()) ---> 11 loss = criterion(output, labels.float()) 13 optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.1) File ~\anaconda3\envs\withGPU\lib\site-packages\torch\nn\modules\module.py:1518, in Module._wrapped_call_impl(self, *args, **kwargs) 1516 return self._compiled_call_impl(*args, **kwargs) # type: ignore[misc] 1517 else: -> 1518 return self._call_impl(*args, **kwargs) File ~\anaconda3\envs\withGPU\lib\site-packages\torch\nn\modules\module.py:1527, in Module._call_impl(self, *args, **kwargs) 1522 # If we don't have any hooks, we want to skip the rest of the logic in 1523 # this function, and just call forward. 1524 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks 1525 or _global_backward_pre_hooks or _global_backward_hooks 1526 or _global_forward_hooks or _global_forward_pre_hooks): -> 1527 return forward_call(*args, **kwargs) 1529 try: 1530 result = None File ~\anaconda3\envs\withGPU\lib\site-packages\torch\nn\modules\loss.py:1179, in CrossEntropyLoss.forward(self, input, target) 1178 def forward(self, input: Tensor, target: Tensor) -> Tensor: -> 1179 return F.cross_entropy(input, target, weight=self.weight, 1180 ignore_index=self.ignore_index, reduction=self.reduction, 1181 label_smoothing=self.label_smoothing) File ~\anaconda3\envs\withGPU\lib\site-packages\torch\nn\functional.py:3053, in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction, label_smoothing) 3051 if size_average is not None or reduce is not None: 3052 reduction = _Reduction.legacy_get_string(size_average, reduce) -> 3053 return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing) RuntimeError: expected scalar type Long but found Float
我的UNet训练代码
模型初始化
model.to(device) # Specify the loss function and optimizer #criterion = torch.nn.CrossEntropyLoss() criterion = nn.CrossEntropyLoss() output = Variable(torch.randn(10, 120).float()) labels = Variable(torch.FloatTensor(10).uniform_(0, 120).long()) loss = criterion(output, labels.float()) optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.1)
训练与验证函数
def train_one_epoch(model, optimizer, data_loader, device): model.train() # Zero the performance stats for each epoch (set initial condition - clear) running_loss = 0.0 start_time = time.time() total = 0 correct = 0 for i, (inputs, labels) in enumerate(dataloaders['train']): inputs = inputs.to(device) print(inputs.shape) labels = labels.to(device).float() #labels = labels.reshape(-1).to(device) print(labels) # output: tensor([number of outputs depends on batch size], device='cuda:0') optimizer.zero_grad() #outputs = model(inputs.float()) outputs = F.softmax(model(inputs.float()), dim=1) # Assuming labels are originally loaded as torch.Tensor # Convert labels to long type #labels = labels.long() # Flatten the labels if needed #labels = labels.reshape(-1) # Print shapes print("Inputs shape:", inputs.shape) print("Outputs shape:", outputs.shape) print("Labels shape:", labels.shape) loss = criterion(labels, torch.argmax(outputs, dim=1)) loss.backward() optimizer.step() _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total # Print performance statistics running_loss += loss.item() if i % 10 == 0: # print every 10 batches batch_time = time.time() speed = (i+1)/(batch_time-start_time) print('[%5d] loss: %.3f, speed: %.2f, accuracy: %.2f %%' % (i, running_loss, speed, accuracy)) running_loss = 0.0 total = 0 correct = 0 def val_model(model, data_loader): model.val() start_time = time.time() total = 0 correct = 0 with torch.no_grad(): for i, (inputs, labels) in enumerate(dataloaders['val']): inputs = inputs.to(device) labels = labels.to(device).long() inputs = inputs.to(device) labels = labels.to(device).long() # zero the parameter gradients #optimizer.zero_grad() # forward + backward + optimize outputs = model(inputs.float()) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum(dim=1).item() accuracy = 100 * correct / total print('Finished Testing') print('Testing accuracy: %.1f %%' %(accuracy))
训练循环
num_epochs = 3 for epoch in range(num_epochs): print("------------------ Training Epoch {} ------------------".format(epoch+1)) train_one_epoch(model, optimizer,'train' , device) val_model(model, 'val') print('Finished Training')
问题解答
错误原因解释
RuntimeError: expected scalar type Long but found Float 是因为PyTorch的CrossEntropyLoss要求目标标签必须是LongTensor类型(整数张量,代表类别索引,比如0、1、2...)。你在测试代码里把已经转成long的labels又用.float()转成了浮点型,违反了Loss的输入要求,直接触发报错。
训练代码核心修正点
标签类型修正
训练函数中不要把标签转成float,必须转为long类型:labels = labels.to(device).long() # 替换原labels.to(device).float()Loss输入逻辑修正
CrossEntropyLoss内部会自动计算softmax,不需要提前对模型输出做F.softmax,否则会导致数值不稳定:outputs = model(inputs.float()) # 直接使用模型输出的logits- Loss的调用顺序必须是
criterion(模型输出, 标签),你之前写反了输入顺序,而且用torch.argmax处理输出的操作完全错误:loss = criterion(outputs, labels) # 正确输入顺序
验证函数错误修正
model.val()是错误写法,应该用model.eval()切换到评估模式;- 统计正确样本数时,
(predicted == labels).sum(dim=1).item()会导致维度错误,直接用.sum().item()即可:correct += (predicted == labels).sum().item()
修正后的关键代码片段
训练函数Loss计算部分
optimizer.zero_grad() outputs = model(inputs.float()) # 直接用模型输出的logits labels = labels.to(device).long() loss = criterion(outputs, labels) loss.backward() optimizer.step() _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total
验证函数修正版
def val_model(model, data_loader): model.eval() # 修正为eval()模式 start_time = time.time() total = 0 correct = 0 with torch.no_grad(): for i, (inputs, labels) in enumerate(dataloaders['val']): inputs = inputs.to(device) labels = labels.to(device).long() outputs = model(inputs.float()) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print('Finished Validation') print('Validation accuracy: %.1f %%' %(accuracy))
内容的提问来源于stack exchange,提问作者Waltty
相关产品推荐
相关产品推荐

