Pytorch加载模型并进行图像分类预测

本文详细介绍了使用PyTorch进行图像分类的流程,包括模型实例化、加载、输入图像处理和输出分类结果。内容涵盖将RGB图像转换为灰度图,使用PIL库处理图像,理解图像通道,将多张图像合并为numpy数组并转换为Tensor,以及处理常见的PyTorch运行时错误。此外,还讨论了torch.from_numpy与torch.Tensor的区别以及torch.squeeze和torch.unsqueeze的用法。
部署运行你感兴趣的模型镜像

目录

1. 整体流程

1)实例化模型

2)加载模型

3)输入图像

4)输出分类结果

5)完整代码

2. 处理图像

 1) How can i convert an RGB image into grayscale in Python?

2)PIL 处理图像的基本操作

3)图像通道数的理解

4)Convert 3 channel image to  2 channel

5)图像通道转换

6)将所有的图像合并为一个numpy数组

7)torch.from_numpy VS torch.Tensor

8)torch.squeeze() 和torch.unsqueeze()

3.issue

1)TypeError: 'module' object is not callable

2)TypeError: 'collections.OrderedDict' object is not callable

3)   TypeError: __init__() missing 1 required positional argument: 'XX'

4)    RuntimeError: Error(s) in loading state_dict for PythonNet: Missing key(s) in state_dict:

5)    RuntimeError: Expected 4-dimensional input for 4-dimensional weight [128, 1, 3, 3], but got 2-dimensional input of size [480, 640] instead

6)RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor



1. 整体流程

1)实例化模型

Assume that the content of YourClass.py is:

class YourClass:
    # ......

If you use:

from YourClassParentDir import YourClass  # means YourClass
from model import PythonNet

net= PythonNet(T=16).eval().cuda()

2)加载模型

import torch

net.load_state_dict(torch.load('checkpoint_max.pth'),False)

3)输入图像

目的:从文件夹中加载所有图像组合为一个 numpy array 作为模型输入

原始图像输入维度:(480,640)

目标图像输入维度:(16,1,128,128)

import glob
from PIL import Image
import numpy as np
from torch.autograd import Variable

#获取图像路径
filelist = glob.glob('./testdata/a/*.jpg')

#打开图像open('frame_path')--》转换为灰度图convert('L')--》缩放图像resize((width, height)) --》合并文件夹中的所有图像为一个numpy array
x = np.array([np.array(Image.open(frame).convert('L').resize((128,128))) for frame in filelist])

#用torch.from_numpy这个方法将numpy类转换成tensor类
x = torch.from_numpy(x).type(torch.FloatTensor).cuda()

#扩充数据维度
x = Variable(torch.unsqueeze(x,dim=1).float(),requires_grad=False)

4)输出分类结果

outputs = net(x)
_, predicted = torch.max(outputs,1)

torch.max()这个函数返回输入张量中所有元素的最大值。

返回一个命名元组(values,indices),其中values是给定维dim中输入张量的每一行的最大值。indices是找到的每个最大值的索引位置(argmax)。也就是说,返回的第一个值是对应图像在类别中的最大概率值,第二个值是最大概率值的对应类别。

Pytorch 分类问题输出结果的数据整理方式:_, predicted = torch.max(outputs.data, 1) - stardsd - 博客园

5)完整代码

from PIL import Image
from torch.autograd import Variable
import numpy as np
import torch
import glob
from model import PythonNet

##############处理输入图像#######################################
#获取图像路径
filelist = glob.glob('./testdata/a/*.jpg')

#打开图像open('frame_path')--》转换为灰度图convert('L')--》缩放图像resize((width, height)) --》合并文件夹中的所有图像为一个numpy array
x = np.array([np.array(Image.open(frame).convert('L').resize((128,128))) for frame in filelist])

#用torch.from_numpy这个方法将numpy类转换成tensor类
x = torch.from_numpy(x).type(torch.FloatTensor).cuda()

