Title: how to add custom metrics to spark mlib evaluator?
Tags: scala;apache-spark
Question: The spark version is 2.3.1. 

```Spark-Mlib``` library provide a ```BinaryClassificationEvaluator``` (BinaryClassificationEvaluator.scala) class to evaluate the algorithm, and also can be used to gird search. But it only suppose two metrics 

```  val metric = $(metricName) match {
  case "areaUnderROC" =&gt; metrics.areaUnderROC()
  case "areaUnderPR" =&gt; metrics.areaUnderPR()
  //what i want todo
  case "areUnderXX"=&gt; myCustomMetric()
}
```

I try to add more, but ```BinaryClassificationEvaluator``` have some members that are set to ```private```, so i can't just extends it. Here are the code that can't be viewed outside the package:

```SchemaUtils.checkColumnTypes(schema, $(rawPredictionCol), Seq(DoubleType, new VectorUDT))
SchemaUtils.checkNumericType(schema, $(labelCol))
```

These code do some type check, so if i remove it, it would workaround. But, It seems unsafe and ugly. So, is there another way to do it? any help would be appreciated!



Here is another answer: You can use MulticlassMetrics. It provides more metrics. As an example using a DataFrame with your labels and predictions: 

```+---------+----------+
|label    |prediction|
+---------+-----+----+
|   1.0   |    0.0   |
|   0.0   |    0.0   |
+---------+----------+
```

You must pivot your dataframe for the label field

```val metrics = df.select("prediction", labelName)
  .as[(Double, Double)]
  .rdd

val multim = new MulticlassMetrics(metrics)
val labels = multim.labels

val accuracy = multim.accuracy

println("Summary Statistics")
println(s"Accuracy = $accuracy")

labels.foreach { l =&gt;
  println(s"Precision($l) = " + multim.precision(l))
}

// Recall by label
labels.foreach { l =&gt;
  println(s"Recall($l) = " + multim.recall(l))
}

// False positive rate by label
labels.foreach { l =&gt;
  println(s"FPR($l) = " + multim.falsePositiveRate(l))
}
```

There are more metrics you can see in https://spark.apache.org/docs/2.2.0/mllib-evaluation-metrics.html

Depending of what kind of metrics you need maybe you should deal with the dataframe with the dataframe. For example, if you want to compute your confusion matrix, you can proceed pivoting over the "prediction" column like:

```df.groupBy("label").
      pivot("prediction", range)
      .count()
      .na.fill(0.0)
      .orderBy("label)
      .show()
```

Comment for this answer: thanks. this works if i only want to measure the model result. But what i want to do is implement an evalluator which can pipeline with the original  workflow(in order to gird search and something else), so this may not work.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2018:00:10/25/18', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<scala><apache-spark>', 'Title': 'how to add custom metrics to spark mlib evaluator?', 'ViewCount': 458, 'id': 52992639, 'user_AboutMe': '', 'user_AccountId': 2780638.0, 'user_DisplayName': 'Ziu', 'user_Reputation': 589.0, 'user_Views': 48.0, 'user_id': 2393253.0}}