sklearn2pmml导出PyCaret的CatBoost模型报非BaseEstimator实例错误
问题成因
- PyCaret模型封装逻辑存在模型间差异:XGBoost、LightGBM经过
create_model/tune_model/finalize_model全流程处理后,返回的对象本身继承scikit-learn的BaseEstimator基类,符合sklearn2pmml的入参校验规则;CatBoost经过调参、最终化步骤后,外层会包裹PyCaret自定义的包装对象,该对象未继承BaseEstimator,直接传入make_pmml_pipeline就会触发类型报错。 - 原代码存在变量名笔误:上一行定义的流水线变量名为
model_pipeline,最后导出时传入的是未定义的model_pipeline_pm,即使类型校验通过也会触发名称错误。 - 依赖版本不匹配会引发后续异常:若
sklearn2pmml版本低于0.86、catboost版本低于1.0,或是scikit-learn版本高于1.2.2,即使传入合规的BaseEstimator实例,也可能出现PMML转换失败的问题。
解决方法
按以下步骤操作即可正常导出CatBoost模型为PMML格式:
- 修正依赖版本:先安装匹配版本的依赖包,执行命令:
pip install scikit-learn==1.2.2 sklearn2pmml==0.86.1 catboost==1.2.2 - 手动组装PMML流水线:不要直接用
make_pmml_pipeline包装PyCaret返回的CatBoost结果,先拆分PyCaret输出流水线中的预处理步骤和原生CatBoost模型,再手动构建PMML可识别的流水线,保证预处理逻辑和模型逻辑同时被导出,修正后的完整代码如下:from sklearn2pmml.pipeline import PMMLPipeline from sklearn2pmml import sklearn2pmml from pycaret.regression import setup, tune_model, finalize_model, create_model # 原有建模逻辑保持不变 clf = setup( data=df, target='target_Var', train_size=0.8, fold_shuffle=True, fold=5, fold_strategy="groupkfold", fold_groups="id", html=False, silent=True, session_id=1, n_jobs=-1 ) model = create_model('catboost') tuned_model = tune_model(model, fold=5) final_model = finalize_model(tuned_model) # 遍历PyCaret流水线的所有步骤,拆分预处理与原生模型 pmml_steps = [] for step_name, step_obj in final_model.steps: if step_name == "trained_model": # 提取原生CatBoost实例,该实例继承BaseEstimator可被sklearn2pmml识别 pmml_steps.append(("catboost_regressor", step_obj)) else: # 保留全部预处理步骤,避免导出的PMML无法处理原始输入数据 pmml_steps.append((step_name, step_obj)) # 构建PMML流水线并导出 pmml_pipeline = PMMLPipeline(pmml_steps) sklearn2pmml(pmml_pipeline, model_path) - 备选导出方案(适配极端兼容场景):如果手动组装流水线仍存在转换问题,可提取原生CatBoost模型后直接调用CatBoost官方的PMML导出接口,避开sklearn2pmml的类型校验:
该方案需要手动同步预处理逻辑,否则导出的PMML无法直接处理原始格式的输入数据,仅推荐在sklearn2pmml完全无法适配的场景使用:
# 提取原生CatBoost模型后直接导出 native_catboost = final_model.named_steps["trained_model"] native_catboost.save_model(model_path, format="pmml")
内容的提问来源于stack exchange,提问作者Forge
相关产品推荐
相关产品推荐

