了解 Spark RandomForest featureImportances 结果
Understanding Spark RandomForest featureImportances results
我正在使用 RandomForest.featureImportances
但我不明白输出结果。
我有 12 个特征,这是我得到的输出。
我知道这可能不是特定于 apache-spark 的问题,但我找不到任何地方可以解释输出。
// org.apache.spark.mllib.linalg.Vector = (12,[0,1,2,3,4,5,6,7,8,9,10,11],
[0.1956128039688559,0.06863606797951556,0.11302128590305296,0.091986700351889,0.03430651625283274,0.05975817050022879,0.06929766152519388,0.052654922125615934,0.06437052114945474,0.1601713590349946,0.0324327322375338,0.057751258970832206])
给定树集成模型,RandomForest.featureImportances
计算每个特征的重要性。
根据 Leo Breiman 和 Adele Cutler 的 "Random Forests" 文档对 Gini 重要性的解释,并遵循 scikit-learn 的实施,这将 "Gini" 重要性的想法推广到其他损失。
对于树的集合,包括 boosting 和 bagging,Hastie 等人。建议使用整体中所有树的单个树重要性的平均值。
而这个特征的重要性计算如下:
- 树木平均数:
- 增益的重要性(特征 j)= 总和(在特征 j 上分裂的节点),其中增益按通过节点的实例数缩放
- 将树的重要性归一化为 1。
- 将特征重要性向量归一化为 1。
参考文献: Hastie, Tibshirani, Friedman. "The Elements of Statistical Learning, 2nd Edition." 2001. - 15.3.2 变量重要性第 593 页。
让我们回到您的重要性向量:
val importanceVector = Vectors.sparse(12,Array(0,1,2,3,4,5,6,7,8,9,10,11), Array(0.1956128039688559,0.06863606797951556,0.11302128590305296,0.091986700351889,0.03430651625283274,0.05975817050022879,0.06929766152519388,0.052654922125615934,0.06437052114945474,0.1601713590349946,0.0324327322375338,0.057751258970832206))
首先,让我们按重要性对这些特征进行排序:
importanceVector.toArray.zipWithIndex
.map(_.swap)
.sortBy(-_._2)
.foreach(x => println(x._1 + " -> " + x._2))
// 0 -> 0.1956128039688559
// 9 -> 0.1601713590349946
// 2 -> 0.11302128590305296
// 3 -> 0.091986700351889
// 6 -> 0.06929766152519388
// 1 -> 0.06863606797951556
// 8 -> 0.06437052114945474
// 5 -> 0.05975817050022879
// 11 -> 0.057751258970832206
// 7 -> 0.052654922125615934
// 4 -> 0.03430651625283274
// 10 -> 0.0324327322375338
这是什么意思?
这意味着您的第一个特征(索引 0)是最重要的特征,权重约为 0.19,而您的第 11 个(索引 10)特征在您的模型中最不重要。
补充上一个答案:
我遇到的一个问题是以 (featureName,Importance) 的形式转储结果,因为 csv.One 可以获得特征输入向量的元数据
val featureMetadata = predictions.schema("features").metadata
这是此元数据的 json 结构:
{
"ml_attr": {
"attrs":
{"numeric":[{idx:I,name:N},...],
"nominal":[{vals:V,idx:I,name:N},...]},
"num_attrs":#Attr
}
}
}
重要性提取代码:
val attrs =featureMetadata.getMetadata("ml_attr").getMetadata("attrs")
val f: (Metadata) => (Long,String) = (m => (m.getLong("idx"), m.getString("name")))
val nominalFeatures= attrs.getMetadataArray("nominal").map(f)
val numericFeatures = attrs.getMetadataArray("numeric").map(f)
val features = (numericFeatures ++ nominalFeatures).sortBy(_._1)
val fImportance = pipeline.stages.filter(_.uid.startsWith("rfc")).head.asInstanceOf[RandomForestClassificationModel].featureImportances.toArray.zip(features).map(x=>(x._2._2,x._1)).sortBy(-_._2)
//Save It now
sc.parallelize(fImportance.toSeq, 1).map(x => s"${x._1},${x._2}").saveAsTextFile(fPath)
我正在使用 RandomForest.featureImportances
但我不明白输出结果。
我有 12 个特征,这是我得到的输出。
我知道这可能不是特定于 apache-spark 的问题,但我找不到任何地方可以解释输出。
// org.apache.spark.mllib.linalg.Vector = (12,[0,1,2,3,4,5,6,7,8,9,10,11],
[0.1956128039688559,0.06863606797951556,0.11302128590305296,0.091986700351889,0.03430651625283274,0.05975817050022879,0.06929766152519388,0.052654922125615934,0.06437052114945474,0.1601713590349946,0.0324327322375338,0.057751258970832206])
给定树集成模型,RandomForest.featureImportances
计算每个特征的重要性。
根据 Leo Breiman 和 Adele Cutler 的 "Random Forests" 文档对 Gini 重要性的解释,并遵循 scikit-learn 的实施,这将 "Gini" 重要性的想法推广到其他损失。
对于树的集合,包括 boosting 和 bagging,Hastie 等人。建议使用整体中所有树的单个树重要性的平均值。
而这个特征的重要性计算如下:
- 树木平均数:
- 增益的重要性(特征 j)= 总和(在特征 j 上分裂的节点),其中增益按通过节点的实例数缩放
- 将树的重要性归一化为 1。
- 将特征重要性向量归一化为 1。
参考文献: Hastie, Tibshirani, Friedman. "The Elements of Statistical Learning, 2nd Edition." 2001. - 15.3.2 变量重要性第 593 页。
让我们回到您的重要性向量:
val importanceVector = Vectors.sparse(12,Array(0,1,2,3,4,5,6,7,8,9,10,11), Array(0.1956128039688559,0.06863606797951556,0.11302128590305296,0.091986700351889,0.03430651625283274,0.05975817050022879,0.06929766152519388,0.052654922125615934,0.06437052114945474,0.1601713590349946,0.0324327322375338,0.057751258970832206))
首先,让我们按重要性对这些特征进行排序:
importanceVector.toArray.zipWithIndex
.map(_.swap)
.sortBy(-_._2)
.foreach(x => println(x._1 + " -> " + x._2))
// 0 -> 0.1956128039688559
// 9 -> 0.1601713590349946
// 2 -> 0.11302128590305296
// 3 -> 0.091986700351889
// 6 -> 0.06929766152519388
// 1 -> 0.06863606797951556
// 8 -> 0.06437052114945474
// 5 -> 0.05975817050022879
// 11 -> 0.057751258970832206
// 7 -> 0.052654922125615934
// 4 -> 0.03430651625283274
// 10 -> 0.0324327322375338
这是什么意思?
这意味着您的第一个特征(索引 0)是最重要的特征,权重约为 0.19,而您的第 11 个(索引 10)特征在您的模型中最不重要。
补充上一个答案:
我遇到的一个问题是以 (featureName,Importance) 的形式转储结果,因为 csv.One 可以获得特征输入向量的元数据
val featureMetadata = predictions.schema("features").metadata
这是此元数据的 json 结构:
{
"ml_attr": {
"attrs":
{"numeric":[{idx:I,name:N},...],
"nominal":[{vals:V,idx:I,name:N},...]},
"num_attrs":#Attr
}
}
}
重要性提取代码:
val attrs =featureMetadata.getMetadata("ml_attr").getMetadata("attrs")
val f: (Metadata) => (Long,String) = (m => (m.getLong("idx"), m.getString("name")))
val nominalFeatures= attrs.getMetadataArray("nominal").map(f)
val numericFeatures = attrs.getMetadataArray("numeric").map(f)
val features = (numericFeatures ++ nominalFeatures).sortBy(_._1)
val fImportance = pipeline.stages.filter(_.uid.startsWith("rfc")).head.asInstanceOf[RandomForestClassificationModel].featureImportances.toArray.zip(features).map(x=>(x._2._2,x._1)).sortBy(-_._2)
//Save It now
sc.parallelize(fImportance.toSeq, 1).map(x => s"${x._1},${x._2}").saveAsTextFile(fPath)