【问题标题】:How to evaluate a classifier with PySpark 2.4.5如何使用 PySpark 2.4.5 评估分类器
【发布时间】:2020-07-01 11:33:34
【问题描述】:

我想知道使用 Apache Spark 2.4.5 和 PySpark (Python) 评估拟合二进制分类模型的最佳方法是什么。我想考虑不同的指标,例如准确度、精确度、召回率、auc 和 f1 分数。

让我们假设给出以下内容:

# pyspark.sql.dataframe.DataFrame in VectorAssembler format containing two columns: target and features
# DataFrame we want to evaluate
df

# Fitted pyspark.ml.tuning.TrainValidationSplitModel (any arbitrary ml algorithm)
model

1.选项

BinaryClassificationEvaluatorMulticlassClassificationEvaluator 都不能自行计算上述所有指标。因此,我们同时使用这两个评估器。

from pyspark.ml.evaluation import BinaryClassificationEvaluator, MulticlassClassificationEvaluator

# Create both evaluators
evaluatorMulti = MulticlassClassificationEvaluator(labelCol="target", predictionCol="prediction")
evaluator = BinaryClassificationEvaluator(labelCol="target", rawPredictionCol="prediction", metricName='areaUnderROC')

# Make predicitons
predictionAndTarget = model.transform(df).select("target", "prediction")

# Get metrics
acc = evaluatorMulti.evaluate(predictionAndTarget, {evaluatorMulti.metricName: "accuracy"})
f1 = evaluatorMulti.evaluate(predictionAndTarget, {evaluatorMulti.metricName: "f1"})
weightedPrecision = evaluatorMulti.evaluate(predictionAndTarget, {evaluatorMulti.metricName: "weightedPrecision"})
weightedRecall = evaluatorMulti.evaluate(predictionAndTarget, {evaluatorMulti.metricName: "weightedRecall"})
auc = evaluator.evaluate(predictionAndTarget)

缺点

  • 在评估二元分类器时使用 MulticlassClassificationEvaluator 似乎很奇怪且自相矛盾
  • 我必须使用两个不同的评估器来计算五个指标
  • MulticlassClassificationEvaluator 只计算weightedPrecisionweightedRecall(这对于多类分类是可以的)。但是,这两个指标在二进制情况下是否等于 precisionrecall

2。选项

将基于 RDD 的 API 与 BinaryClassificatinMetricsMulticlassMetrics 结合使用。同样,这两个指标都不能自己计算上面提到的所有指标(至少在 python 中不是 ..)。因此,我们同时使用两者。

from pyspark.mllib.evaluation import BinaryClassificationMetrics, MulticlassMetrics

# Make prediction
predictionAndTarget = model.transform(df).select("target", "prediction")

# Create both evaluators
metrics_binary = BinaryClassificationMetrics(predictionAndTarget.rdd.map(tuple))
metrics_multi = MulticlassMetrics(predictionAndTarget.rdd.map(tuple))

acc = metrics_multi.accuracy
f1 = metrics_multi.fMeasure(1.0)
precision = metrics_multi.precision(1.0)
recall = metrics_multi.recall(1.0)
auc = metrics_binary.areaUnderROC

缺点

  • 根据 Spark 的说法,基于 RDD 的 API 现在处于维护模式,DataFrame-based API is primary API
  • 同样,我必须使用两个不同的指标来计算五个指标
  • 同样,在评估二元分类器时,使用 MulticlassMetrics 似乎是矛盾的

上涨

  • 就我而言(~1.000.000 行)选项 2 似乎比选项 1 更快

惊喜

  • 就我而言,使用选项 1 和使用选项 2 时,f1areaUnderRoc 值不同。

选项 3

使用 numpy 和 sklearn

import numpy as np
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score, f1_score

# Make predicitons
predictionAndTarget = model.transform(df).select("target", "prediction")

predictionAndTargetNumpy = np.array((predictionAndTarget.collect()))

acc = accuracy_score(predictionAndTargetNumpy[:,0], predictionAndTargetNumpy[:,1])
f1 = f1_score(predictionAndTargetNumpy[:,0], predictionAndTargetNumpy[:,1])
precision = precision_score(predictionAndTargetNumpy[:,0], predictionAndTargetNumpy[:,1])
recall = recall_score(predictionAndTargetNumpy[:,0], predictionAndTargetNumpy[:,1])
auc = roc_auc_score(predictionAndTargetNumpy[:,0], predictionAndTargetNumpy[:,1])

