【问题标题】:Scikit-Learn - How to get non-normalized importance score from RandomForestRegressorScikit-Learn - 如何从 RandomForestRegressor 获得非标准化的重要性分数
【发布时间】:2021-05-01 19:40:25
【问题描述】:

我想从 RandomForestRegressor 获得非标准化的重要性分数。

拟合回归器后,我可以访问包含归一化重要性分数的feature_importances_

为了获得非标准化分数,我尝试了这个,但没有奏效。我无法获得正确的值:

arr = []
for i in range(0,len(clf.feature_importances_)):
  arr.append(np.array(clf.feature_importances_)[0:i].sum())

non_normalized = clf.feature_importances_*arr

是否有禁用标准化的选项?

【问题讨论】:

    标签: python scikit-learn random-forest


    【解决方案1】:

    重要性始终归一化为总和为 1,即使您向下到每个决策树回归量,例如:

    import numpy as np
    import pandas as pd
    from sklearn.datasets import load_boston
    from sklearn.ensemble import RandomForestRegressor
    
    boston = load_boston()
    
    X = pd.DataFrame(boston.data, columns=boston.feature_names)
    y = boston.target
    
    X_train, X_test,y_train, y_test = train_test_split(X,y,test_size=0.3)
    
    rf = RandomForestRegressor(n_estimators=100)
    rf.fit(X_train, y_train)
    

    您可以在每棵树中看到,重要性值已经归一化:

    [x.feature_importances_.sum() for x in rf.estimators_]
     
    [1.0,
    0.9999999999999999,
     1.0,
     1.0,
     0.9999999999999999,
     1.0,
     0.9999999999999998,...
    

    提取树的 mse 减少并重新计算并非易事。一种替代解决方案是使用 permutation_importance 以 r 平方或 rmse 作为度量,以估计每个特征的重要性,这些值未标准化:

    from sklearn.inspection import permutation_importance
    importance_r2 = permutation_importance(rf, X_test, y_test,scoring="r2")
    importance_rmse = permutation_importance(rf, X_test,
     y_test,scoring="neg_root_mean_squared_error")
    

    并绘制结果:

    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
    ax1.boxplot(importance_r2.importances.T, vert=False,labels=X_test.columns)
    ax1.set_xlabel('Decrease in R2')
    ax2.boxplot(importance_rmse.importances.T, vert=False,labels=X_test.columns)
    ax2.set_xlabel('Decrease in RMSE')
    fig.tight_layout()
    

    【讨论】:

      【解决方案2】:

      由于随机森林是一种基于决策树的集成方法,您可以使用 RandomForestRegressor 的属性clf.estimators_ 访问底层决策树。通过树列表,您可以访问每个决策树的特征重要性:

      feat_imp = [tree.feature_importances_ for tree in clf.estimators_]
      

      【讨论】:

      • 谢谢,但是当引导为 TRUE 时我还需要 OOB,而且似乎每棵树的 OOB 都不可用?
      【解决方案3】:

      默认情况下,重要性被归一化为总和为 1。但是,可以通过访问随机森林或决策树模型的树并使用 normalize=False 调用函数来计算重要性来改变这一点。

      这里首先是一个单决策树回归的例子:

      from sklearn.datasets import load_diabetes
      from sklearn import tree
      
      X, y = load_diabetes(return_X_y=True)
      model = tree.DecisionTreeRegressor(random_state=0)
      model.fit(X,y)
      model.tree_.compute_feature_importances(normalize=False)
      
      array([ 273.29445957,   55.8130721 , 1383.95383906,  447.64458872,
              414.2412427 ,  412.20392795,  423.76003212,   77.75521807,
             2063.37527614,  377.84324049])
      

      对于随机森林,有一个额外的步骤。我们需要首先访问每棵树,计算每棵树的特征重要性,然后对树进行平均:

      import numpy as np
      from sklearn.datasets import load_diabetes
      from sklearn.ensemble import RandomForestRegressor
      
      X, y = load_diabetes(return_X_y=True)
      model = RandomForestRegressor(random_state=0)
      model.fit(X,y)
      
      importances = np.zeros((model.n_estimators, model.n_features_))
      for i,tree in enumerate(model.estimators_):
          importances[i] = tree.tree_.compute_feature_importances(normalize=False)
      np.mean(importances, axis=0)
      
      array([ 363.40653952,   78.42318883, 1767.47349563,  564.32760593,
              275.84188613,  318.61079764,  310.57670354,  160.56454205,
             1655.62870107,  424.28382897])
      

      【讨论】:

        猜你喜欢
        • 2015-11-21
        • 2021-01-15
        • 2018-10-08
        • 2016-04-18
        • 2014-03-31
        • 2019-11-14
        • 2018-08-12
        • 2021-06-15
        相关资源
        最近更新 更多