【问题标题】:Understanding Spark RandomForest featureImportances results了解 Spark RandomForest 功能重要性结果
【发布时间】:2016-10-19 02:40:55
【问题描述】:

我正在使用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])

【问题讨论】:

    标签: apache-spark classification random-forest apache-spark-mllib


    【解决方案1】:

    给定一个树集成模型,RandomForest.featureImportances 计算每个特征的重要性

    这将“基尼”重要性的概念推广到其他损失,遵循 Leo Breiman 和 Adele Cutler 的“随机森林”文档中对基尼重要性的解释,并遵循 scikit-learn 的实施。

    对于树的集合,包括提升和装袋,Hastie 等人。建议使用集合中所有树的单个树重要性的平均值。

    这个特征的重要性计算如下:

    • 树的平均值:
      • importance(feature 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)特征在您的模型中是最不重要的。

    【讨论】:

    • 很好,详细的回答,谢谢!我正在做多类分类 - 4 个类,有没有办法计算每个类的特征重要性?
    • 目前看来不像。
    • @other15,我的第一个想法是为你的 4 个类中的每一个训练一个二元分类器。然后你会有每个特征的重要性。不知道,我知道,但它应该可以工作。
    • 这不是一个很好的方法。您正在考虑一个强有力的启发式说法,即每个分类器的分类都是正确的,但情况可能并非如此。如果数据不平衡,您的结果将毫无意义。
    • 酷。我会在那里开始我的搜索。谢谢。
    【解决方案2】:

    补充上一个答案:

    我遇到的一个问题是以 (featureName,Importance) 的形式将结果转储为 csv。可以将特征输入向量的元数据获取为

     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)
    

    【讨论】:

      猜你喜欢
      • 2020-05-12
      • 2017-12-23
      • 2015-07-25
      • 2023-01-29
      • 2012-07-28
      • 2019-04-17
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多