PySpark 和 MLLib:Class 随机森林预测的概率
PySpark & MLLib: Class Probabilities of Random Forest Predictions
我正在尝试提取我使用 PySpark 训练的随机森林对象的 class 概率。但是,我在文档中的任何地方都没有看到它的示例,也不是 RandomForestModel
.
的方法
如何从 PySpark 中的 RandomForestModel
classifier 提取 class 概率?
这里是文档中提供的示例代码,只提供最后的class(不是概率):
from pyspark.mllib.tree import RandomForest
from pyspark.mllib.util import MLUtils
# Load and parse the data file into an RDD of LabeledPoint.
data = MLUtils.loadLibSVMFile(sc, 'data/mllib/sample_libsvm_data.txt')
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a RandomForest model.
# Empty categoricalFeaturesInfo indicates all features are continuous.
# Note: Use larger numTrees in practice.
# Setting featureSubsetStrategy="auto" lets the algorithm choose.
model = RandomForest.trainClassifier(trainingData, numClasses=2, categoricalFeaturesInfo={},
numTrees=3, featureSubsetStrategy="auto",
impurity='gini', maxDepth=4, maxBins=32)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
我没有看到任何 model.predict_proba()
方法 -- 我该怎么办??
据我所知,当前版本 (1.2.1) 不支持此功能。本机 Scala 代码 (tree.py) 上的 Python 包装器仅定义 'predict' 函数,这些函数依次调用相应的 Scala 对应项 (treeEnsembleModels.scala)。后者通过在二元决策之间进行投票来做出决策。一个更简洁的解决方案是提供一个概率预测,它可以任意设定阈值或用于像 sklearn 中的 ROC 计算。应该为将来的版本添加此功能!
作为一种变通方法,我将 predict_proba 作为纯 Python 函数实现(参见下面的示例)。它既不优雅也不高效,因为它 运行 是对森林中单个决策树集的循环。诀窍 - 或者更确切地说是一个肮脏的黑客 - 是访问 Java 决策树模型的数组并将它们转换为 Python 对应物。之后,您可以计算单个模型对整个数据集的预测,并使用 'zip' 在 RDD 中累积它们的总和。除以树的数量得到期望的结果。对于大型数据集,在主节点中对少量决策树进行循环应该是可以接受的。
由于难以将 Python 集成到 Spark(运行 in Java),下面的代码相当棘手。应该非常小心,不要将任何复杂的数据发送到工作节点,这会由于序列化问题导致崩溃。引用 Spark 上下文的代码不能在工作节点上 运行。此外,不能序列化引用任何 Java 代码的代码。例如,在下面的代码中使用 len(trees) 而不是 ntrees 可能很诱人——砰!在 Java/Scala 中编写这样的包装器可以更优雅,例如通过 运行 在工作节点上的决策树上循环,从而减少通信成本。
下面的测试函数表明 predict_proba 给出了与原始示例中使用的预测相同的测试错误。
def predict_proba(rf_model, data):
'''
This wrapper overcomes the "binary" nature of predictions in the native
RandomForestModel.
'''
# Collect the individual decision tree models by calling the underlying
# Java model. These are returned as JavaArray defined by py4j.
trees = rf_model._java_model.trees()
ntrees = rf_model.numTrees()
scores = DecisionTreeModel(trees[0]).predict(data.map(lambda x: x.features))
# For each decision tree, apply its prediction to the entire dataset and
# accumulate the results using 'zip'.
for i in range(1,ntrees):
dtm = DecisionTreeModel(trees[i])
scores = scores.zip(dtm.predict(data.map(lambda x: x.features)))
scores = scores.map(lambda x: x[0] + x[1])
# Divide the accumulated scores over the number of trees
return scores.map(lambda x: x/ntrees)
def testError(lap):
testErr = lap.filter(lambda (v, p): v != p).count() / float(testData.count())
print('Test Error = ' + str(testErr))
def testClassification(trainingData, testData):
model = RandomForest.trainClassifier(trainingData, numClasses=2,
categoricalFeaturesInfo={},
numTrees=50, maxDepth=30)
# Compute test error by thresholding probabilistic predictions
threshold = 0.5
scores = predict_proba(model,testData)
pred = scores.map(lambda x: 0 if x < threshold else 1)
lab_pred = testData.map(lambda lp: lp.label).zip(pred)
testError(lab_pred)
# Compute test error by comparing binary predictions
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testError(labelsAndPredictions)
总而言之,这是学习 Spark 的一个很好的练习!
但是,它将在 Spark 1.5.0 和新的 Spark-ML API 中可用。
现在可用。
Spark ML 提供:
- a
predictionCol
包含 预测标签
- 和一个
probabilityCol
,其中包含每个标签 概率的向量 ,这是你在找什么!
- 您还可以访问原始计数
有关更多详细信息,请参阅 Spark 文档:
http://spark.apache.org/docs/latest/ml-classification-regression.html#output-columns-predictions
可能人们会继续使用这个 post,但我今天在尝试计算 multi-class classifier 的准确性时遇到了同样的问题一个训练集。所以我想如果有人尝试使用 mllib,我会分享我的经验...
概率可以很容易地计算如下:-
# say you have a testset against which you want to run your classifier
(trainingset, testset) =data.randomSplit([0.7, 0.3])
# I converted the spark dataset containing the test data to pandas
ptd=testData.toPandas()
#Now get a count of number of labels matching the predictions
correct = ((ptd.label-1) == (predictions)).sum()
# here we had to change the labels from 0-9 as opposed to 1-10 since
#labels take the values from 0 .. numClasses-1
m=ptd.shape[0]
print((correct/m)*100)
我正在尝试提取我使用 PySpark 训练的随机森林对象的 class 概率。但是,我在文档中的任何地方都没有看到它的示例,也不是 RandomForestModel
.
如何从 PySpark 中的 RandomForestModel
classifier 提取 class 概率?
这里是文档中提供的示例代码,只提供最后的class(不是概率):
from pyspark.mllib.tree import RandomForest
from pyspark.mllib.util import MLUtils
# Load and parse the data file into an RDD of LabeledPoint.
data = MLUtils.loadLibSVMFile(sc, 'data/mllib/sample_libsvm_data.txt')
# Split the data into training and test sets (30% held out for testing)
(trainingData, testData) = data.randomSplit([0.7, 0.3])
# Train a RandomForest model.
# Empty categoricalFeaturesInfo indicates all features are continuous.
# Note: Use larger numTrees in practice.
# Setting featureSubsetStrategy="auto" lets the algorithm choose.
model = RandomForest.trainClassifier(trainingData, numClasses=2, categoricalFeaturesInfo={},
numTrees=3, featureSubsetStrategy="auto",
impurity='gini', maxDepth=4, maxBins=32)
# Evaluate model on test instances and compute test error
predictions = model.predict(testData.map(lambda x: x.features))
我没有看到任何 model.predict_proba()
方法 -- 我该怎么办??
据我所知,当前版本 (1.2.1) 不支持此功能。本机 Scala 代码 (tree.py) 上的 Python 包装器仅定义 'predict' 函数,这些函数依次调用相应的 Scala 对应项 (treeEnsembleModels.scala)。后者通过在二元决策之间进行投票来做出决策。一个更简洁的解决方案是提供一个概率预测,它可以任意设定阈值或用于像 sklearn 中的 ROC 计算。应该为将来的版本添加此功能!
作为一种变通方法,我将 predict_proba 作为纯 Python 函数实现(参见下面的示例)。它既不优雅也不高效,因为它 运行 是对森林中单个决策树集的循环。诀窍 - 或者更确切地说是一个肮脏的黑客 - 是访问 Java 决策树模型的数组并将它们转换为 Python 对应物。之后,您可以计算单个模型对整个数据集的预测,并使用 'zip' 在 RDD 中累积它们的总和。除以树的数量得到期望的结果。对于大型数据集,在主节点中对少量决策树进行循环应该是可以接受的。
由于难以将 Python 集成到 Spark(运行 in Java),下面的代码相当棘手。应该非常小心,不要将任何复杂的数据发送到工作节点,这会由于序列化问题导致崩溃。引用 Spark 上下文的代码不能在工作节点上 运行。此外,不能序列化引用任何 Java 代码的代码。例如,在下面的代码中使用 len(trees) 而不是 ntrees 可能很诱人——砰!在 Java/Scala 中编写这样的包装器可以更优雅,例如通过 运行 在工作节点上的决策树上循环,从而减少通信成本。
下面的测试函数表明 predict_proba 给出了与原始示例中使用的预测相同的测试错误。
def predict_proba(rf_model, data):
'''
This wrapper overcomes the "binary" nature of predictions in the native
RandomForestModel.
'''
# Collect the individual decision tree models by calling the underlying
# Java model. These are returned as JavaArray defined by py4j.
trees = rf_model._java_model.trees()
ntrees = rf_model.numTrees()
scores = DecisionTreeModel(trees[0]).predict(data.map(lambda x: x.features))
# For each decision tree, apply its prediction to the entire dataset and
# accumulate the results using 'zip'.
for i in range(1,ntrees):
dtm = DecisionTreeModel(trees[i])
scores = scores.zip(dtm.predict(data.map(lambda x: x.features)))
scores = scores.map(lambda x: x[0] + x[1])
# Divide the accumulated scores over the number of trees
return scores.map(lambda x: x/ntrees)
def testError(lap):
testErr = lap.filter(lambda (v, p): v != p).count() / float(testData.count())
print('Test Error = ' + str(testErr))
def testClassification(trainingData, testData):
model = RandomForest.trainClassifier(trainingData, numClasses=2,
categoricalFeaturesInfo={},
numTrees=50, maxDepth=30)
# Compute test error by thresholding probabilistic predictions
threshold = 0.5
scores = predict_proba(model,testData)
pred = scores.map(lambda x: 0 if x < threshold else 1)
lab_pred = testData.map(lambda lp: lp.label).zip(pred)
testError(lab_pred)
# Compute test error by comparing binary predictions
predictions = model.predict(testData.map(lambda x: x.features))
labelsAndPredictions = testData.map(lambda lp: lp.label).zip(predictions)
testError(labelsAndPredictions)
总而言之,这是学习 Spark 的一个很好的练习!
但是,它将在 Spark 1.5.0 和新的 Spark-ML API 中可用。
现在可用。
Spark ML 提供:
- a
predictionCol
包含 预测标签 - 和一个
probabilityCol
,其中包含每个标签 概率的向量 ,这是你在找什么! - 您还可以访问原始计数
有关更多详细信息,请参阅 Spark 文档: http://spark.apache.org/docs/latest/ml-classification-regression.html#output-columns-predictions
可能人们会继续使用这个 post,但我今天在尝试计算 multi-class classifier 的准确性时遇到了同样的问题一个训练集。所以我想如果有人尝试使用 mllib,我会分享我的经验...
概率可以很容易地计算如下:-
# say you have a testset against which you want to run your classifier
(trainingset, testset) =data.randomSplit([0.7, 0.3])
# I converted the spark dataset containing the test data to pandas
ptd=testData.toPandas()
#Now get a count of number of labels matching the predictions
correct = ((ptd.label-1) == (predictions)).sum()
# here we had to change the labels from 0-9 as opposed to 1-10 since
#labels take the values from 0 .. numClasses-1
m=ptd.shape[0]
print((correct/m)*100)