PyTorch GPU迁移时出现‘张量位于CPU但预期在GPU’错误的技术求助
解决PyTorch中"is on CPU, but expected to be on GPU"的设备不匹配问题
嘿,这个问题我太熟了!你遇到的错误核心就是模型组件和输入张量没有在同一个计算设备上——更具体来说,你的代码里有个关键细节没处理对,导致隐藏层根本没被移到GPU上。
问题根源分析
你用普通的list()来存储hidden_layers里的线性层,但PyTorch只会识别并管理用nn.Module或nn.ModuleList注册的组件。普通列表里的层不会被纳入模型的参数管理体系,当你调用net.to(device)时,这些隐藏层还会留在CPU上,而输入张量如果已经移到GPU,就会出现设备不匹配的报错。
具体修复步骤
1. 把普通列表改成nn.ModuleList
修改你的模型定义,将存储隐藏层的列表替换为PyTorch的nn.ModuleList,这样所有层都会被正确注册到模型中,调用.to(device)时就能统一迁移到GPU:
import torch.nn as nn import torch class Net(nn.Module): def __init__(self, num_features, size_hidden_layer, n_hidden_layer): super(Net, self).__init__() self.size_hidden_layer = size_hidden_layer self.n_hidden_layer = n_hidden_layer # 替换普通list为nn.ModuleList self.hidden_layers = nn.ModuleList() self.hidden_layers.append(nn.Linear(num_features, size_hidden_layer)) for _ in range(n_hidden_layer-1): self.hidden_layers.append(nn.Linear(size_hidden_layer, size_hidden_layer)) self.last_layer = nn.Linear(size_hidden_layer, 1) def forward(self, x): # 遍历起来更简洁的写法 for layer in self.hidden_layers: x = torch.relu(layer(x)) return self.last_layer(x)
2. 确保模型和输入都迁移到同一设备
训练前要把整个模型移到目标设备,同时每个batch的输入张量和标签也要同步迁移:
# 先检测可用设备 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 初始化模型并迁移到设备 net = Net(num_features=10, size_hidden_layer=64, n_hidden_layer=2).to(device) # 训练循环中,每个batch都要迁移数据 for X, y in train_dataloader: X = X.to(device) y = y.to(device) # 后续的前向传播、损失计算、反向传播都能正常运行了 outputs = net(X) loss = criterion(outputs, y) # ... 其他训练逻辑
3. 调试小技巧
如果还是不确定设备是否匹配,可以打印模型参数和输入张量的设备来验证:
# 查看模型所在设备(取第一个参数即可) print(next(net.parameters()).device) # 查看输入张量所在设备 print(X.device)
两者必须显示一致(比如都是cuda:0)才能正常运行。
额外注意点
- 如果自定义了损失函数或者在模型外创建了其他张量,也要确保这些张量迁移到同一设备;
- 推断阶段的输入数据同样需要迁移到模型所在的设备,不能只在训练时处理。
内容的提问来源于stack exchange,提问作者demonoga
相关产品推荐
相关产品推荐