缺点

  • 使用 sklearn 和 numpy 似乎很奇怪,因为 Apache Spark 声称拥有自己的评估 API
  • 如果数据集变得太大,甚至无法使用 numpy 和 sklearn。

总结一下我的问题:

  1. 建议使用上述哪个选项(如果有)来评估使用 Apache Spark 2.4.5 和 PySpark 的二进制分类器。
  2. 还有其他选项吗?我错过了什么重要的事情吗?
  3. 为什么我在使用选项 1 和使用选项 2 时得到不同的指标结果

【问题讨论】:

  • 我尝试了你的第一种方法,它只适用于准确性。
  • 尝试使用 Spark 的MulticlassClassificationEvaluator,我只能在上面秒 OP 的 cmets。令人困惑的是,并非所有指标都由一个评估者类提供。在 Spark 中也有类似 sklearn 的分类报告之类的东西会很棒。

标签: python apache-spark pyspark apache-spark-mllib evaluation


【解决方案1】:

不确定现在是否相关,但可以回答您的问题 3,因此可能是问题 1-

Spark ML 仅作为 MulticlassClassificationEvaluator 模块的一部分提供加权精度和加权召回指标。 如果您希望对整体精度指标有等效的解释,特别是在二进制分类等效于 Scikit world 的情况下,那么最好计算混淆矩阵并使用精度和召回公式进行评估

Spark ML 使用的加权精度是使用两个类的精度计算的,然后使用测试集中每个类标签的权重相加,即

Prec (Label 1) = TP/(TP+FP)
Prec (Label 0) = TN/(TN+FN)
Weight of Label 1 in test set WL1 = L1/(L1+L2)
Weight of Label 0 in test set WL2 = L2/(L1+L2)
Weighted precision = (PrecL1 * WL1) + (PrecL0 * WL2)

在数据集中即使有轻微的类不平衡的情况下,加权精度和召回率将超过整体精度和召回率,因此基于 Sklearn 和基于 Spark ML 之间的指标会有所不同。

作为说明,类不平衡数据集的混淆矩阵如下:

 array([[3969025,  445123],
       [ 284283, 1663913]])
 
 Total 1 Class labels   1948196
 Total 0 Class labels   4414148

 Proportion Label 1 :0.306207272
 Proportion Label 0 :0.693792728


Spark ML will give metrics :
Accuracy : 0.8853557745384405
Weighted Precision : 0.8890015815237463
WeightedRecall :    0.8853557745384406
F-1 Score  :  0.8865644697253956

而实际总体指标计算给出(Scikit 等效项):

 Accuracy:  0.8853557745384405
 Precision: 0.7889448070113549
 Recall:    0.8540788503826103
 AUC:   0.8540788503826103
 f1:    0.8540788503826103

因此,Spark ML 加权版本夸大了我们观察到的其他总体度量计算,特别是对于二进制分类

【讨论】:

  • 感谢您的解释!但是,我的问题是为什么在使用选项 1(基于 Spark ML DataFrame 的 API)与使用选项 2(基于 Spark ML RDD 的 API)时得到不同的结果。而且我不确定您的解释如何回答我的第一个问题(推荐哪个选项)?
  • 不应该是“Total 1 Class labels” 3969025 + 445123=4414148 吗?
  • 很抱歉,如果第 1 类的重量基本上是 L1=(TP+FP)/(TP+FP+FN+TN) 并且我必须乘以 TP/(TP+FP ) 然后对于 0 类 L0=(TN+FN)/(TP+FP+FN+TN) 和 TN/(TN+FN) ,如果我加在一起,我基本上得到了准确度 (TP + TN)/(TP + TN + FP + FN)
  • 纯评估的好方法,但将其用作 CrossValidator 对象的评估器很热?我的意思是,如何基于 f1(scikit 学习等效)运行 CrossValidator
猜你喜欢
  • 2021-04-10
  • 1970-01-01
  • 2017-06-10
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
相关资源
最近更新 更多