如何在Spark的随机森林模型中访问单个预测?

5
我希望使用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个回答

5

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]

但是最好使用机器学习模型:
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框架中并行化预测向量? - dbaron
t.predict(testData)是分布式的,但你不能分发外部循环(即推导式)。这意味着你需要numTrees个作业。 - zero323
关于完整相似矩阵,它确切地与大小有关。你可以尝试应用一些近似方法,只比较最佳候选者。 - zero323
例如,有https://github.com/soundcloud/cosine-lsh-join-spark,但它没有Python API。 - zero323
我会研究一下并将其结果与我目前得到的结果进行比较。谢谢! :) - dbaron
嗨@dbaron,我有完全相同的问题。我正在尝试使用Pypsark获取接近矩阵。你最终得到了吗?你认为使用Spark值得吗? - Carmen Pérez Carrillo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接