Apache spark 基于LBFGS的Spark Logistic回归预测多类分类的概率

Apache spark 基于LBFGS的Spark Logistic回归预测多类分类的概率,apache-spark,pyspark,logistic-regression,apache-spark-mllib,Apache Spark,Pyspark,Logistic Regression,Apache Spark Mllib,我正在使用LogisticRegressionWithLBFGS()来训练具有多个类的模型 从mllib中的文档可以看出,clearThreshold()只能在分类为二进制时使用。有没有一种方法可以在多类分类中使用类似的东西,以便在模型的给定输入中输出每个类的概率?有两种方法可以实现这一点。一种是创建一种方法,该方法承担 注意,它只是与原始方法略有不同,它只是根据输入特征计算逻辑。它还定义了一些VAL和VAR,这些VAL和VAR最初是私有的,并且包含在此方法之外。最终,它将分数索引到一个数组中,

我正在使用
LogisticRegressionWithLBFGS()
来训练具有多个类的模型


mllib
中的文档可以看出,
clearThreshold()
只能在分类为二进制时使用。有没有一种方法可以在多类分类中使用类似的东西,以便在模型的给定输入中输出每个类的概率?

有两种方法可以实现这一点。一种是创建一种方法,该方法承担

注意,它只是与原始方法略有不同,它只是根据输入特征计算逻辑。它还定义了一些VAL和VAR,这些VAL和VAR最初是私有的,并且包含在此方法之外。最终,它将分数索引到一个数组中,并将其与最佳答案一起返回。我这样称呼我的方法:

// Compute raw scores on the test set.
val predictionAndLabelsAndProbabilities = test
  .map { case LabeledPoint(label, features) =>
val (prediction, probabilities) = ClassificationUtility
  .predictPoint(features, model)
(prediction, label, probabilities)}
但是:

Spark的贡献者似乎不鼓励使用MLlib而支持ML。ML逻辑回归API目前不支持多类分类。我现在使用它作为一对所有分类的包装器。您可以通过迭代模型获得原始分数:

val lr = new LogisticRegression().setFitIntercept(true)
val ovr = new OneVsRest()
ovr.setClassifier(lr)
val ovrModel = ovr.fit(training)
ovrModel.models.zipWithIndex.foreach {
  case (model: LogisticRegressionModel, i: Int) =>
    model.save(s"model-${model.uid}-$i")
}

val model0 = LogisticRegressionModel.load("model-logreg_457c82141c06-0")
val model1 = LogisticRegressionModel.load("model-logreg_457c82141c06-1")
val model2 = LogisticRegressionModel.load("model-logreg_457c82141c06-2")
现在您已经有了各个模型,您可以通过计算原始预测的S形来获得概率

def sigmoid(x: Double): Double = {
  1.0 / (1.0 + Math.exp(-x))
}

val newPredictionAndLabels0 = model0.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels0.foreach(println)

val newPredictionAndLabels1 = model1.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels1.foreach(println)

val newPredictionAndLabels2 = model2.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels2.foreach(println)

我尝试了OnevsRest的解决方案,但在使用.select(“prediction”,“rawPrediction”)时,我无法访问rawPrediction列。在执行newPrediction和labels0.show()时,该列不存在。您是如何获得rawPrediction的?@outlier似乎在“rawPrediction”的末尾有一个额外的空间。试着移除它,看看是否可以修复它。
def sigmoid(x: Double): Double = {
  1.0 / (1.0 + Math.exp(-x))
}

val newPredictionAndLabels0 = model0.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels0.foreach(println)

val newPredictionAndLabels1 = model1.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels1.foreach(println)

val newPredictionAndLabels2 = model2.transform(newRescaledData)
  .select("prediction", "rawPrediction")
  .map(row => (row.getDouble(0),
    sigmoid(row.getAs[org.apache.spark.mllib.linalg.DenseVector](1).values(1)) ))
newPredictionAndLabels2.foreach(println)