2

私はLogisticRegressionWithLBFGS()を使用して、複数のクラスを持つモデルを訓練しています。マルチクラス分類のためにSpark LogisticRegressionWithLBFGSを使用する予測の確率

mllibのドキュメントから、clearThreshold()は、分類がバイナリの場合にのみ使用できると書かれています。モデルの与えられた入力に各クラスの確率を出力するために、マルチクラス分類に類似のものを使用する方法はありますか?

答えて

0

これを行うには2通りの方法があります。一つは、それだけわずかに異なる元のメソッドからであるLogisticRegression.scala

object ClassificationUtility { 
    def predictPoint(dataMatrix: Vector, model: LogisticRegressionModel): 
    (Double, Array[Double]) = { 
    require(dataMatrix.size == model.numFeatures) 
    val dataWithBiasSize: Int = model.weights.size/(model.numClasses - 1) 
    val weightsArray: Array[Double] = model.weights match { 
     case dv: DenseVector => dv.values 
     case _ => 
     throw new IllegalArgumentException(s"weights only supports dense vector but got type ${model.weights.getClass}.") 
    } 
    var bestClass = 0 
    var maxMargin = 0.0 
    val withBias = dataMatrix.size + 1 == dataWithBiasSize 
    val classProbabilities: Array[Double] = new Array[Double (model.numClasses) 
    (0 until model.numClasses - 1).foreach { i => 
     var margin = 0.0 
     dataMatrix.foreachActive { (index, value) => 
     if (value != 0.0) margin += value * weightsArray((i * dataWithBiasSize) + index) 
     } 
     // Intercept is required to be added into margin. 
     if (withBias) { 
     margin += weightsArray((i * dataWithBiasSize) + dataMatrix.size) 
     } 
     if (margin > maxMargin) { 
     maxMargin = margin 
     bestClass = i + 1 
     } 
     classProbabilities(i+1) = 1.0/(1.0 + Math.exp(-margin)) 
    } 
    return (bestClass.toDouble, classProbabilities) 
    } 
} 

predictPointの責任を負いメソッドを作成することであり、それだけで、入力フィーチャの関数としてロジスティックを算出します。また、元々プライベートであり、このメソッドの外に含まれるいくつかのvalとvarsを定義します。最終的には、配列内のスコアをインデックス化し、それを最善の回答と一緒に返します。私はそうのように私のメソッドを呼び出します。

// 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)} 

しかし:

スパークの貢献者は、MLの賛成でMLlibの使用を落胆されているようです。 MLロジスティック回帰APIは、現在、マルチクラス分類をサポートしていません。私は現在OneVsRestを使用しています。これは1対すべての分類のラッパーとして機能します。あなたがモデルを反復処理することにより、生のスコアを取得することができます。今、あなたは個々のモデルを持っていることを

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") 

を、あなたは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) 
のシグモイドを計算することにより、確率を得ることができます
関連する問題