跨系统使用mlr3prob的xgboost.cox模型预测时遇DMatrix初始化错误求助
解决mlr3中保存/加载xgboost.cox模型后预测报错的问题
问题现象
使用mlr3prob和mlr3extralearners训练surv.xgboost.cox模型,保存为RDS文件迁移到其他系统后,调用predict()或predict_newdata()时触发报错:
src/c_api/c_api.cc:675: DMatrix/Booster has not been initialized or has already been disposed.
即使手动替换加载的xgb.Booster对象,报错依然存在。
环境版本
- R版本:4.2.3
- 核心包版本:
- dplyr_1.1.4
- xgboost_1.7.7.1
- mlr3proba_0.6.9
- mlr3verse_0.3.0
- mlr3tuning_1.0.0
- paradox_1.0.1
- survival_3.7-0
- mlr3extralearners_1.0.0
- mlr3_0.22.1
复现代码
library(mlr3) library(mlr3proba) library(mlr3verse) library(mlr3extralearners) library(xgboost) library(dplyr) # 训练阶段 lung_filter = lung |> select(-sex,-ph.ecog) task = TaskSurv$new(id="lung",backend = lung_filter,time = "time",event = "status") learner = lrn("surv.xgboost.cox")$train(task) saveRDS(task,"task.rds") saveRDS(learner,"learner.rds") xgb.save(learner$model$model, "xgb.model") # 训练后本地预测正常 learner$predict_newdata(lung_filter,task) learner$predict(task) # 加载阶段(新环境/清空环境后) rm(list=ls()) lung_filter = lung |> select(-sex,-ph.ecog) task2 = readRDS("task.rds") learner2 = readRDS("learner.rds") # 查看加载后的模型状态,提示Handle无效 learner2$model$model # 手动加载xgb模型并替换 model = xgb.load("xgb.model") learner2$model$model = model # 尝试预测,触发报错 learner2$predict_newdata(lung_filter,task2) learner2$predict(task2)
解决方案
核心原因
xgboost的Booster对象依赖C后端的资源句柄,RDS序列化仅能保存对象表层信息,无法持久化底层C资源,导致加载后句柄无效。同时mlr3的surv.xgboost.cox learner会缓存训练时的dtrain(DMatrix对象),加载后该缓存已失效,预测时优先调用无效缓存触发报错。
方案1:正确的模型保存/加载流程
不要直接保存整个learner对象,而是拆分保存配置参数与训练好的Booster,在新环境重新初始化learner:
训练时保存内容
# 训练模型 learner = lrn("surv.xgboost.cox")$train(task) # 保存learner参数配置 saveRDS(learner$param_set$values, "xgb_cox_params.rds") # 保存xgb.Booster模型 xgb.save(learner$model$model, "xgb_cox_model.model") # 保存训练特征列名(确保新数据列一致) saveRDS(task$feature_names, "feature_names.rds")
新环境加载并预测
library(mlr3) library(mlr3proba) library(mlr3extralearners) library(xgboost) library(dplyr) # 加载配置与模型 params = readRDS("xgb_cox_params.rds") feature_names = readRDS("feature_names.rds") xgb_model = xgb.load("xgb_cox_model.model") # 初始化learner并设置参数 learner = lrn("surv.xgboost.cox", .params = params) # 构建mlr3要求的model结构 learner$model = list( model = xgb_model, task_feature_names = feature_names, target_names = c("time", "status") ) # 准备匹配格式的新数据 lung_filter = lung |> select(all_of(feature_names), time, status) task2 = TaskSurv$new(id="lung_pred", backend=lung_filter, time="time", event="status") # 执行预测 pred = learner$predict(task2) pred_newdata = learner$predict_newdata(lung_filter, task2)
方案2:临时修复已保存的learner
如果已保存了完整learner对象,可通过清空无效缓存解决:
learner2 = readRDS("learner.rds") xgb_model = xgb.load("xgb.model") # 清空缓存的无效DMatrix learner2$model$dtrain = NULL # 替换为有效Booster learner2$model$model = xgb_model # 执行预测 pred = learner2$predict(task2)
内容的提问来源于stack exchange,提问作者gen linlin
相关产品推荐
相关产品推荐

