pyspark 提取 ROC 曲线?

set*_*127 12 pyspark apache-spark-ml

有没有办法从pyspark中的Spark ML获取ROC曲线上的点?在文档中,我看到了一个 Scala 的例子,但不是 python:https : //spark.apache.org/docs/2.1.0/mllib-evaluation-metrics.html

那正确吗?我当然可以想出实现它的方法,但我不得不想象如果有一个预先构建的函数它会更快。我正在处理 300 万个分数和几十个模型,所以速度很重要。

Ale*_*oss 17

对于适用机型除了Logistic回归(如决策树或随机森林缺乏模型摘要)的作品更广泛的解决方案,你可以得到使用ROC曲线BinaryClassificationMetrics从星火MLlib。

请注意,PySpark 版本并未实现Scala 版本所做的所有方法,因此您需要使用JavaModelWrapper 中.call(name)函数。py4j似乎也不支持解析类,所以必须手动处理。scala.Tuple2

例子:

from pyspark.mllib.evaluation import BinaryClassificationMetrics

# Scala version implements .roc() and .pr()
# Python: https://spark.apache.org/docs/latest/api/python/_modules/pyspark/mllib/common.html
# Scala: https://spark.apache.org/docs/latest/api/java/org/apache/spark/mllib/evaluation/BinaryClassificationMetrics.html
class CurveMetrics(BinaryClassificationMetrics):
    def __init__(self, *args):
        super(CurveMetrics, self).__init__(*args)

    def _to_list(self, rdd):
        points = []
        # Note this collect could be inefficient for large datasets 
        # considering there may be one probability per datapoint (at most)
        # The Scala version takes a numBins parameter, 
        # but it doesn't seem possible to pass this from Python to Java
        for row in rdd.collect():
            # Results are returned as type scala.Tuple2, 
            # which doesn't appear to have a py4j mapping
            points += [(float(row._1()), float(row._2()))]
        return points

    def get_curve(self, method):
        rdd = getattr(self._java_model, method)().toJavaRDD()
        return self._to_list(rdd)
Run Code Online (Sandbox Code Playgroud)

用法:

import matplotlib.pyplot as plt

# Create a Pipeline estimator and fit on train DF, predict on test DF
model = estimator.fit(train)
predictions = model.transform(test)

# Returns as a list (false positive rate, true positive rate)
preds = predictions.select('label','probability').rdd.map(lambda row: (float(row['probability'][1]), float(row['label'])))
points = CurveMetrics(preds).get_curve('roc')

plt.figure()
x_val = [x[0] for x in points]
y_val = [x[1] for x in points]
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.plot(x_val, y_val)
Run Code Online (Sandbox Code Playgroud)

使用 PySpark BinaryClassificationMetrics 生成的 ROC 曲线

Scala 中的 BinaryClassificationMetrics 还实现了其他几个有用的方法:

metrics = CurveMetrics(preds)
metrics.get_curve('fMeasureByThreshold')
metrics.get_curve('precisionByThreshold')
metrics.get_curve('recallByThreshold')
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@AlexRoss,这真的很有帮助!我希望我能多次升级! (2认同)

And*_*rea 8

只要 ROC 曲线是 FPR 对 TPR 的图,您就可以提取所需的值如下:

your_model.summary.roc.select('FPR').collect()
your_model.summary.roc.select('TPR').collect())
Run Code Online (Sandbox Code Playgroud)

your_model例如,你从这样的东西中得到的模型在哪里:

from pyspark.ml.classification import LogisticRegression
log_reg = LogisticRegression()
your_model = log_reg.fit(df)
Run Code Online (Sandbox Code Playgroud)

现在,您应该只针对 TPR 绘制 FPR,例如使用matplotlib.

聚苯乙烯

这是使用名为your_model(以及其他任何东西!)的模型绘制 ROC 曲线的完整示例。我还在 ROC 图中绘制了参考“随机猜测”线。

import matplotlib.pyplot as plt
plt.figure(figsize=(5,5))
plt.plot([0, 1], [0, 1], 'r--')
plt.plot(your_model.summary.roc.select('FPR').collect(),
         your_model.summary.roc.select('TPR').collect())
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.show()
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这很有帮助。不过,就我而言,我没有实际模型。我有一个带有概率和二进制标签的两列 rdd。在 scala 文档中,您可以执行 `metrics = BinaryClassificationMetrics(predictionAndLabels)` 然后 `metrics.roc` 为您提供分数。但这对 pyspark 不起作用。我猜这是一个功能存在于其他地方的冰雹? (2认同)