【问题标题】:model.predictProbabilities() for LogisticRegression in Spark?Spark中LogisticRegression的model.predictProbabilities()?
【发布时间】:2016-05-18 09:40:19
【问题描述】:

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

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

如果我想知道第二好的预测是什么,比如 3.0,我该如何检索这些信息?

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

【问题讨论】:

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


    【解决方案1】:

    在 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。它将向量相乘并选择具有最高预测的类。权重可公开访问,因此您可以复制该算法并保存预测,而不是只返回最高的。

    【讨论】:

    • 感谢您的回答。虽然,我在努力理解如何使用 ProbabilisticClassificationModel。 1)我不确定 LogisticRegressionWithLBFGS 是 ProbabilisticClassificationModel 的子类。 2) 网上没有关于如何使用 ProbabilisticClassificationModel 的示例 3) 传递给变换函数的数据帧是什么?我用于 LogisticRegression 的训练集?很抱歉造成了很大的混乱。
    • 你是对的,这一点都不明显。几个小时后我会回来提供一个完整的例子!
    • 是的,对不起,我睡着了:)。所以看起来有两个类叫做LogisticRegressionModel,一个在spark.ml,一个在spark.mllib。只有第一个给你原始的预测。我已经重写了答案来解释这一点。使用spark.ml 看起来最简单,但如果您可以从 Spark 复制一些代码,您也可以使用spark.mllib
    • @DanielDarabos 你能告诉这里 rawPrediction 列的含义是什么,以及我们如何知道哪个概率属于哪个类?谢谢
    • rawPrediction 在 softmax 之前。 (github.com/apache/spark/blob/v2.1.1/mllib/src/main/scala/org/…) 概率与类的顺序相同。
    【解决方案2】:

    遵循@Daniel Darabos 的建议:

    1. 我尝试使用 ml 中的 LogisticRegression 函数而不是 mllib 不幸的是,它不支持多类逻辑回归,而只支持二元回归。
    2. 我看了PredictedPoint 并对其进行了修改,以便打印每个类的所有概率。这是它的样子:
        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] 但可以随意更改。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-09
      • 1970-01-01
      • 1970-01-01
      • 2013-10-01
      • 2019-06-20
      • 2017-12-01
      • 1970-01-01
      • 2021-03-23
      相关资源
      最近更新 更多