我用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列已经存在”。
您对改善这项工作的表现有什么建议吗?
答案 0 :(得分:0)
一些注意事项:
monotonically_increasing_id
的两列。不能保证两者都会增加相同的值。数据集1可以得到1,2,3,数据集2可以得到1000,2005,3999 类似的东西:
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并在脑海中进行翻译-但这就是您如何解决它的要旨。