私はLogisticRegressionWithLBFGS()
を使用して、複数のクラスを持つモデルを訓練しています。マルチクラス分類のためにSpark LogisticRegressionWithLBFGSを使用する予測の確率
mllib
のドキュメントから、clearThreshold()
は、分類がバイナリの場合にのみ使用できると書かれています。モデルの与えられた入力に各クラスの確率を出力するために、マルチクラス分類に類似のものを使用する方法はありますか?
私はLogisticRegressionWithLBFGS()
を使用して、複数のクラスを持つモデルを訓練しています。マルチクラス分類のためにSpark LogisticRegressionWithLBFGSを使用する予測の確率
mllib
のドキュメントから、clearThreshold()
は、分類がバイナリの場合にのみ使用できると書かれています。モデルの与えられた入力に各クラスの確率を出力するために、マルチクラス分類に類似のものを使用する方法はありますか?
これを行うには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)
のシグモイドを計算することにより、確率を得ることができます