繁体   English   中英

如何计算 scala/spark 中的对数损失指标?

[英]How to calculate the log loss metric in scala/spark?

我已经训练了一个二元分类器 ( XGBoostClassifier ) model,并在我的结果 dataframe 中有两列: PREDICTED_COLTARGET_COL 例如,我可以通过以下方式计算 areaUnderROC:

val metrics = new BinaryClassificationMetrics(df.select(col(PREDICTED_COL), col(TARGET_COL)).rdd.map(row => (row.getDouble(0), row.getInt(1).toDouble)))
val auc = metrics.areaUnderROC()

但是,没有相应/简单的方法来计算对数损失度量。 怎么做?

注意:我尝试使用org.apache.spark.mllib.tree.loss.LogLoss但 function 不带任何参数(例如我的 PREDICTED_COL 和 TARGET_COL),所以不知道如何使用它。

这是 LogLoss 公式: 对数损失公式

您可以只实现公式:

val df_ll = df.withColumn("logloss", -($"target_col" * log($"predicted_col") + (lit(1) - $"target_col") * log(lit(1) - $"predicted_col")))

请注意,我们仅使用 spark.sql.functions 的内置函数,这意味着我们获得了相当好的性能(比 UDF 更好)

所以这里有一个方便的 function 来计算给定 dataframe 的对数损失( TARGET_COL是基本事实,又名PREDICTED_COL ,模型返回的预测是:

def calcualteLogLoss (df: Dataset[Row]): Double = {
    val df2 = df.withColumn("logloss",
      col(TARGET_COL).multiply(lit(-1))
        .multiply(log(col(PREDICTED_COL)))
      .minus(
        lit(1.0).minus(col(TARGET_COL))
          .multiply(log(lit(1).minus(col(PREDICTED_COL))))
      )
    )

    // calculate desired logloss as average of all samples
    val loglossA = df2.agg(mean("logloss").alias("ll")).collect()
    var logloss = -1d
    if (loglossA != null && loglossA.length > 0){
      val loglossB = loglossA.head
      if (loglossB != null && loglossB.length > 0 && loglossB.get(0) != null) {
        logloss = loglossB.getDouble(0)
      }
    }

    logloss
  }

这个简单的 function 可以用来获取日志丢失。

from pyspark.sql.types import *
import pyspark.sql.functions as F

def logloss(predictions, label_column):
        """
        function for calculation of log loss
        :param spark.DataFrame predictions : model predicted spark dataframe
        :param string label_column : column name containing true labels
        :return float log_loss
        """
        get_first_element = F.udf(lambda v:float(v[1]), FloatType())
        predictions = predictions.select(F.col(label_column).alias("label"), "probability")
        predictions = predictions.withColumn("true_prediction_probability", \
                                               get_first_element(F.col("probability"))).drop("probability")

        predictions = predictions.withColumn("logloss", -(F.col("label") * F.log(F.col("true_prediction_probability")) + \
                             (F.lit(1) - F.col("label")) * F.log(F.lit(1) - F.col("true_prediction_probability"))))
        log_loss = predictions.select(F.mean("logloss")).collect()[0][0]

        return log_loss

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM