使用公开仓库代码加载自定义文件时遇到PyTorch反序列化(Unpickling)错误
Fixing
_pickle.UnpicklingError (Persistent ID Instruction Issue) with Custom .pkl Files 我前阵子在跑一段模型性能评估代码时,刚好碰到和你一模一样的问题——用仓库自带的示例.pkl文件能正常运行,自己按照文档生成的自定义文件就直接炸出这个pickle错误。先把相关的代码和报错信息贴出来,方便大家对照:
我运行的代码片段:
split = 'CS' pkl_path = './data.pkl' if split == 'CS': gt_file = './data/smarthome_CS_51.json' classes = 51 pkl = open(pkl_path, 'rb') logits = pickle.load(pkl, encoding='latin1')
触发的错误日志:
Traceback (most recent call last): File "test-with-eval.py", line 484, in <module> logits = pickle.load(pkl, encoding='latin1') _pickle.UnpicklingError: A load persistent id instruction was encountered, but no persistent_load function was specified.
问题根源:
这个错误的核心原因是:你生成自定义.pkl文件时用了pickle的持久化ID(Persistent ID)机制,但在反序列化的代码里没有提供对应的处理函数。仓库的示例文件应该是用普通的pickle序列化逻辑生成的,不需要额外处理;而你生成文件时,大概率是序列化了带有自定义__reduce__方法的对象(比如某些深度学习框架的张量、自定义类实例),这类对象在序列化时会返回persistent ID,反序列化时就需要对应的persistent_load函数来解析。
两种可行的解决办法:
1. 修改生成.pkl的代码,避开persistent ID
检查你生成data.pkl的代码,看看是不是直接序列化了框架的自定义对象(比如PyTorch Tensor、TensorFlow Tensor)。如果是,改成序列化原生Python类型或者numpy数组就可以解决问题:
# 举个例子,如果你之前是直接存张量: # pickle.dump(model_output_tensor, open(pkl_path, 'wb')) # 改成存numpy数组: pickle.dump(model_output_tensor.numpy(), open(pkl_path, 'wb'))
这样生成的.pkl文件就不会包含persistent ID,用原代码加载就没问题了。
2. 在反序列化时添加persistent_load处理函数
如果没办法修改生成代码,那可以在调用pickle.load时,通过persistent_load参数指定解析函数。这里需要你清楚生成文件时persistent ID对应的是什么对象,举个简单的例子:
def persistent_load(pid): # 根据你的实际persistent ID类型编写逻辑,比如pid是类名/对象标识 if isinstance(pid, str) and pid == "MyCustomModelOutput": # 返回对应的类或者处理逻辑 return MyCustomModelOutput # 未知ID直接抛出错误,方便排查 raise pickle.UnpicklingError(f"Unrecognized persistent ID: {pid}") # 修改加载代码 with open(pkl_path, 'rb') as pkl: logits = pickle.load(pkl, encoding='latin1', persistent_load=persistent_load)
另外,也可以检查下生成和加载时的pickle版本是否一致,版本不兼容也可能导致这类奇怪的反序列化错误。
内容的提问来源于stack exchange,提问作者Megan Darcy
相关产品推荐
相关产品推荐