#扩充数据维度
x = Variable(torch.unsqueeze(x,dim=1).float(),requires_grad=False)

#############定义预测函数#######################################
def predict(x):
    net= PythonNet(T=16).eval().cuda()
    net.load_state_dict(torch.load('checkpoint_max.pth'),False)

    outputs = net(x)
    _, predicted = torch.max(outputs,1)
    print("_:",_)
    print("predicted:",predicted)
    print("outputs:",outputs)

############输入图像进行预测#####################################
predict(x)

2. 处理图像

 1) How can i convert an RGB image into grayscale in Python?

matplotlib - How can I convert an RGB image into grayscale in Python? - Stack Overflow

2)PIL 处理图像的基本操作

python——PIL Image处理图像_aaon22357的博客-优快云博客

3)图像通道数的理解

关于图像通道的理解 | TinaCristal's Blog

4)Convert 3 channel image to  2 channel

python - I have converted 3 channel RGB image into 2 channels grayscale image, How to decrease greyscale channels to 1? - Stack Overflow

5)图像通道转换

图像通道转换——从np.ndarray的[w, h, c]转为Tensor的[c, w, h]_莫邪莫急的博客-优快云博客

6)将所有的图像合并为一个numpy数组

python — 如何在numpy数组中加载多个图像?

7)torch.from_numpy VS torch.Tensor

torch.from_numpy VS torch.Tensor_麦克斯韦恶魔的博客-优快云博客

8)torch.squeeze() 和torch.unsqueeze()

pytorch学习 中 torch.squeeze() 和torch.unsqueeze()的用法_xiexu911的博客-优快云博客_torch.unsqueeze

3.issue

1)TypeError: 'module' object is not callable

python - TypeError: 'module' object is not callable - Stack Overflow

2)TypeError: 'collections.OrderedDict' object is not callable

pytorch加载模型报错TypeError: ‘collections.OrderedDict‘ object is not callable_xiaoqiaoliushuiCC的博客-优快云博客

3)   TypeError: __init__() missing 1 required positional argument: 'XX'

Python成功解决TypeError: __init__() missing 1 required positional argument: ‘comment‘_肥鼠路易的博客-优快云博客

4)    RuntimeError: Error(s) in loading state_dict for PythonNet: Missing key(s) in state_dict:

pytorch加载模型报错RuntimeError: Error(s) in loading state_dict for SSD:Missing key(s) in state_dict:... - 代码先锋网

5)    RuntimeError: Expected 4-dimensional input for 4-dimensional weight [128, 1, 3, 3], but got 2-dimensional input of size [480, 640] instead

RuntimeError: Expected 4-dimensional input for 4-dimensional weight 64 3 3, but got 3-dimensional in_Steven_ycs的博客-优快云博客

6)RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor

RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.DoubleTensor) should be the_一千零一夜的博客-优快云博客


​​​​​​

您可能感兴趣的与本文相关的镜像

PyTorch 2.9

