导入xgboost的pickle文件时报错:xgboost.core.XGBoostError

导入训练好的xgboost的pickle文件时经常出现以下错误:

xgboost.core.XGBoostError: [20:26:28] /Users/runner/work/xgboost/xgboost/python-package/build/temp.macosx-10.9-x86_64-cpython-38/xgboost/src/learner.cc:1222: Check failed: header == serialisation_header_: 
  If you are loading a serialized model (like pickle in Python, RDS in R) generated by
  older XGBoost, please export the model by calling `Booster.save_model` from that version
  first, then load it back in current version. See:

    https://xgboost.readthedocs.io/en/latest/tutorials/saving_model.html

  for more details about differences between saving model and serializing.

Stack trace:
  [bt] (0) 1   libxgboost.dylib                    0x000000011bc736d5 dmlc::LogMessageFatal::~LogMessageFatal() + 117
  [bt] (1) 2   libxgboost.dylib                    0x000000011bd99427 xgboost::LearnerIO::Load(dmlc::Stream*) + 2599
  [bt] (2) 3   libxgboost.dylib                    0x000000011bc962e2 XGBoosterUnserializeFromBuffer + 146
  [bt] (3) 4   libffi.8.dylib                      0x0000000105468972 ffi_call_unix64 + 82
  [bt] (4) 5   ???                                 0x00007ff7bb473540 0x0 + 140701975655744

问题分析:

        这个问题通常是训练xgboost模型,存储模型pickle文件时的xgboost版本与目前读取使用pickle文件的xgboost版本不一致导致的。

解决办法:

1、一般想到的解决办法时,重新安装当前使用pickle文件的xgboost版本,使其与训练模型时的版本一致,但进场会出现以下问题:

重新安装当前的xgboost的版本可能会导致一系列附属包的安装问题

2、还可以尝试解决办法

将老版本xgboost的pickle文件保存为.bin文件形式,如下:

# 当前环境为老版本Python环境
import xgboost as xgb
import pickle
#利用booster升级模型版本 --使用架构升级中的xgboost版本升级模型文件
booster = xgb.Booster()
path00 = 'xxxxx/'
booster.load_model(path00+'xgboost_model.bin')

在新版本xgboost环境中导入.bin文件:

import xgboost as xgb
import pickle
#利用booster升级模型版本 --使用架构升级中的xgboost版本升级模型文件
booster = xgb.Booster()
path00 = 'xxxxxx/'
booster.load_model(path00+'xgboost_model.bin')
#加载模型
ret_path ='xxxxxxx/'
pickle.dump(booster,open(ret_path+"xgboost_model.pickle","wb"))

### 解决方案 在Python中,`_pickle.PicklingError: Can't pickle <class>` 错误通常发生在尝试序列化某些对象。此错误表明该类未实现可被 `pickle` 序列化的特性[^1]。 #### 原因分析 当一个类的对象不可被序列化,可能的原因包括但不限于以下几点: - 类定义位于动态创建的函数或方法内部。 - 类依赖于外部资源(如文件句柄、网络连接等),这些资源本身无法被序列化。 - 类中存在对 lambda 表达式的引用或其他匿名函数,而这些也无法被序列化。 #### 实现可序列化的类设计 为了使自定义类能够支持序列化操作,可以遵循以下几个原则: 1. **确保类及其成员均可被序列化** 如果类中的属性是非标准数据类型或者复杂结构,则需要确认它们也实现了序列化接口。如果某个属性不需要保存到磁盘上,在初始化阶段可以通过设置默认值来跳过它[^2]。 2. **重写 __getstate__ 和 __setstate__ 方法** 对于复杂的类实例,可以通过重新定义这两个特殊的方法来自定义其状态管理逻辑。这允许开发者控制哪些部分会被实际存储以及如何恢复那些信息[^3]。 ```python import pickle class MyClass: def __init__(self, name, resource=None): self.name = name # 'resource' 是一个假设的例子,表示某种不可串行化的资源 self.resource = resource def __getstate__(self): state = self.__dict__.copy() del state['resource'] # 删除不能被序列化的字段 return state def __setstate__(self, state): self.__dict__.update(state) self.resource = None # 初始化为None 或者其他安全值 obj = MyClass("Test", open('file.txt', 'r')) serialized_data = pickle.dumps(obj) # 正常工作不会抛出异常 deserialized_obj = pickle.loads(serialized_data) print(deserialized_obj.name) # 输出 Test ``` #### 使用 dill 替代 standard library 的 pickle即使调整了类的设计仍然遇到困难,这可以选择第三方库 `dill` ,它可以处理更广泛的 Python 数据类型和构造形式[^4]。 ```python import dill as pickle def my_function(): pass lambda_func = lambda x: x * 2 complex_object = {"func": my_function, "lambda": lambda_func} with open('data.pkl', 'wb') as f: pickle.dump(complex_object, f) # 成功完成dump过程 with open('data.pkl', 'rb') as f: loaded_complex_object = pickle.load(f) print(loaded_complex_object["lambda"](5)) # 结果应为10 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值