Spark 1.5.1,MLLib 随机森林概率
Spark 1.5.1, MLLib Random Forest Probability
我正在使用带有 MLLib 的 Spark 1.5.1。我使用 MLLib 构建了一个随机森林模型,现在使用该模型进行预测。我可以使用 .predict 函数找到预测类别(0.0 或 1.0)。但是,我找不到检索概率的函数(请参阅随附的屏幕截图)。我以为 spark 1.5.1 随机森林会提供概率,我在这里遗漏了什么吗?
遗憾的是,该功能在较旧的 Spark MLlib 1.5.1 中不可用。
然而,您可以在 Spark MLlib 2.x 中最近的管道 API 中找到它,如 RandomForestClassifier
:
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.RandomForestClassifier
import org.apache.spark.ml.feature.{IndexToString, StringIndexer, VectorIndexer}
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file, converting it to a DataFrame.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt").toDF
// Index labels, adding metadata to the label column.
// Fit on whole dataset to include all labels in index.
val labelIndexer = new StringIndexer()
.setInputCol("label")
.setOutputCol("indexedLabel").fit(data)
// Automatically identify categorical features, and index them.
// Set maxCategories so features with > 4 distinct values are treated as continuous.
val featureIndexer = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(4).fit(data)
// Split the data into training and test sets (30% held out for testing)
val Array(trainingData, testData) = data.randomSplit(Array(0.7, 0.3))
// Train a RandomForest model.
val rf = new RandomForestClassifier()
.setLabelCol(labelIndexer.getOutputCol)
.setFeaturesCol(featureIndexer.getOutputCol)
.setNumTrees(10)
// Convert indexed labels back to original labels.
val labelConverter = new IndexToString()
.setInputCol("prediction")
.setOutputCol("predictedLabel")
.setLabels(labelIndexer.labels)
// Chain indexers and forest in a Pipeline
val pipeline = new Pipeline()
.setStages(Array(labelIndexer, featureIndexer, rf, labelConverter))
// Fit model. This also runs the indexers.
val model = pipeline.fit(trainingData)
// Make predictions.
val predictions = model.transform(testData)
// predictions: org.apache.spark.sql.DataFrame = [label: double, features: vector, indexedLabel: double, indexedFeatures: vector, rawPrediction: vector, probability: vector, prediction: double, predictedLabel: string]
predictions.show(10)
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// |label| features|indexedLabel| indexedFeatures|rawPrediction|probability|prediction|predictedLabel|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [0.0,10.0]| [0.0,1.0]| 1.0| 0.0|
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[129,130,131...| 1.0|(692,[129,130,131...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[181,182,183...| 1.0|(692,[181,182,183...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 1.0|(692,[99,100,101,...| 0.0|(692,[99,100,101,...| [4.0,6.0]| [0.4,0.6]| 1.0| 0.0|
// | 1.0|(692,[123,124,125...| 0.0|(692,[123,124,125...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[124,125,126...| 0.0|(692,[124,125,126...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[125,126,127...| 0.0|(692,[125,126,127...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// only showing top 10 rows
注:本例来自Spark MLlib的官方文档ML - Random forest classifier。
下面是对某些输出列的一些解释:
predictionCol
表示预测的标签。
rawPredictionCol
表示长度为 # 类 的向量,其中包含进行预测的树节点处训练实例标签的计数(仅可用于分类)。
probabilityCol
表示长度为 # 类 的概率向量等于 rawPrediction
归一化为多项分布(仅适用于分类)。
你不能直接得到class化的概率,但是自己计算相对容易。 RandomForest 是树的集合,其输出概率是这些树的多数投票除以树的总数。
由于 MLib 中的 RandomForestModel 为您提供了经过训练的树,因此您自己可以轻松完成。下面的代码给出了二进制 classification 问题的概率。它对多 class class 化的推广很简单。
def predict(points: RDD[LabeledPoint], model: RandomForestModel) = {
val numTrees = model.trees.length
val trees = points.sparkContext.broadcast(model.trees)
points.map { point =>
trees.value
.map(_.predict(point.features))
.sum / numTrees
}
}
for multi-class case 你只需要用 .map(_.predict(point.features)-> 1.0) 替换 map 并按键而不是 sum 进行分组,最后取最大值。
我正在使用带有 MLLib 的 Spark 1.5.1。我使用 MLLib 构建了一个随机森林模型,现在使用该模型进行预测。我可以使用 .predict 函数找到预测类别(0.0 或 1.0)。但是,我找不到检索概率的函数(请参阅随附的屏幕截图)。我以为 spark 1.5.1 随机森林会提供概率,我在这里遗漏了什么吗?
遗憾的是,该功能在较旧的 Spark MLlib 1.5.1 中不可用。
然而,您可以在 Spark MLlib 2.x 中最近的管道 API 中找到它,如 RandomForestClassifier
:
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.RandomForestClassifier
import org.apache.spark.ml.feature.{IndexToString, StringIndexer, VectorIndexer}
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file, converting it to a DataFrame.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt").toDF
// Index labels, adding metadata to the label column.
// Fit on whole dataset to include all labels in index.
val labelIndexer = new StringIndexer()
.setInputCol("label")
.setOutputCol("indexedLabel").fit(data)
// Automatically identify categorical features, and index them.
// Set maxCategories so features with > 4 distinct values are treated as continuous.
val featureIndexer = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(4).fit(data)
// Split the data into training and test sets (30% held out for testing)
val Array(trainingData, testData) = data.randomSplit(Array(0.7, 0.3))
// Train a RandomForest model.
val rf = new RandomForestClassifier()
.setLabelCol(labelIndexer.getOutputCol)
.setFeaturesCol(featureIndexer.getOutputCol)
.setNumTrees(10)
// Convert indexed labels back to original labels.
val labelConverter = new IndexToString()
.setInputCol("prediction")
.setOutputCol("predictedLabel")
.setLabels(labelIndexer.labels)
// Chain indexers and forest in a Pipeline
val pipeline = new Pipeline()
.setStages(Array(labelIndexer, featureIndexer, rf, labelConverter))
// Fit model. This also runs the indexers.
val model = pipeline.fit(trainingData)
// Make predictions.
val predictions = model.transform(testData)
// predictions: org.apache.spark.sql.DataFrame = [label: double, features: vector, indexedLabel: double, indexedFeatures: vector, rawPrediction: vector, probability: vector, prediction: double, predictedLabel: string]
predictions.show(10)
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// |label| features|indexedLabel| indexedFeatures|rawPrediction|probability|prediction|predictedLabel|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [0.0,10.0]| [0.0,1.0]| 1.0| 0.0|
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[129,130,131...| 1.0|(692,[129,130,131...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[181,182,183...| 1.0|(692,[181,182,183...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 1.0|(692,[99,100,101,...| 0.0|(692,[99,100,101,...| [4.0,6.0]| [0.4,0.6]| 1.0| 0.0|
// | 1.0|(692,[123,124,125...| 0.0|(692,[123,124,125...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[124,125,126...| 0.0|(692,[124,125,126...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[125,126,127...| 0.0|(692,[125,126,127...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// only showing top 10 rows
注:本例来自Spark MLlib的官方文档ML - Random forest classifier。
下面是对某些输出列的一些解释:
predictionCol
表示预测的标签。rawPredictionCol
表示长度为 # 类 的向量,其中包含进行预测的树节点处训练实例标签的计数(仅可用于分类)。probabilityCol
表示长度为 # 类 的概率向量等于rawPrediction
归一化为多项分布(仅适用于分类)。
你不能直接得到class化的概率,但是自己计算相对容易。 RandomForest 是树的集合,其输出概率是这些树的多数投票除以树的总数。
由于 MLib 中的 RandomForestModel 为您提供了经过训练的树,因此您自己可以轻松完成。下面的代码给出了二进制 classification 问题的概率。它对多 class class 化的推广很简单。
def predict(points: RDD[LabeledPoint], model: RandomForestModel) = {
val numTrees = model.trees.length
val trees = points.sparkContext.broadcast(model.trees)
points.map { point =>
trees.value
.map(_.predict(point.features))
.sum / numTrees
}
}
for multi-class case 你只需要用 .map(_.predict(point.features)-> 1.0) 替换 map 并按键而不是 sum 进行分组,最后取最大值。