You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决pickle序列化含自定义函数的Python对象跨环境加载报错问题

解决方案

方案1:使用dill替代pickle完成序列化(最快适配现有代码)

dill扩展了pickle的序列化能力,支持直接序列化函数实现、闭包环境,不需要改动原有函数定义:
首先安装dill:pip install dill
保存端代码:

import shap, dill
import tensorflow as tf

model = ... # 你的tensorflow模型
def f(X):
    ...
    return model.predict(...).flatten()
explainer = shap.KernelExplainer(f, X.iloc[:50, :])

# 保存逻辑
with open(f"/tmp/{file}.pkl", 'wb') as fil:
    dill.dump(explainer, fil)

加载端代码:

import dill
with open(f"/tmp/{file}.pkl", 'rb') as fil:
    explainer = dill.load(fil)

注意:保存和加载环境的dill、shap、tensorflow版本要尽可能保持一致,避免版本兼容问题

方案2:将自定义函数封装为可调用类(兼容性最好,原生pickle支持)

pickle可以正常序列化自定义类的实例,把函数逻辑和依赖的模型封装到类中即可:
保存端代码:

import shap, pickle
import tensorflow as tf

class ShapPredictWrapper:
    def __init__(self, model):
        self.model = model
    def __call__(self, X):
        # 把原f函数的逻辑写在这里
        return self.model.predict(...).flatten()

model = ... # 你的tensorflow模型
f = ShapPredictWrapper(model)
explainer = shap.KernelExplainer(f, X.iloc[:50, :])

with open(f"/tmp/{file}.pkl", 'wb') as fil:
    pickle.dump(explainer, fil)

加载端代码:必须在加载前先定义完全相同的ShapPredictWrapper类,或者将该类放到公共模块中,两端都从公共模块导入

import pickle
# 先导入/定义ShapPredictWrapper类,要和保存端完全一致
from xxx import ShapPredictWrapper

with open(f"/tmp/{file}.pkl", 'rb') as fil:
    explainer = pickle.load(fil)

方案3:将自定义函数放到公共模块中

如果你的保存和加载脚本在同一个项目中,可以把f函数和模型加载逻辑都放到单独的公共模块比如shap_utils.py里,保存和加载时都从shap_utils导入f,不要把f定义在if __name__ == '__main__'包裹的代码块中,pickle无法序列化主脚本内的顶层函数。

术语表述优化建议
  • 描述问题时可以明确标注「序列化/反序列化」「跨进程/跨脚本加载」「自定义顶层函数/闭包函数」这些关键词,更容易匹配到对应解决方案
  • 报错信息可以贴完整的Traceback,而不是仅贴最终报错提示,方便定位是序列化阶段出错还是反序列化阶段出错
  • 可以补充说明保存和加载两端的运行环境差异,比如是否是同一个项目、依赖版本是否一致、函数定义是否在两端都存在

内容的提问来源于stack exchange,提问作者Rory Donovan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:36:06