PyTorch 2.9

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think> 我们参考了站内引用中的信息,特别是引用[3]中提到的PyTorch加载模型进行图像分类预测的方法。下面将详细介绍如何使用PyTorch加载.pth模型文件对实际图像进行分类预测。 ### 1. 加载预训练模型 首先,我们需要定义与训练时相同的模型结构,然后加载预训练的权重。 ```python import torch import torchvision.transforms as transforms from PIL import Image import matplotlib.pyplot as plt # 定义模型(假设是一个简单的CNN,与训练时结构一致) class SimpleCNN(torch.nn.Module): def __init__(self, num_classes=10): super(SimpleCNN, self).__init__() self.features = torch.nn.Sequential( torch.nn.Conv2d(3, 16, kernel_size=3, padding=1), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size=2, stride=2), torch.nn.Conv2d(16, 32, kernel_size=3, padding=1), torch.nn.ReLU(), torch.nn.MaxPool2d(kernel_size=2, stride=2) ) self.classifier = torch.nn.Sequential( torch.nn.Linear(32 * 56 * 56, 256), # 假设输入图像为224x224,经过两次池化后为56x56 torch.nn.ReLU(), torch.nn.Linear(256, num_classes) ) def forward(self, x): x = self.features(x) x = torch.flatten(x, 1) x = self.classifier(x) return x # 创建模型实例 model = SimpleCNN(num_classes=10) # 加载预训练权重 model.load_state_dict(torch.load('model.pth', map_location=torch.device('cpu'))) model.eval() # 设置为评估模式 ``` ### 2. 图像预处理 对输入图像进行与训练时相同的预处理操作,包括调整大小、转换为张量、标准化等。 ```python def preprocess_image(image_path): # 定义预处理转换 transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整大小 transforms.ToTensor(), # 转换为张量 transforms.Normalize( # 标准化 mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) ]) # 加载图像 image = Image.open(image_path).convert('RGB') # 应用预处理 input_tensor = transform(image) # 添加批次维度 input_batch = input_tensor.unsqueeze(0) # 可视化预处理后的图像(可选) plt.imshow(input_tensor.permute(1, 2, 0)) # 注意:标准化后的图像可能看起来不正常 plt.title('预处理后的图像') plt.axis('off') plt.show() return input_batch ``` ### 3. 执行预测 使用加载模型对预处理后的图像进行预测。 ```python def predict_image(model, image_path): # 预处理图像 input_batch = preprocess_image(image_path) # 使用模型进行预测 with torch.no_grad(): output = model(input_batch) # 应用softmax获取概率 probabilities = torch.nn.functional.softmax(output[0], dim=0) # 获取预测结果 predicted_class_idx = torch.argmax(probabilities).item() return predicted_class_idx, probabilities ``` ### 4. 完整示例 整合以上步骤,对单张图像进行分类预测。 ```python if __name__ == "__main__": # 图像路径 image_path = 'test_image.jpg' # 执行预测 predicted_class, probs = predict_image(model, image_path) # 输出结果 print(f'预测类别: {predicted_class}') print(f'各类别概率: {probs}') # 假设有类别标签列表 class_labels = ['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车'] print(f'预测类别标签: {class_labels[predicted_class]}') ``` ### 5. 关键注意事项 1. **模型结构一致性**:加载预训练权重时,必须使用与训练时完全相同的模型结构[^3]。 2. **预处理一致性**:图像预处理必须与训练时完全相同,包括大小调整、标准化参数等[^2]。 3. **设备兼容性**:如果训练时使用GPU,预测时使用CPU,需通过`map_location`参数指定: ```python torch.load('model.pth', map_location=torch.device('cpu')) ``` 4. **模式切换**:预测前务必调用`model.eval()`将模型设置为评估模式,这会影响如Dropout和BatchNorm等层的运行方式。 ### 6. 部署优化 对于生产环境部署,可以考虑以下优化: - **转换为ONNX格式**:实现跨平台部署(如引用[1]所述): ```python # 导出为ONNX格式 dummy_input = torch.randn(1, 3, 224, 224) torch.onnx.export( model, dummy_input, "model.onnx", input_names=["input"], output_names=["output"], dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}} ) ``` - **使用TorchScript**:通过脚本化或追踪创建序列化模型: ```python scripted_model = torch.jit.script(model) scripted_model.save('model_scripted.pt') ``` ### 性能对比 | 方法 | 优点 | 缺点 | |------------|--------------------------|--------------------------| | 原生PyTorch | 灵活,支持动态图 | 依赖完整PyTorch环境 | | ONNX | 跨平台,支持多种推理引擎 | 转换过程可能损失部分信息 | | TorchScript | 独立运行,性能优化 | 部分Python特性不支持 | §§相关问题§§ 1. 如何将PyTorch模型转换为ONNX格式? 2. PyTorch模型加载时出现键不匹配错误如何解决? 3. 如何使用TorchScript优化模型推理性能? </think> # 使用PyTorch加载.pth模型文件进行图像分类预测 下面我将详细介绍如何使用PyTorch加载.pth模型文件对实际图像进行分类预测,包含完整的代码实现和关键步骤说明。 ## 完整实现流程 ### 1. 加载预训练模型 首先需要加载预训练的.pth模型文件,关键是确保模型结构与训练时完全一致: ```python import torch import torchvision.transforms as transforms from PIL import Image import matplotlib.pyplot as plt # 定义与训练时相同的模型结构 class SimpleCNN(torch.nn.Module): def __init__(self, num_classes=10): super(SimpleCNN, self).__init__() self.conv1 = torch.nn.Conv2d(3, 16, kernel_size=3, padding=1) self.relu1 = torch.nn.ReLU() self.pool1 = torch.nn.MaxPool2d(kernel_size=2, stride=2) self.conv2 = torch.nn.Conv2d(16, 32, kernel_size=3, padding=1) self.relu2 = torch.nn.ReLU() self.pool2 = torch.nn.MaxPool2d(kernel_size=2, stride=2) self.fc1 = torch.nn.Linear(32 * 56 * 56, 256) # 假设输入为224x224 self.relu3 = torch.nn.ReLU() self.fc2 = torch.nn.Linear(256, num_classes) def forward(self, x): x = self.pool1(self.relu1(self.conv1(x))) x = self.pool2(self.relu2(self.conv2(x))) x = x.view(x.size(0), -1) # 展平 x = self.relu3(self.fc1(x)) x = self.fc2(x) return x # 创建模型实例加载预训练权重 model = SimpleCNN(num_classes=10) # 类别数需与训练时一致 model.load_state_dict(torch.load('model.pth', map_location=torch.device('cpu'))) model.eval() # 设置为评估模式(禁用Dropout等) ``` ### 2. 图像预处理 对输入图像进行与训练时相同的预处理操作: ```python def preprocess_image(image_path): # 定义预处理转换(需与训练时一致) transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整大小 transforms.ToTensor(), # 转换为张量 transforms.Normalize( # 标准化(使用ImageNet参数) mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) ]) # 加载图像 image = Image.open(image_path).convert('RGB') # 应用预处理添加批次维度 input_tensor = transform(image) input_batch = input_tensor.unsqueeze(0) # 添加批次维度 [N, C, H, W] # 可视化预处理后的图像 plt.figure(figsize=(8, 6)) plt.imshow(input_tensor.permute(1, 2, 0)) # 转换为[H, W, C]格式 plt.title('预处理后的图像') plt.axis('off') plt.show() return input_batch ``` ### 3. 执行预测 使用模型进行预测解释结果: ```python def predict(model, input_batch): with torch.no_grad(): # 禁用梯度计算 output = model(input_batch) # 应用softmax获取概率 probabilities = torch.nn.functional.softmax(output[0], dim=0) # 获取预测结果 predicted_idx = torch.argmax(probabilities).item() confidence = probabilities[predicted_idx].item() return predicted_idx, confidence, probabilities # 使用示例 if __name__ == "__main__": image_path = "test_image.jpg" # 预处理图像 input_batch = preprocess_image(image_path) # 执行预测 predicted_idx, confidence, probs = predict(model, input_batch) # 类别标签(根据训练数据集定义) class_labels = ['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车'] # 输出结果 print(f"预测结果: {class_labels[predicted_idx]} (置信度: {confidence:.2%})") print("\n各类别概率:") for i, prob in enumerate(probs): print(f"{class_labels[i]}: {prob.item():.4f}") ``` ## 关键注意事项 ### 1. 模型结构一致性 加载.pth文件时,**模型结构必须与训练时完全一致**。如果模型定义发生变化,会导致加载失败: ```python # 常见错误:训练后修改了模型结构 class ModifiedCNN(SimpleCNN): # 添加了新层 def __init__(self): super().__init__() self.new_layer = torch.nn.Linear(10, 5) # 添加了新层 model = ModifiedCNN() model.load_state_dict(torch.load('model.pth')) # 会报错:键不匹配 ``` ### 2. 设备兼容性 如果训练使用GPU而预测使用CPU,需要指定`map_location`: ```python # 从GPU训练转换为CPU预测 model.load_state_dict(torch.load('model.pth', map_location=torch.device('cpu'))) ``` ### 3. 预处理一致性 **预处理操作必须与训练时完全相同**,特别是标准化参数: ```python # 错误示例:使用了不同的标准化参数 wrong_transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) # 错误参数 ]) ``` ### 4. 模型模式设置 预测前必须调用`model.eval()`: - 禁用Dropout层 - 固定BatchNorm层的统计量 - 确保一致的预测结果 ## 模型部署优化 ### 1. 转换为ONNX格式(实现跨平台部署) ```python # 导出为ONNX格式 dummy_input = torch.randn(1, 3, 224, 224) # 与模型输入尺寸一致 torch.onnx.export( model, dummy_input, "model.onnx", input_names=["input"], output_names=["output"], dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}} ) ``` ### 2. 使用TorchScript序列化 ```python # 脚本化模型 scripted_model = torch.jit.script(model) scripted_model.save("model_scripted.pt") # 加载和使用 loaded_model = torch.jit.load("model_scripted.pt") loaded_model.eval() ``` ### 3. 性能优化技巧 ```python # 半精度推理(减少内存使用,加速计算) model.half() # 转换为半精度 input_batch = input_batch.half() # 使用PyTorch的JIT编译器优化 with torch.jit.optimized_execution(True): output = model(input_batch) ``` ## 常见问题解决 ### 1. 键不匹配错误 当模型结构变化时会出现此错误,解决方案: ```python # 部分加载(忽略不匹配的键) pretrained_dict = torch.load('model.pth') model_dict = model.state_dict() # 筛选出匹配的键 pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict} model_dict.update(pretrained_dict) model.load_state_dict(model_dict) ``` ### 2. 输入尺寸不匹配 确保输入图像尺寸与训练时一致: ```python # 动态调整预处理 def adaptive_preprocess(image_path, target_size=(224, 224)): img = Image.open(image_path) # 保持宽高比的调整 img.thumbnail((target_size[0]*2, target_size[1]*2), Image.LANCZOS) # 中心裁剪 left = (img.width - target_size[0])/2 top = (img.height - target_size[1])/2 right = (img.width + target_size[0])/2 bottom = (img.height + target_size[1])/2 img = img.crop((left, top, right, bottom)) # 剩余预处理... ``` ### 3. 类别标签映射 确保使用与训练时相同的类别顺序: ```python # 从训练数据集中获取真实类别标签 from torchvision.datasets import ImageFolder train_dataset = ImageFolder('train_data/') class_labels = train_dataset.classes # ['cat', 'dog', ...] ``` ## 完整应用示例(Flask API) ```python from flask import Flask, request, jsonify import io app = Flask(__name__) model = SimpleCNN() model.load_state_dict(torch.load('model.pth')) model.eval() @app.route('/predict', methods=['POST']) def predict(): if 'file' not in request.files: return jsonify({'error': '未提供图像文件'}), 400 file = request.files['file'].read() image = Image.open(io.BytesIO(file)).convert('RGB') # 预处理 transform = transforms.Compose([...]) # 与训练时相同 input_tensor = transform(image).unsqueeze(0) # 预测 with torch.no_grad(): output = model(input_tensor) probs = torch.nn.functional.softmax(output[0], dim=0) # 返回结果 results = { 'predicted_class': int(torch.argmax(probs)), 'confidence': float(probs.max()), 'probabilities': probs.tolist() } return jsonify(results) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` 通过以上步骤,您可以成功加载.pth模型文件对实际图像进行分类预测。关键是要确保模型结构、预处理操作与训练时完全一致,正确处理不同的部署场景。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值