Spark中的LogisticRegression的model.predictProbabilities()?

时间:2016-02-08 16:30:52

标签: apache-spark logistic-regression apache-spark-mllib

我正在使用Spark 1.6运行多类 Logistic回归(withLBFGS)

给出 x 和可能的标签 {1.0,2.0,3.0} 最终模型将输出最佳预测,例如 2.0

如果我有兴趣知道第二个最佳预测是什么,请说 3.0 ,我该如何检索该信息?

在NaiveBayes中,我将使用model.predictProbabilities()函数,该函数为每个样本输出一个包含每个可能结果的所有概率的向量。

2 个答案:

答案 0 :(得分:3)

Spark中有两种方法可以进行逻辑回归:spark.mlspark.mllib

使用DataFrames,您可以使用spark.ml

import org.apache.spark
import sqlContext.implicits._

def p(label: Double, a: Double, b: Double) =
  new spark.mllib.regression.LabeledPoint(
    label, new spark.mllib.linalg.DenseVector(Array(a, b)))

val data = sc.parallelize(Seq(p(1.0, 0.0, 0.5), p(0.0, 0.5, 1.0)))
val df = data.toDF

val model = new spark.ml.classification.LogisticRegression().fit(df)
model.transform(df).show

您可以获得原始预测和概率:

+-----+---------+--------------------+--------------------+----------+
|label| features|       rawPrediction|         probability|prediction|
+-----+---------+--------------------+--------------------+----------+
|  1.0|[0.0,0.5]|[-19.037302860930...|[5.39764620520461...|       1.0|
|  0.0|[0.5,1.0]|[18.9861466274786...|[0.99999999431904...|       0.0|
+-----+---------+--------------------+--------------------+----------+

使用RDD,您可以使用spark.mllib

val model = new spark.mllib.classification.LogisticRegressionWithLBFGS().run(data)

此模型不会公开原始预测和概率。你可以看看predictPoint。它将向量相乘并选择具有最高预测的类。权重可公开访问,因此您可以复制该算法并保存预测,而不是仅返回最高权重。

答案 1 :(得分:2)

遵循@Daniel Darabos的建议:

  1. 我尝试使用 ml 中的LogisticRegression函数,而不是 mllib 不幸的是,它不支持多类逻辑回归,而只支持二元逻辑回归。
  2. 我看了PredictedPoint 并修改它,以便打印每个类的所有概率。这就是它的样子:
  3.     def predictPointForMulticlass(featurizedVector:Vector,weightsArray:Vector,intercept:Double,numClasses:Int,numFeatures:Int) : Seq[(String, Double)] = {
    
            val weightsArraySize = weightsArray.size
            val dataWithBiasSize = weightsArraySize / (numClasses - 1)
            val withBias = false
    
            var bestClass = 0
            var maxMargin = 0.0
            var margins = new Array[Double](numClasses - 1)
            var temp_marginMap = new HashMap[Int, Double]()
            var res = new HashMap[Int, Double]()
    
            (0 until numClasses - 1).foreach { i =>
              var margin = 0.0
              var index = 0
              featurizedVector.toArray.foreach(value => {
                if (value != 0.0) {
                  margin += value * weightsArray((i * dataWithBiasSize) + index)
                }
                index += 1
              }
              )
            // Intercept is required to be added into margin.
            if (withBias) {
                margin += weightsArray((i * dataWithBiasSize) + featurizedVector.size)
            }
            val prob = 1.0 / (1.0 + Math.exp(-margin))
            margins(i) = margin
    
            temp_marginMap += (i -> margin)
    
            if(margin > maxMargin) {
                maxMargin = margin
                bestClass = i + 1
              }
            }
    
            for ((k,v) <- temp_marginMap){
              val calc =probCalc(maxMargin,v)
              res += (k -> calc)
            }
    
          return res
        }
    

    其中probCalc()简单地定义为:         

          def probCalc(maxMargin:Double,margin:Double) :Double ={
            val res = 1.0 / (1.0 + Math.exp(-(margin - maxMargin)))
            res
          }
    

    我正在返回一个Hashmap [Int,Double],但可以根据需要进行更改。

    希望这有帮助!