一、报错详情
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 numpy.core.multiarray._reconstruct was not an allowed global by default. Please use `torch.serialization.add_safe_globals([numpy.core.multiarray._reconstruct])` or the `torch.serialization.safe_globals([numpy.core.multiarray._reconstruct])` context manager to allowlist this global if you trust this class/function.
报错如图:
二、问题分析
错误信息非常明确地指向了PyTorch 2.6版本中torch.load
函数默认行为的变化(weights_only
参数从False
变为True
),导致在加载包含特定全局对象(这里是numpy.core.multiarray._reconstruct
)的模型文件时失败。原因如下:
- PyTorch安全性升级:从PyTorch 2.6开始,
torch.load()
函数默认只允许加载包含张量、数字、字符串等简单类型的文件,以防止潜在的恶意代码执行。 - numpy对象问题:模型文件中包含了
numpy.core.multiarray._reconstruct
对象,这是NumPy数组重构所需的函数。当weights_only=True
时,PyTorch不允许加载这类非默认安全类型的对象。 - 项目兼容性:使用的项目可能是在旧版PyTorch下开发的,所以没有考虑到这一安全性变更。
三、解决方法
方案一:添加安全全局变量(推荐,相对安全)
此方法将所需的NumPy函数添加到PyTorch的安全全局变量列表中,既能维持安全性又能解决兼容性问题。
- 找到项目的主入口文件(可能是
visual_interface.py
)。 - 在文件开头的导入部分后,添加以下代码
import torch
from numpy.core.multiarray import _reconstruct
# 将numpy的_reconstruct函数添加到安全全局变量中
torch.serialization.add_safe_globals([_reconstruct])
保存文件并重新运行程序。
方案二:修改torch.load参数(快速但需注意安全)
此方法直接修改模型加载代码,允许加载任意对象,但需要你确保模型来源可靠。
- 找到项目中调用
torch.load
的文件(错误提示中是:项目\models\experimental.py
第xx行左右)。 - 找到类似这样的代码行:
model.append(torch.load(w, map_location=map_location)['model'].float().fuse().eval())
-
将其修改为:
model.append(torch.load(w, map_location=map_location, weights_only=False)['model'].float().fuse().eval())
-
保存文件并重新运行程序。
方案三:创建补丁文件(适合多次使用)
如果你需要在多个项目中解决此问题,可以创建一个补丁文件:
- 在项目目录中创建一个新文件(如
patch_weights_load.py
):import torch from numpy.core.multiarray import _reconstruct def patch_weights_load(): """Patch PyTorch to allow loading numpy objects safely""" torch.serialization.add_safe_globals([_reconstruct]) print("Successfully patched PyTorch weights loading for numpy objects") # 自动执行补丁 patch_weights_load()
-
在你的主程序文件最开头添加:
import patch_weights_load
四、解决方案对比表
方案 | 安全性 | 易用性 | 适用场景 | 注意事项 |
---|---|---|---|---|
添加安全全局变量 | 高 | 中等 | 大多数情况,特别是生产环境 | 需要找到合适的添加位置 |
修改torch.load参数 | 中(需信任来源) | 简单 | 快速测试,来源可信的模型 | 仅对信任的模型文件使用 |
创建补丁文件 | 高 | 中等 | 多项目环境,需要重复使用 | 需要额外维护一个文件 |
提醒:如果选择方案二(设置weights_only=False
),请确保你的模型文件来自可信来源,因为这可能执行文件中包含的任意代码。