我正在使用Spark 1.6运行多类逻辑回归(使用LBFGS)。
给定 x 和可能的标签 {1.0,2.0,3.0}最终模型只会输出最佳预测,比如2.0。
如果我有兴趣知道第二好的预测是什么,比如3.0,我该如何检索这些信息?
在 NaiveBayes 中,我会使用 model.predictProbability() 函数,该函数为每个样本输出一个向量,其中包含每个可能结果的所有概率。
在 Spark 中有两种方法可以进行逻辑回归:spark.ml
和 spark.mllib
。
使用数据帧,您可以使用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
.它将向量相乘,并选择预测最高的类。权重是可公开访问的,因此您可以复制该算法并保存预测,而不仅仅是返回最高的预测。
遵循@Daniel Darabos的建议:
- 我尝试使用 ml 中的 LogisticRegression 函数而不是 mllib不幸的是,它不支持多类逻辑回归,而只支持二进制回归。
- 我看了一下预测点并对其进行了修改,使其打印每个类的所有概率。这是它的样子:
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
}
我正在返回一个哈希图[Int,Double],但可以根据自己的意愿进行更改。
希望这有帮助!