PySpark 和 MLLib:随机森林特征的重要性

Posted

技术标签:

【中文标题】PySpark 和 MLLib:随机森林特征的重要性【英文标题】:PySpark & MLLib: Random Forest Feature Importances 【发布时间】:2015-05-12 09:05:52 【问题描述】:

我正在尝试提取我使用 PySpark 训练的随机森林对象的特征重要性。但是,我在文档中的任何地方都没有看到这样做的示例,也不是 RandomForestModel 的方法。

如何从 PySpark 中的 RandomForestModel 回归器或分类器中提取特征重要性?

这是文档中提供的示例代码,可帮助我们入门;但是,其中没有提及特征重要性。

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)

我没有看到可用的model.__featureImportances_ 属性——我在哪里可以找到这个?

【问题讨论】:

有人对这个问题有更新吗?现在有没有实现 model.__featureImportances_ 的 PySpark 实现? @PabloO 我已经发布了更新的答案 【参考方案1】:

现在 Spark ML 似乎有一种直接的方法可以做到这一点。见https://kb.databricks.com/machine-learning/extract-feature-info.html

这是关键代码:

pipeline = Pipeline(stages=[indexer, assembler, decision_tree)
DTmodel = pipeline.fit(train)
va = dtModel.stages[-2]
tree = DTmodel.stages[-1]

display(tree) #visualize the decision tree model
print(tree.toDebugString) #print the nodes of the decision tree model

list(zip(va.getInputCols(), tree.featureImportances))

【讨论】:

【参考方案2】:

更新版本 > 2.0.0

从 2.0.0 版本开始,如您所见 here,FeatureImportances 可用于随机森林。

其实你可以找到here那个:

DataFrame API 支持两种主要的树集成算法:随机森林和梯度提升树 (GBT)。两者都使用 spark.ml 决策树作为基础模型。

用户可以在 MLlib Ensemble 指南中找到有关集成算法的更多信息。 在本节中,我们将演示用于集成的 DataFrame API。

此 API 与原始 MLlib 集成 API 的主要区别在于:

支持 DataFrames 和 ML Pipelines 分类与回归的分离 使用 DataFrame 元数据来区分连续和分类特征 随机森林的更多功能:特征重要性估计,以及用于分类的每个类别的预测概率(也称为类别条件概率)。

如果你想拥有特征重要性值,你必须使用 ml 包,而不是 mllib,并使用数据框。

下面有一个例子,你可以找到here:

# IMPORT
>>> import numpy
>>> from numpy import allclose
>>> from pyspark.ml.linalg import Vectors
>>> from pyspark.ml.feature import StringIndexer
>>> from pyspark.ml.classification import RandomForestClassifier

# PREPARE DATA
>>> df = spark.createDataFrame([
...     (1.0, Vectors.dense(1.0)),
...     (0.0, Vectors.sparse(1, [], []))], ["label", "features"])
>>> stringIndexer = StringIndexer(inputCol="label", outputCol="indexed")
>>> si_model = stringIndexer.fit(df)
>>> td = si_model.transform(df)

# BUILD THE MODEL
>>> rf = RandomForestClassifier(numTrees=3, maxDepth=2, labelCol="indexed", seed=42)
>>> model = rf.fit(td)

# FEATURE IMPORTANCES
>>> model.featureImportances
SparseVector(1, 0: 1.0) 

【讨论】:

如果您需要原始功能名称中的 featureImportances,请使用此功能:timlrx.com/2018/06/19/…【参考方案3】:

我相信这现在可行。您可以致电:

from pyspark.ml.classification import RandomForestClassifier
rf = RandomForestClassifier()
model = rf.fit(data)
print model.featureImportances

在 RandomForestClassifier 上运行拟合会返回一个 RandomForestClassificationModel,该模型已计算出所需的 featureImportances。我希望这会有所帮助:)

【讨论】:

【参考方案4】:

现在在 Spark 1.5 中实现了特征重要性。 See resolved JIRA issue.你可以得到一个特征重要性向量:

val importances: Vector = model.featureImportances

【讨论】:

这实际上只是在 Scala 方面,在 PySpark 中还没有。也许下一个版本。 另外,它只存在于ML实现中,不存在于MLlib中【参考方案5】:

我不得不让你失望,但是 RandomForest 的 MLlib 实现中的特征重要性只是没有计算出来,所以你不能从任何地方得到它们,除非你自己实现它们的计算。

这里是如何找到它的:

你调用了一个函数 RandomForest.trainClassifier 在这里 deinfed https://github.com/apache/spark/blob/branch-1.3/python/pyspark/mllib/tree.py

它调用 callMLlibFunc("trainRandomForestModel", ...),这是对 Scala 函数 RandomForest.trainClassifierRandomForest.trainRegressor(取决于算法)的调用,它会返回 RandomForestModel 对象。

此对象在https://github.com/apache/spark/blob/branch-1.3/mllib/src/main/scala/org/apache/spark/mllib/tree/model/treeEnsembleModels.scala 中进行了描述,并扩展了同一源文件中定义的TreeEnsembleModel。不幸的是,这个类只存储算法(回归或分类)、树本身、树的相对权重和组合策略(总和、平均、投票)。不幸的是,它不存储特征重要性,甚至不计算它们(计算算法见https://github.com/apache/spark/blob/branch-1.3/mllib/src/main/scala/org/apache/spark/mllib/tree/RandomForest.scala)

【讨论】:

如果您通过自己实现功能来为 MLlib 做出贡献,您可以采用 sklearn 实现。github.com/scikit-learn/scikit-learn/blob/master/sklearn/… - 方法 feature_importances_ 收集底层树的功能重要性并将它们组合在一起通过计算平均值。这里的代码 - github.com/scikit-learn/scikit-learn/blob/… - 方法 compute_feature_importances 用于估计单个树的特征重要性 谢谢——是的,我们正在尝试类似的东西,但由于我们只有树调试输出(不是每个特征拆分的杂质减少),我们只能粗略估计重要性.有没有办法从每个 MLLib 树拆分中减少杂质? 您在这里唯一能做的就是通过将估计决策树特征重要性的代码移植到 Scala 并将此补丁推送到 MLlib 代码来为 MLlib 做出贡献。如果没有这个,你的估计只会像你提到的那样粗略。

以上是关于PySpark 和 MLLib:随机森林特征的重要性的主要内容,如果未能解决你的问题,请参考以下文章

带有列名的pyspark随机森林分类器特征重要性

PySpark MLLIB 随机森林:预测总是 0

在 PySpark mllib 中使用随机森林的非法参数异常

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

如何在随机森林中使用 Spark 特征重要性?

pyspark GBTRegressor 特征重要度 及排序