皮肤图像分类训练遇RuntimeError:期望CPU后端却得到CUDA权重
解决RuntimeError: Expected object of backend CPU but got backend CUDA for argument #2 'weight'
这个错误的核心原因很明确:你的模型参数在CUDA设备上,但输入/目标张量却被意外放到了CPU上,导致计算时设备不兼容。我们来一步步拆解问题,然后给出修复方案:
问题定位
看你代码里这两行关键代码:
input_var=torch.tensor(input) depth_var=torch.tensor(depth).squeeze(1)
你已经通过input = input.to(device)和depth = depth.to(device)把数据移到了目标设备(比如CUDA),但torch.tensor()默认会在CPU上创建新的张量——这就把已经移到CUDA的数据又拉回了CPU。而你的模型已经通过model = model.to(device)放到了CUDA上,当模型用CPU的输入做前向传播时,模型的权重(在CUDA)和输入(在CPU)设备不匹配,就触发了这个错误。
修复方案
1. 移除不必要的torch.tensor()调用
直接复用已经移到目标设备的张量即可,不需要重新创建:
input_var = input depth_var = depth.squeeze(1)
如果担心数据类型或设备的一致性,也可以用torch.as_tensor()来保留原张量的设备属性:
input_var = torch.as_tensor(input, device=device) depth_var = torch.as_tensor(depth, device=device).squeeze(1)
2. 优化模型设备移动的位置
把model = model.to(device)移到训练循环外面,不需要每个epoch都重复移动模型,训练前执行一次就足够了:
model = model.to(device) # 移到循环外,仅执行一次 start_epoch=0 for epoch in range(num_epochs): # 循环内的代码逻辑...
3. 其他小优化
- 用
model(input_var)代替model.forward(input_var):这是PyTorch的规范写法,model()会自动调用__call__方法,包含Dropout、BatchNorm等层的训练模式处理,直接调用forward会跳过这些关键逻辑。 - 简化损失累加:
running_loss += loss.item()比running_loss += loss.data.cpu().numpy()更简洁,loss.item()直接返回CPU上的数值,无需额外转换。
修正后的完整代码片段
model = model.to(device) start_epoch=0 for epoch in range(num_epochs): print('Starting train epoch %d / %d' % (start_epoch + epoch + 1, num_epochs)) print(device) running_loss = 0 count = 0 epoch_loss = 0 for step,(input, depth) in enumerate(train_loader): input = input.to(device) depth = depth.to(device) # 直接使用已在目标设备上的张量 input_var = input depth_var = depth.squeeze(1) output = model(input_var) # 规范的前向传播调用 loss = loss_fn(output, depth_var) print('count: ',count,' loss:', loss.item()) count += 1 running_loss += loss.item() optimizer.zero_grad() loss.backward() optimizer.step() if count%100==0: torch.save(model,"./pkl/cifar.pkl")
这样修改后,模型、输入、目标张量都会统一在同一个设备上,就不会再出现设备不匹配的错误了。
内容的提问来源于stack exchange,提问作者chris_123
相关产品推荐
相关产品推荐

