特征重要性 - Bagging、scikit-learn

Feature importances - Bagging, scikit-learn

对于一个项目,我正在使用 scikit-learn 的回归算法(随机森林、额外树、Adaboost 和装袋)比较许多决策树。 为了比较和解释它们,我使用了特征 importance ,尽管对于装袋决策树这看起来不可用。

我的问题:有人知道如何获取 Bagging 的特征重要性列表吗?

你好,Kornee

你说的是 BaggingClassifier 吗?它可以与许多基本估计器一起使用,因此没有实现特征重要性。有一些独立于模型的方法来计算特征重要性(参见 https://github.com/scikit-learn/scikit-learn/issues/8898),scikit-learn 不使用它们。

如果决策树作为基础估计器,您可以自己计算特征重要性:它只是 bagging.estimators_ 中所有树的 tree.feature_importances_ 的平均值:

import numpy as np
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)
clf = BaggingClassifier(DecisionTreeClassifier())
clf.fit(X, y)

feature_importances = np.mean([
    tree.feature_importances_ for tree in clf.estimators_
], axis=0)

RandomForestClassifer 在内部进行相同的计算。

我遇到了同样的问题,平均特征重要性是我感兴趣的。此外,我需要有一个 feature_importance_ 属性由装袋分类器对象公开(即可访问)。这对于在另一个 scikit-learn 算法中使用是必要的(即带有 ROC_AUC 记分员的 RFE)。

我选择重载 BaggingClassifier,以直接访问基本估计量的均值 feature_importance(或“coef_”参数)。

操作方法如下:

class BaggingClassifierCoefs(BaggingClassifier):
    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        # add attribute of interest
        self.feature_importances_ = None
    def fit(self, X, y, sample_weight=None):
        # overload fit function to compute feature_importance
        fitted = self._fit(X, y, self.max_samples, sample_weight=sample_weight) # hidden fit function
        if hasattr(fitted.estimators_[0], 'feature_importances_'):
            self.feature_importances_ =  np.mean([tree.feature_importances_ for tree in fitted.estimators_], axis=0)
        else:
            self.feature_importances_ =  np.mean([tree.coef_ for tree in fitted.estimators_], axis=0)
    return(fitted)

扩展 CharlesG 发布的内容,这是我重载 BaggingRegressor 的解决方案(同样适用于 BaggingClassifier)。

class myBaggingRegressor(BaggingRegressor):
    def fit(self, X, y):
        fitd = super().fit(X, y)
        # need to pad features?
        if self.max_features == 1.0:
            # compute feature importances or coefficients
            if hasattr(fitd.estimators_[0], 'feature_importances_'):
                self.feature_importances_ =  np.mean([est.feature_importances_ for est in fitd.estimators_], axis=0)
            else:
                self.coef_ =  np.mean([est.coef_ for est in fitd.estimators_], axis=0)
                self.intercept_ =  np.mean([est.intercept_ for est in fitd.estimators_], axis=0)
        else:
            # need to process results into the right shape
            coefsImports = np.empty(shape=(self.n_features_, self.n_estimators), dtype=float)
            coefsImports.fill(np.nan)
            if hasattr(fitd.estimators_[0], 'feature_importances_'):
                # store the feature importances
                for idx, thisEstim in enumerate(fitd.estimators_):
                    coefsImports[fitd.estimators_features_[idx], idx] = thisEstim.feature_importances_
                # compute average
                self.feature_importances_ = np.nanmean(coefsImports, axis=1)
            else:
                # store the coefficients & intercepts
                self.intercept_ = 0
                for idx, thisEstim in enumerate(fitd.estimators_):
                    coefsImports[fitd.estimators_features_[idx], idx] = thisEstim.coefs_
                    self.intercept += thisEstim.intercept_
                # compute
                self.intercept /= self.n_estimators
                # average
                self.coefs_ = np.mean(coefsImports, axis=1)                
        return fitd

如果 max_features <> 1.0 这会正确处理,但我想如果 bootstrap_features=True.

将无法正常工作

我想这是因为 sklearn 自 2017 年以来已经发展了很多,但无法让它与构造函数一起工作,而且它似乎并不是完全必要的——唯一的原因是预先指定feature_importances_ 属性为 None。但是,在调用 fit() 之前它甚至不应该存在。