我找不到如何使用Spark ML Pipeline来分类一组新的实例(带有未知标签)。 我找到的所有示例都基于具有已知标签的测试集(仅用于评估分类的性能)。
我有以下管道:
StringIndexer indexer = new StringIndexer().setInputCol("category").setOutputCol("categoryIndex");
Tokenizer tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words");
HashingTF hashingTF = new HashingTF().setNumFeatures(NUM_FEATURES).setInputCol(tokenizer.getOutputCol())
.setOutputCol("rawFeatures");
IDF idf = new IDF().setInputCol(hashingTF.getOutputCol()).setOutputCol("rescaledFeatures");
NaiveBayes naiveBayes = new NaiveBayes().setFeaturesCol(idf.getOutputCol()).setLabelCol("categoryIndex");
Pipeline pipeline = new Pipeline()
.setStages(new PipelineStage[] { indexer, tokenizer, hashingTF, idf, naiveBayes });
它完美无缺,既适合估算器又适合运行变压器(针对包含金色标签的测试装置)
但是,当我尝试使用相同的管道来实现"真正的"没有黄金标签的例子(标签正是我们想要获得的),作为管道一部分的StringIndexer抛出异常:
Caused by: org.apache.spark.SparkException: Unseen label: UNKNOWN.
UNKNOWN是我用编程方式创建新的数据集元素时设置的假标签,其中包含新的看不见的示例,当然这种标签不存在于训练集中。我理解为什么会出现这个错误,但有没有办法告诉管道我不再是"培训"或"评估",但使用它进行真正的分类? 如何从新示例(没有已知标签)开始为管道构建有效输入以对其进行分类?
这是我在stackoverflow中的第一个问题,希望我已经清楚地解释了它。 在此先感谢: - )
答案 0 :(得分:1)
我自己找到了解决方案。
TL; DR:StringIndexer
应放在管道之外。
使用StringIndexer
转换初始数据集以获取每个标签索引,但不在管道中包含转换。然后在管道的末尾设置一个IndexToString
转换器,将预测的索引(用于分类/回归的 ML 算法的结果)转换回分类标签
这样,当存储管道模型以供以后在生产中使用时,将不会有StringIndexer
导致上述问题,而IndexToString
将解释结果预测模型的输出有意义的标签。