Traceback (most recent call last): File "C:\Users\唐添美.DESKTOP-95B881R\Desktop\MNIST实现\test.py", line 38, in <module> mynet = torch.load('MNIST_4_acc_0.9692999720573425.pth', map_location=torch.device('cpu')) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\唐添美.DESKTOP-95B881R\.conda\envs\python高级应用\Lib\site-packages\torch\serialization.py", line 1524, in load raise pickle.UnpicklingError(_get_wo_message(str(e))) from None _pickle.UnpicklingError: Weights only load failed. This file can still be loaded, to do so you have two options, do those steps only if you trust the source of the checkpoint. (1) In PyTorch 2.6, we changed the default value of the `weights_only` argument in `torch.load` from `False` to `True`. Re-running `torch.load` with `weights_only` set to `False` will likely succeed, but it can result in arbitrary code execution. Do it only if you got the file from a trusted source. (2) Alternatively, to load with `weights_only=True` please check the recommended steps in the following error message. WeightsUnpickler error: Unsupported global: GLOBAL __main__.MyNet was not an allowed global by default. Please use `torch.serialization.add_safe_globals([__main__.MyNet])` or the `torch.serialization.safe_globals([__main__.MyNet])` context manager to allowlist this global if you trust this class/function. Check the documentation of torch.load to learn more about types accepted by default with weights_only https://pytorch.org/docs/stable/generated/torch.load.html.
时间: 2025-05-28 10:46:47 浏览: 15
### PyTorch 加载模型时出现 `UnpicklingError` 的原因分析
当使用 `torch.load()` 函数加载模型权重文件时,如果遇到 `UnpicklingError` 错误,通常是因为序列化和反序列化的环境不一致。具体来说,这可能是由于以下原因之一:
1. **模块路径问题**:保存模型的脚本中的类定义无法被当前运行环境中找到。
2. **Python 版本差异**:用于保存模型的 Python 版本与加载模型的版本不同。
3. **PyTorch 版本冲突**:保存模型使用的 PyTorch 版本与加载模型所用的版本存在兼容性问题。
以下是针对该问题的具体解决方案及其说明。
---
#### 方法一:设置 `weights_only=True`
通过将参数 `weights_only=True` 传递给 `torch.load()`,可以仅加载模型的状态字典而不尝试恢复完整的对象结构[^1]。这种方法适用于只需要加载权重而不需要重新构建原始模型的情况。
```python
state_dict = torch.load('model.pth', map_location=torch.device('cpu'), weights_only=True)
model.load_state_dict(state_dict)
```
此方法的优点在于它绕过了可能引发错误的对象重建过程,从而有效解决了因模块路径或类定义缺失而导致的问题。
---
#### 方法二:调整类定义的位置
如果需要完全还原模型实例而非仅仅加载其状态字典,则应确保保存模型时所依赖的类定义能够在加载端正确导入。例如,在训练阶段定义了一个名为 `MyNet` 的网络类并将其保存到磁盘中;那么在推理阶段也需提供相同的类定义以便成功完成 unpickling 过程[^2]。
假设原项目中有如下代码片段:
```python
class MyNet(nn.Module):
def __init__(self):
super(MyNet, self).__init__()
...
def forward(self, x):
...
net = MyNet()
torch.save(net.state_dict(), 'model.pth')
```
则应在测试程序里同样实现这个 `MyNet` 类型,并调用相应的方法来初始化以及填充已存储好的参数值:
```python
from my_module import MyNet # 假设 MyNet 定义在此处
model = MyNet()
model.load_state_dict(torch.load('model.pth'))
model.eval()
```
注意这里的关键点是要保证两个地方对于同一个神经网络架构描述的一致性和可访问性。
---
#### 方法三:利用自定义全局变量映射 (`add_safe_globals`)
某些情况下,即使提供了必要的类定义仍会遭遇失败情形——这是因为 pickle 协议内部维护了一份安全性的白名单机制,默认不允许执行未知来源的数据操作命令。此时可以通过扩展允许列表的方式解决问题[^3]。
虽然官方文档并未直接提及如何修改这些默认行为,但在实际应用过程中发现可通过向 `pickle.Unpickler.add_safeglobals()` 添加额外条目达到目的(尽管这种方式并不推荐作为常规手段)。下面展示一段伪代码示意这一思路的应用场景:
```python
import types
import sys
import dill as pkl # 使用更强大的dill库替代标准库pickle
def custom_loader(file_path):
class CustomUnpickler(pkl.Unpickler):
def find_class(self, module_name, name):
try:
result = super().find_class(module_name, name)
except Exception as e:
if (module_name == "__main__") and hasattr(sys.modules["__main__"], name):
return getattr(sys.modules["__main__"], name)
raise e from None
return result
with open(file_path, 'rb') as f:
model = CustomUnpickler(f).load()
return model
loaded_model = custom_loader('model.pkl')
```
上述例子展示了如何创建一个继承自 Pickle 的子类,并重写其中部分逻辑使得能够动态适应更多复杂情况下的需求。
---
#### 总结
综上所述,处理 `UnpicklingError` 可采用三种主要策略:一是简化任务范围至单纯读取数值数据层面;二是严格匹配前后两端涉及的所有组件要素关系链路;三是探索更为灵活开放的技术路线以突破传统框架局限。每种方式各有优劣权衡之处,最终选择取决于特定应用场景的实际约束条件和个人偏好倾向等因素综合考量决定。
---
阅读全文
相关推荐


















