嵌入式特征选择方法将选择过程直接融入机器学习模型的构建。树模型是一种很常用且高效的内嵌技术。决策树、随机森林和梯度提升等算法在训练时会自行计算每个特征的重要性分数。树模型如何评估特征基于树的模型通过根据特征值递归地分割数据来构建一系列决策规则。这些模型中特征重要性的主旨是,那些在分割数据、提高节点纯度(用于分类)或减小方差(用于回归)方面更有效的特征被认为更重要。以单个决策树为例。当树算法决定在哪里分割一个节点时,它会评估不同特征和阈值上的潜在分割点。选择产生最佳分割的特征和阈值(例如,分类中基尼不纯度降低最大,或回归中均方误差减少最多)。在树中更上方(靠近根部)被选作分割点或被用于更多分割的特征通常对最终预测有更大影响。对于随机森林或梯度提升机等集成模型,它们结合了多个树的预测,特征重要性通常计算为该特征在集成中所有树上的平均重要性。这种平均过程使得重要性分数比单个决策树的更稳定。基尼重要性(平均不纯度下降): 常用于分类树(如CART)。它衡量的是通过特定特征分割所实现的节点不纯度总减少量(按到达该节点的概率加权),并在集成中的所有树上取平均。减少量越大,表明该特征对分类越重要。平均准确度下降(置换重要性): 虽然不像基尼重要性那样在训练期间直接计算,但置换重要性与之相关且常被使用。它衡量的是当某个特征的值被随机打乱时,模型准确度的下降程度。这种方法可用于任何已训练好的模型,不限于树模型,但常与树模型方法并提。它可能比基尼重要性更稳定,特别是在特征相关联时。均方误差减少: 对于回归任务,重要性通常基于特征分割能将节点内方差(MSE)减少多少,并在所有树上取平均。在Scikit-learn中获取特征重要性在Scikit-learn中,训练基于树的模型后,获取特征重要性十分直接。大多数集成树估计器(如RandomForestClassifier、RandomForestRegressor、GradientBoostingClassifier、GradientBoostingRegressor、HistGradientBoostingClassifier等)在调用fit方法后会提供一个feature_importances_属性。来看一个实际的例子。假设我们有特征矩阵X_train和目标向量y_train。import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # 假设X和y是预先加载的pandas DataFrame和Series # 为了演示,我们创建合成数据: from sklearn.datasets import make_classification X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=2, n_classes=2, random_state=42) feature_names = [f'feature_{i}' for i in range(X.shape[1])] X = pd.DataFrame(X, columns=feature_names) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 初始化并训练一个RandomForestClassifier rf_model = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1) rf_model.fit(X_train, y_train) # 获取特征重要性 importances = rf_model.feature_importances_ # 创建一个DataFrame以便更好地可视化 importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': importances}) importance_df = importance_df.sort_values(by='Importance', ascending=False) print("RandomForestClassifier的特征重要性:") print(importance_df) # 你可以使用柱状图可视化这些重要性 # (Plotly的可视化JSON将在下方生成)这段代码训练了一个随机森林模型,然后提取并以降序打印出重要性分数。可视化这些分数通常能提供更清晰的认识。{"data":[{"type":"bar","y":["feature_2","feature_3","feature_0","feature_1","feature_4","feature_7","feature_8","feature_5","feature_6","feature_9"],"x":[0.1943,0.1912,0.1445,0.1225,0.0901,0.0695,0.0672,0.0531,0.0479,0.0197],"orientation":"h","marker":{"color":"#20c997"}}],"layout":{"title":{"text":"随机森林的特征重要性","x":0.5},"xaxis":{"title":"重要性分数"},"yaxis":{"title":"特征","autorange":"reversed"},"height":400,"margin":{"l":100,"r":20,"t":40,"b":40}}}随机森林模型计算的特征重要性,以水平柱状图形式展现。特征根据其对模型预测的贡献(平均不纯度下降)从最重要到最不重要进行排序。使用重要性分数选择特征获得重要性分数后,你可以用它们来选择特征子集。常用策略包括:保留前N个特征: 选择重要性分数最高的N个特征。设置阈值: 保留所有重要性分数高于某个预设或计算阈值的特征。该阈值可以是绝对值、最大重要性的一部分,或平均/中位数重要性。Scikit-learn提供了SelectFromModel元转换器,它简化了这个过程。它接受一个具有feature_importances_(或线性模型的coef_)属性的估计器,并根据指定的阈值选择特征。from sklearn.feature_selection import SelectFromModel import numpy as np # 将SelectFromModel与已训练的RandomForest模型一起使用 # 我们可以设置一个阈值,例如,选择重要性高于中位数重要性的特征 # 从已拟合的模型中计算中位数重要性 median_importance = np.median(rf_model.feature_importances_) selector = SelectFromModel(estimator=rf_model, threshold=median_importance, prefit=True) # 此外,如果希望SelectFromModel自行计算,可以使用 threshold='median'。 # selector = SelectFromModel(estimator=rf_model, threshold='median', prefit=True) # 'median' 需要字符串输入 # 'prefit=True' 是因为rf_model已经训练过了。 # 如果prefit=False,SelectFromModel将自行拟合估计器。 # 转换数据以仅保留选定的特征 X_train_selected = selector.transform(X_train) X_test_selected = selector.transform(X_test) # 获取选定特征的名称 selected_feature_indices = selector.get_support(indices=True) selected_feature_names = X_train.columns[selected_feature_indices] print(f"\n原始特征数量: {X_train.shape[1]}") print(f"选定的特征数量 (重要性 > 中位数): {X_train_selected.shape[1]}") print(f"选定的特征: {selected_feature_names.tolist()}")SelectFromModel可以使用"mean"、"median"等阈值,或浮点数值(例如0.01)。你还可以指定max_features直接选择前N个特征,不过这通常需要在SelectFromModel内部重新拟合估计器,除非使用了prefit=True并且阈值能自行选定所需数量。注意事项与局限尽管基于树的特征重要性被广泛应用且高效,但请记住以下几点:对高基数特征的偏倚: 基于不纯度的重要性度量(如基尼重要性)有时会夸大连续特征或具有许多独特值的分类特征的重要性。置换重要性通常较少受到这种偏倚的影响。相关联特征: 如果两个或多个特征高度相关并提供相似信息,模型可能会随意选择其中一个进行分割,或将重要性分配给它们。这可能导致原本有用的特征因有相关联的对应项而显得不那么重要。通常最好事先处理高度相关联的特征(例如,使用过滤方法部分中的方法)。模型特异性: 重要性来自正在训练的特定模型。不同模型类型,甚至相同模型类型的不同超参数,都可能产生不同的重要性排名。不稳定性: 重要性分数,特别是来自单个决策树或有时甚至是较小数据集上的集成模型的分数,可能有些不稳定。多次运行模型(使用不同的随机状态)或使用交叉验证可以得到更稳定的估计。随机森林等集成方法天生就比单个树提供更稳定的分数。基于树的特征重要性提供了一种计算高效的方式,可以直接从许多数据科学家日常使用的模型中评估特征关联性。通过理解这些分数是如何获得的以及它们的潜在局限,你可以有效地将它们作为特征选择工具包的一部分,通常与SelectFromModel结合使用,以减少维度并可能提升模型性能和可解释性。