PySpark转PMML失败求助:无法用转换后数据生成PMML文件
问题分析与解决方案
核心问题
第一种方法失败的根本原因是:你把数据转换(StringIndexer)和模型训练拆成了两个独立的Pipeline,最终的dts_model只包含RFormula和决策树的逻辑,丢失了前面StringIndexer的转换元数据。而indexed_data本身带有StringIndexer生成的列元数据,pyspark2pmml在结合这个DataFrame和不完整的Model时,无法正确对齐数据处理流程,最终触发报错。
CSV导出再导入的方法能成功,是因为导出再读入后的test_df是无额外元数据的纯基础类型DataFrame,列类型都是普通数值/字符串,和RFormula训练时的预期完全匹配,pyspark2pmml可以正常解析整个流程。
正确实现方式
你需要把StringIndexer、RFormula、决策树整合到同一个Pipeline中,让从数据预处理到模型训练的完整流程被记录在PipelineModel里,这样pyspark2pmml就能正确生成包含所有预处理逻辑的PMML文件。
修改后的代码如下:
... (previous steps) filtered_data = filtered_data.filter(data['year'] <= '2020') cat_cols = ['CYC_CLASS', 'CYC_DISCHPORT'] num_cols = ['weekofyear'] label_cols = 'dwell_time' # 直接处理原始分类列,生成索引后列 si = [StringIndexer(inputCol=d, outputCol=d + "_indexed", handleInvalid='keep') for d in cat_cols] # 特征列替换为索引后的分类列+数值列 feat_cols = [d + "_indexed" for d in cat_cols] + num_cols # 基于处理后的特征列定义RFormula formula = RFormula(formula = f"{label_cols} ~ {' + '.join(feat_cols)}") dt_clf = DecisionTreeClassifier(maxBins=10) # 整合所有步骤到同一个Pipeline full_pipeline = Pipeline(stages = si + [formula, dt_clf]) # 使用原始filtered_data训练完整Pipeline dts_model = full_pipeline.fit(filtered_data) # 生成PMML from pyspark2pmml import PMMLBuilder pmmlDTs = PMMLBuilder(spark, filtered_data, dts_model) pmmlDTs.buildFile("test_dtsi_22121230556.pmml")
关键差异说明
流程完整性
- 错误方法:数据转换和模型训练分离,Model不包含预处理逻辑,PMMLBuilder无法理解
indexed_data的列来源。 - 正确方法:整个流程从原始数据到模型训练都在一个Pipeline里,Model包含所有预处理+训练逻辑,PMMLBuilder可以完整解析并生成符合规范的PMML。
- 错误方法:数据转换和模型训练分离,Model不包含预处理逻辑,PMMLBuilder无法理解
元数据处理
indexed_data的列带有StringIndexer生成的元数据(比如标签到索引的映射),但单独训练的dts_model未关联这些元数据,导致PMMLBuilder解析时出现不匹配。- CSV导出再导入会丢失所有列元数据,变成纯基础类型,此时Model和DataFrame的元数据完全对齐,虽然能生成PMML,但会丢失预处理逻辑,实际部署使用时会出现数据不兼容问题。
内容的提问来源于stack exchange,提问作者fritzp
相关产品推荐
相关产品推荐

