如何使用 PySpark 2.4.5 评估分类器

Gus*_*sto 16 python evaluation apache-spark pyspark apache-spark-mllib

我想知道使用 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
Run Code Online (Sandbox Code Playgroud)

1. 选项

无论BinaryClassificationEvaluator也不MulticlassClassificationEvaluator可以计算出自己的上述所有指标。因此,我们使用两个评估器。

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)
Run Code Online (Sandbox Code Playgroud)

缺点

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

2. 选项

使用基于RDD API BinaryClassificatinMetrics和MulticlassMetrics。同样,这两个指标都不能单独计算上面提到的所有指标(至少在 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
Run Code Online (Sandbox Code Playgroud)

缺点

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

上行空间

  • 在我的情况下(~1.000.000 行)选项 2 似乎比选项 1 快

惊喜

  • 在我来说,我得到不同f1和areaUnderRoc使用选项2时,使用选项1时,VS值。

选项 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])
Run Code Online (Sandbox Code Playgroud)

缺点

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

总结我的问题:

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

rau*_*aul 3

不确定现在是否相关,但可以回答你的问题 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)
Run Code Online (Sandbox Code Playgroud)

即使数据集中存在轻微的类别不平衡,加权精度和召回率也将高于总体精度和召回率,因此基于 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
Run Code Online (Sandbox Code Playgroud)

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

 Accuracy:  0.8853557745384405
 Precision: 0.7889448070113549
 Recall:    0.8540788503826103
 AUC:   0.8540788503826103
 f1:    0.8540788503826103
Run Code Online (Sandbox Code Playgroud)

因此,Spark ML 加权版本夸大了我们特别观察到的二元分类的总体指标计算