如何访问 Spark RandomForest 中的单个预测?

Posted

技术标签:

【中文标题】如何访问 Spark RandomForest 中的单个预测?【英文标题】:How to access individual predictions in Spark RandomForest? 【发布时间】:2016-06-02 01:47:19 【问题描述】:

我希望使用 pyspark.mllib.tree.RandomForest 模块来获取我的观察的邻近矩阵。

直到现在,我的数据还小到可以直接加载到内存中。因此,我使用 sklearn.ensemble.RandomForestClassifier 通过以下方式获取邻近矩阵:假设 X 是包含特征的矩阵,Y 是包含标签的向量。我训练了随机森林来区分标签为“0”和标签“1”的对象。有了训练有素的随机森林,我想通过计算两个观察有多少决策树具有相同的最终节点(=叶)来衡量我的数据集中每对观察之间的接近度。因此,对于 100 棵决策树,两个观察值之间的邻近度度量的范围可以从 0(从不落在同一个最终叶)和 100(在所有决策树中都落在同一个最终叶)。这个的python实现:

import numpy
from sklearn import ensemble

## data
print X.shape, Y.shape # X is a matrix that holds the 4281 features and contains 8562 observations and Y contains 8562 labels
>> (8562, 4281) (8562,)

## train the tree
n_trees = 100
rand_tree = sklearn.ensemble.RandomForestClassifier(n_estimators=n_tress)
rand_tree.fit(X, Y)

## get proximity matrix
apply_mat = rand_tree.apply(X)
obs_num = len(apply_mat)
sim_mat = numpy.eye(obs_num) * len(apply_mat[0]) # max values that they can be similar at = N estimators

for i in xrange(obs_num):
    for j in xrange(i, obs_num):
        vec_i = apply_mat[i]
        vec_j = apply_mat[j]
        sim_val = len(vec_i[vec_i==vec_j])
        sim_mat[i][j] = sim_val
        sim_mat[j][i] = sim_val

sim_mat_norm = sim_mat / len(apply_mat[0])
print sim_mat_norm.shape
>> (8562, 8562)

现在,我处理的数据太大而无法放入内存,因此我决定改用 Spark。我能够加载数据并对其进行拟合,但我没有找到将随机森林“应用”到数据以获得邻近矩阵的方法。有没有办法得到它? (我使用与 Spark 文档中相同的实现:https://spark.apache.org/docs/1.2.0/mllib-ensembles.html#classification):

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

model = RandomForest.trainClassifier(trainingData, numClasses=2, categoricalFeaturesInfo=,
                                 numTrees=3, featureSubsetStrategy="auto",
                                 impurity='gini', maxDepth=4, maxBins=32)

我也很高兴听到其他可以解决我问题的想法。 谢谢!

【问题讨论】:

【参考方案1】:

PySpark MLlib 模型不提供直接访问此信息的方法。从理论上讲,您可以尝试直接提取模型并为每棵树单独预测:

from pyspark.mllib.tree import DecisionTreeMode

numTrees = 3
trees = [DecisionTreeModel(model._java_model.trees()[i])
    for i in range(numTrees)]

predictions = [t.predict(testData) for t in trees]

但使用 ML 模型可能会更好:

from pyspark.ml.feature import StringIndexer
from pyspark.ml.classification import RandomForestClassifier

df = sqlContext.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt")

indexer = StringIndexer(inputCol="label", outputCol="indexed").fit(df)
df_indexed = indexer.transform(df)

model = RandomForestClassifier(
    numTrees=3, maxDepth=2, labelCol="indexed", seed=42
).fit(df_indexed)

并使用rawPredictionprobability 列:

model.transform(df).select("rawPrediction", "probability").show(5, False)

## +---------------------------------------+-----------------------------------------+
## |rawPrediction                          |probability                              |
## +---------------------------------------+-----------------------------------------+
## |[0.0,3.0]                              |[0.0,1.0]                                |
## |[2.979591836734694,0.02040816326530612]|[0.9931972789115647,0.006802721088435374]|
## |[2.979591836734694,0.02040816326530612]|[0.9931972789115647,0.006802721088435374]|
## |[2.979591836734694,0.02040816326530612]|[0.9931972789115647,0.006802721088435374]|
## |[2.979591836734694,0.02040816326530612]|[0.9931972789115647,0.006802721088435374]|
## +---------------------------------------+-----------------------------------------+

注意:如果您认为您的数据需要 Spark,那么构建全距离/相似度矩阵不太可能是一个好主意。只是说说而已。

【讨论】:

感谢您的帮助。您是否因为我的数据量大而认为这不是一个好主意?我实际上需要从我的约 30M 对象中找到约 1% 的最近对象对(因此我想计算邻近矩阵)。这些对象有很多特征(4000),因此我决定使用 RF + 距离矩阵而不是使用 KDE 或其他算法,因为它的自然并行化。重新考虑您的第一个建议 - 我还能在 Spark 框架中并行化预测向量吗? t.predict(testData) 已分发,但您不能分发外循环(即理解)。这意味着您需要numTrees 工作。 关于完全相似矩阵,它的大小正好是大小。不过,您可以尝试应用一些近似值并仅比较最佳候选者。 有例如github.com/soundcloud/cosine-lsh-join-spark,但它没有Python API。 我会对此进行调查,并将其结果与我目前得到的结果进行比较。谢谢! :)

以上是关于如何访问 Spark RandomForest 中的单个预测?的主要内容,如果未能解决你的问题,请参考以下文章

将 KDDCup 99 数据与 Spark MLLib RandomForest 一起使用

如何使用 pySpark 决定将 numClasses 参数传递给 SPark MLlib 中的随机森林算法

如何将 spark DataFrame 转换为 RDD mllib LabeledPoints?

在 R 中使用 randomForest 包,如何从分类模型中获取概率?

如何知道 RandomForest 中特定样本的特征及其贡献

如何在 R 中并行运行多个内核上的 randomForest? [复制]