Spark ML CrossValidator是否可配置多Evaluator同时获取R2与RMSE
问题解答
方案可行性结论
你提出的连续调用两次setEvaluator配置多评估器的方案不可行。
Spark MLlib 中CrossValidator的设计仅支持传入单个Evaluator作为超参数优化的排序依据,setEvaluator为覆盖式赋值,后一次传入的R2评估器会直接覆盖之前设置的RMSE评估器,最终交叉验证只会按R2筛选最优模型,也仅能输出R2对应的交叉验证平均指标。
可行实现方案
仅需要运行一次交叉验证即可同时获取两类指标,无需创建两个CrossValidator实例,参考实现如下:
基础配置
选择一个作为最优模型筛选依据的主指标(示例用RMSE)配置CrossValidator,同时开启子模型收集能力:
val lr_evaluator_rmse = new RegressionEvaluator() .setLabelCol("ArrDelay") .setPredictionCol("predictionLR") .setMetricName("rmse") val lr_evaluator_r2 = new RegressionEvaluator() .setLabelCol("ArrDelay") .setPredictionCol("predictionLR") .setMetricName("r2") val lr_cv = new CrossValidator() .setEstimator(lr_pipeline) .setEvaluator(lr_evaluator_rmse) .setEstimatorParamMaps(lr_paramGrid) .setNumFolds(3) .setParallelism(3) .setCollectSubModels(true) // 开启子模型收集,Spark 3.0及以上版本支持
计算多指标
拟合完成后可按需求计算不同场景的指标:
场景1:只需最优模型在测试集的两类指标
// 拟合交叉验证模型 val lr_cv_model = lr_cv.fit(train_dataset) val best_lr_model = lr_cv_model.bestModel val test_predictions = best_lr_model.transform(test_dataset) // 分别计算两个评估指标 val test_rmse = lr_evaluator_rmse.evaluate(test_predictions) val test_r2 = lr_evaluator_r2.evaluate(test_predictions)
场景2:需要交叉验证K折的平均两类指标
// RMSE的K折平均可直接从CrossValidator结果获取 val avg_cv_rmse = lr_cv_model.avgMetrics.head // 遍历各折的子模型手动计算R2的平均 val avg_cv_r2 = lr_cv_model.subModels.map { fold_model => lr_evaluator_r2.evaluate(fold_model.transform(fold_validation_dataset)) }.sum / lr_cv_model.subModels.length
内容的提问来源于stack exchange,提问作者rayqz
相关产品推荐
相关产品推荐

