PyTorch加载CNN模型预测报错:TypeError: 'collections.OrderedDict'对象不可调用
解决PyTorch加载模型后调用报错:TypeError: 'collections.OrderedDict' object is not callable
你踩了PyTorch模型保存/加载的一个常见坑——你加载回来的不是完整的模型实例,而是模型的状态字典(state_dict),也就是一个OrderedDict类型的参数集合,直接用它做预测调用自然会报错。
错误原因拆解
如果训练时你用的是torch.save(model.state_dict(), "score_detector.pkl")这种方式保存,那torch.load()拿到的就是模型所有层的参数字典,而非可以直接调用的模型对象。这就像你只有一堆零件,还没拼成能干活的机器,肯定没法直接用。
一步步解决问题
1. 重构你的CNN模型结构
首先要把训练时定义的CNN类原封不动地写出来——层的数量、参数、顺序必须和训练时完全一致,否则参数没法对应上。比如假设你的模型是这样的(请替换成你实际的模型结构):
import torch import torch.nn as nn import torch.nn.functional as F class CNN(nn.Module): def __init__(self): super().__init__() # 和训练时完全一致的层结构 self.conv1 = nn.Conv2d(1, 16, kernel_size=5, padding=2) self.pool = nn.MaxPool2d(2) self.conv2 = nn.Conv2d(16, 32, kernel_size=5, padding=2) self.fc1 = nn.Linear(32 * 7 * 7, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): # 和训练时完全一致的前向传播逻辑 x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(x.size(0), -1) fc1_out = F.relu(self.fc1(x)) output = self.fc2(fc1_out) # 对应你原代码返回的test_output和last_layer return output, fc1_out
2. 正确加载模型参数
先实例化模型,再把加载的状态字典“注入”到模型中:
# 1. 创建模型实例,并移到GPU(和训练时保持一致) cnn = CNN().cuda() # 2. 加载保存的状态字典到模型 cnn.load_state_dict(torch.load("/usr/prakt/w153/Desktop/score_detector.pkl")) # 3. 必须切换到评估模式!避免BatchNorm、Dropout等层干扰预测结果 cnn.eval()
3. 优化你的预测代码
你的代码里用了Variable和volatile=True,这是PyTorch 0.4之前的旧写法,现在可以简化,同时要保证图像预处理和训练时一致:
import scipy.ndimage # 读取图像 img = scipy.ndimage.imread("/usr/prakt/w153/Desktop/resize_num_three.png") # 图像预处理(和训练时对齐): # 如果是RGB图转灰度图:img = img.mean(axis=2) # 归一化到0-1范围(MNIST数据的常规处理) img = img / 255.0 # 调整维度为模型需要的格式:(28,28) → (1,1,28,28),对应[batch_size, channels, height, width] test_x = torch.FloatTensor(img).unsqueeze(0).unsqueeze(1).cuda() # 用torch.no_grad()关闭梯度计算,节省内存 with torch.no_grad(): test_output, last_layer = cnn(test_x) # 获取最终预测结果 pred = torch.max(test_output, 1)[1].item() print(f"预测的数字是: {pred}")
额外提醒
- 如果想在CPU上预测,加载模型时添加
map_location='cpu':torch.load("xxx.pkl", map_location='cpu'),同时模型实例不用移到GPU。 - 注意颜色模式:MNIST是黑底白字,如果你的图像是白底黑字,需要反转:
img = 1 - img,否则模型可能识别不准。 - 确认图像尺寸确实是28*28,和MNIST数据集一致。
内容的提问来源于stack exchange,提问作者Yingqiang Gao
相关产品推荐
相关产品推荐

