【pytorch】模型训练和推理使用的设备不一致导致的问题

当使用PyTorch在不同GPU间迁移已训练模型时,可能会遇到CUDA内存溢出错误。本文详细解释了错误产生的原因,即模型加载时默认指向被占用的显卡,以及如何通过设置map_location参数来解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

前几天使用0号显卡训练了模型,今天想要推理的时候,0卡被占用,所以选择使用1卡进行推理。
但是推理的时候却报错:RuntimeError: CUDA error: out of memory

原因

所有先前保存的模块,不论其设备,首先加载到CPU上,然后移动到之前保存它们的设备上(也就是0号显卡)。因为0号显卡被占用,所以显示out of memory

解决方法

load模型的时候,添加map_location参数

torch.load(path_file, map_location='cuda:1')

参考资料

  1. https://github.com/apachecn/pytorch-doc-zh/blob/master/docs/1.0/jit.md
  2. pytorch在gpu训练加载模型,训练与测试在不同机器上遇到的问题总结
  3. pytorch将cpu训练好的模型参数load到gpu上,或者gpu->cpu上
<think>好的,我现在需要解决用户的问题,即如何在PyTorch中加载预训练模型权重并用于推理。根据用户提供的引用内容,我需要综合这些信息来构建一个清晰的步骤指南。 首先,用户提到的引用[1]提到使用torch.load(PATH)加载模型,并调用model.eval()进入推理模式。这应该是基础步骤。过,用户可能需要注意模型结构的匹配问题,如果预训练模型的架构与当前模型完全一致,可能需要调整加载方式。 引用[2][3]讨论了迁移学习中的微调,特别是如何加载部分参数并冻结某些层。虽然用户主要关注推理,但了解如何正确加载权重是关键。例如,引用[3]中的代码展示了如何处理模型参数匹配的情况,比如忽略分类层或处理BN层的额外参数。这可能对用户有帮助,尤其是在模型结构有变化。 引用[4]提到的问题是关于加载相同结构部分但输出一致的情况,可能是因为某些层未被正确固定。虽然用户的问题是关于推理,但正确加载权重并确保模型状态正确(如eval模式)可能影响输出结果,这点需要注意。 接下来,我需要将这些信息整合成一个步骤化的教程。首先加载模型结构,然后加载权重,处理可能的键匹配问题,设置模型为评估模式,并进行前向传播。同,需要提到常见的错误,如忘记调用eval()导致dropout或BN层行为一致,或者结构匹配的解决方法。 可能还需要考虑使用torch.no_grad()来减少内存消耗,并加快计算速度。此外,示例代码将帮助用户更好地理解流程,比如加载预训练的ResNet并进行推理。 最后,根据用户的要求,生成相关问题,这些问题应围绕加载模型同情况、处理结构差异、性能优化等。需要确保问题覆盖用户可能遇到的后续疑问。</think>### PyTorch加载预训练模型权重进行推理的完整教程 #### 一、基础加载流程(结构完全匹配) 1. **定义模型结构** 确保模型类定义与预训练权重完全一致,包括层名称、参数顺序、网络分支结构。 2. **加载权重与模式切换** ```python import torch from models import YourModelClass # 替换为实际模型定义 # 初始化模型 model = YourModelClass() # 加载预训练权重(推荐使用map_location参数确保设备兼容) checkpoint = torch.load('pretrained.pth', map_location='cpu') model.load_state_dict(checkpoint['model_state_dict']) # 根据实际键名调整 # 切换推理模式(关键步骤) model.eval() ``` #### 二、常见场景解决方案 ▌**场景1:部分结构匹配**(参考引用[3][^3]) ```python # 步骤1:打印当前模型与预训练模型的键名差异 pretrained_dict = torch.load('vgg16_bn.pth') model_dict = model.state_dict() # 步骤2:筛选可加载参数(忽略无关层) filtered_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict and v.shape == model_dict[k].shape} # 步骤3:特殊处理BN层参数(处理num_batches_tracked字段) if 'num_batches_tracked' in model_dict.keys(): filtered_dict = {k: v for k, v in filtered_dict.items() if 'num_batches_tracked' not in k} # 步骤4:加载并设置严格模式 model.load_state_dict(filtered_dict, strict=False) ``` ▌**场景2:仅需加载部分组件**(参考引用[4][^4]) ```python # 针对backbone模块加载 backbone_dict = {k.replace('backbone.', ''): v for k, v in checkpoint.items() if k.startswith('backbone')} model.backbone.load_state_dict(backbone_dict) # 冻结指定层参数 for param in model.backbone.parameters(): param.requires_grad_(False) ``` #### 三、执行推理的标准流程 ```python # 数据预处理规范 from torchvision import transforms preprocess = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 推理过程封装 with torch.no_grad(): # 禁用梯度计算 input_tensor = preprocess(raw_image).unsqueeze(0) if torch.cuda.is_available(): input_tensor = input_tensor.to('cuda') model.to('cuda') outputs = model(input_tensor) probabilities = torch.nn.functional.softmax(outputs[0], dim=0) ``` #### 四、关键注意事项 1. **模式区别** `model.eval()`会关闭dropout层BN层的训练模式统计量计算,这对输出一致性至关重要[^1] 2. **设备管理** 通过`map_location`参数实现跨设备加载: ```python # GPU加载CPU训练模型 torch.load('cpu_model.pth', map_location=torch.device('cuda:0')) ``` 3. **版本兼容** 当出现`Unexpected key(s) in state_dict`警告,可使用`strict=False`参数跳过匹配层(需验证关键层是否加载成功) #### 五、完整示例(以ResNet50为例) ```python import torchvision.models as models # 初始化模型 model = models.resnet50(pretrained=False) # 加载自定义权重 checkpoint = torch.load('custom_resnet50.pth') model.load_state_dict(checkpoint) # 准备输入 model.eval() input_tensor = torch.randn(1, 3, 224, 224) # 执行推理 with torch.no_grad(): output = model(input_tensor) print(f"Output shape: {output.shape}") ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值