将多个SparkML管道应用于单个DataFrame

时间:2018-06-22 13:35:42

标签: apache-spark machine-learning apache-spark-sql apache-spark-ml

我用SparkML训练了数个ml管道,并将其保留在HDFS中。现在,我想将管道应用于相同的数据框。我实现了一个通用评分类,该类将数据与数据一起读取到管道中,将每个管道应用于数据框,并将模型预测附加为新列。这是我的Java代码示例:

    List<PipelineModel> models = readPipelineModels(...)
    Dataset<Row> originalDf = spark.read().parquet(...)
    Dataset<Row> mergedDf = originalDf;
    for (PipelineModel pipelineModel : models) {
            Dataset<Row> applyDf = pipelineModel.transform(originalDf);
            applyDf = dropDuplicateColumns(applyDf, mergedDf); // drops columns in applyDf which are present in mergedDf
            mergedDf = mergedDf.withColumn("rowId", monotonically_increasing_id());
            applyDf = applyDf.withColumn("rowId", monotonically_increasing_id());
            mergedDf = mergedDf.join(applyDf, "rowId").drop("rowId").cache();
    }

我注意到一些性能问题,尤其是对于大型数据集。用于绑定数据帧的联接非常昂贵,并且在各阶段之间进行了许多改组。

请注意,我将每个模型都应用于了originalDf,而不是mergedDf。如果在每次迭代中将模型应用于mergedDf,则会收到一个错误消息,指出以前的迭代中“ xy列已经存在”。

您对改善这项工作的表现有什么建议吗?

1 个答案:

答案 0 :(得分:0)

一些注意事项:

  • 我不会分别制作monotonically_increasing_id的两列。不能保证两者都会增加相同的值。数据集1可以得到1,2,3,数据集2可以得到1000,2005,3999
  • 我认为您不需要删除/合并DF。我只会重复使用应用模型的结果。

类似的东西:

List<PipelineModel> models = readPipelineModels(...);
Dataset<Row> mergedDf = spark.read().parquet(...);
int i = 0;
for (PipelineModel pipelineModel : models) {
    i += 1;
    mergedDf = pipelineModel.transform(mergedDf);
    mergedDf = mergedDf.withColumnRenamed("yourModelOutput", "model_outputs_" + i);
}

FWIW我已经习惯了PySpark并在脑海中进行翻译-但这就是您如何解决它的要旨。