apache-spark - 我可以在 PMML(从 Spark 导出)中使用没有 One-Hot-Encoding 的 StringIndexer 吗?
问题描述
我正在尝试采用功能齐全的 SparkML 管道(出于兼容性原因,Scala、Spark 2.1.1)并将其转换为 PMML 以实现互操作性和存储目的。
目前,管道具有以下形式:Array(StringIndexer,StringIndexer,VectorAssembler,VectorIndexer)。我已经尝试过标准的 org.jpmml.sparkml.PMMLBuilder,它在我已经为数据库中的字符串编制索引的情况下工作得非常好。(我知道这些列中有多少不同的字符串,我完全确定它们会保持分类。)我计划在决策树和其他一些基于树的方法中使用它们,SparkML 有对树中的分类变量进行可爱的处理,这使得 one-hot-encoding 不太理想。
val strCols = Array("stringCol1","stringCol2")
val strIndexers = strCols.map(c => new StringIndexer().setInputCol(c).setOutputCol(c+"_Indexed"))
val collist = df.columns.diff(strCols) ++ strCols.map(c => c+"_Indexed")
val vectorAssembler = new VectorAssembler()
.setInputCols(collist)
.setOutputCol("rawFeatures")
val vectorIndexer = new VectorIndexer().setInputCol("rawFeatures").setOutputCol("features").setMaxCategories(35)
val pipeintro = new Pipeline().setStages(strIndexers :+ vectorAssembler :+ vectorIndexer)
val pipeIntro = pipeintro.fit(df)
val pmmlBuilder = new org.jpmml.sparkml.PMMLBuilder(df.schema, pipeIntro).buildFile(new File("out.pmml"))
我希望代码完成运行并输出适当的 PMML,但我得到的是:
java.lang.IllegalArgumentException: Field stringCol1 has valid values [MT, IP, OB, GA, ED, OP]
at org.jpmml.converter.PMMLEncoder.toCategorical(PMMLEncoder.java:209)
at org.jpmml.sparkml.feature.VectorIndexerModelConverter.encodeFeatures(VectorIndexerModelConverter.java:80)
at org.jpmml.sparkml.FeatureConverter.registerFeatures(FeatureConverter.java:47)
at org.jpmml.sparkml.PMMLBuilder.build(PMMLBuilder.java:114)
at org.jpmml.sparkml.PMMLBuilder.buildFile(PMMLBuilder.java:292)
我检查了空值;没有,也没有其他无效的值。有一些迹象表明,StringIndexers 在放入 VectorAssembler 之前应该是单热编码的,但这对于这个特定的管道来说不是最理想的,因为它旨在馈送到 SparkML 定义的树中,它可以很好地处理多值分类列. 该指南是否被硬编码到 PMML 或 Spark-PMML 编码器中?我还缺少其他一些错误吗?
解决方案
这个特殊的例外是关于冲突的“stringCol1”定义 - 它的值空间已由StringIndexer
([MT, IP, OB, GA, ED, OP]) 定义,现在VectorIndexer
正试图用不同的值空间重新定义它。其中一项尝试是错误的。
可能是 JPMML-SparkML 库或您的脚本的错误。也许StringIndexerModel
根本不应该是 VectorIndexed 的输出?
推荐阅读
- reactjs - 如何从后端 Django 进行重定向
- python - 如何在 Python Tkinter 中使用多个窗口
- python - 如何创建一个可以在一对多关系中仅添加或删除一个条目的 API 调用
- angular - 如何通过 WAN 或 LAN 访问 Angular 客户端
- android - exec 类型的 android gradle 任务执行失败
- javascript - 如何从另一个组件调用和使用我的 useState
- python - 请求的 MovieWriter (ffmpeg) 不可用
- java - 如何将数据从数据库设置到组合框?
- microsoft-dynamics - Dynamics 365 中队列中的事件生命周期
- mysql - 如何在云上连接 Spring Cloud Function 和 MySQL