在机器学习领域,特征重要性的评估是理解模型决策过程的关键步骤。随机森林是一种流行的集成学习方法,它通过构建多个决策树并结合它们的预测结果来提高模型的准确性和鲁棒性。本文将介绍如何利用随机森林算法来评估特征在分类任务中的重要性,并展示两种不同的特征重要性评估方法:基于不纯度减少(MDI)和基于特征排列。
首先,生成了一个包含1000个样本和10个特征的合成数据集,其中只有3个特征是信息性的。为了确保信息性特征对应于数据集X的前三个列,没有对数据进行洗牌。接着,将数据集划分为训练集和测试集。
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=1000, n_features=10, n_informative=3, n_redundant=0, n_repeated=0, n_classes=2, random_state=0, shuffle=False)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
然后,使用随机森林分类器来拟合训练数据,并计算特征重要性。
from sklearn.ensemble import RandomForestClassifier
feature_names = [f"feature {i}" for i in range(X.shape[1])]
forest = RandomForestClassifier(random_state=0)
forest.fit(X_train, y_train)
特征重要性是通过随机森林中每棵树的不纯度减少的平均值和标准差来计算的。需要注意的是,基于不纯度的特征重要性可能对具有高基数特征(即具有许多唯一值的特征)产生误导。
首先计算了特征重要性,并绘制了条形图来展示这些特征的重要性及其在不同树之间的变异性。
import time
import numpy as np
start_time = time.time()
importances = forest.feature_importances_
std = np.std([tree.feature_importances_ for tree in forest.estimators_], axis=0)
elapsed_time = time.time() - start_time
print(f"计算重要性所需的时间:{elapsed_time:.3f}秒")
接下来,绘制了基于不纯度减少的特征重要性条形图。
import pandas as pd
import matplotlib.pyplot as plt
forest_importances = pd.Series(importances, index=feature_names)
fig, ax = plt.subplots()
forest_importances.plot.bar(yerr=std, ax=ax)
ax.set_title("使用MDI的特征重要性")
ax.set_ylabel("不纯度减少的平均值")
fig.tight_layout()
从图中可以观察到,正如预期的那样,前三个特征被认为是重要的。
排列特征重要性克服了基于不纯度的特征重要性的局限性:它们不会对高基数特征产生偏见,并且可以在留出的测试集上计算。
from sklearn.inspection import permutation_importance
start_time = time.time()
result = permutation_importance(forest, X_test, y_test, n_repeats=10, random_state=42, n_jobs=2)
elapsed_time = time.time() - start_time
forest_importances = pd.Series(result.importances_mean, index=feature_names)
print(f"计算重要性所需的时间:{elapsed_time:.3f}秒")
绘制了基于排列的特征重要性条形图。
fig, ax = plt.subplots()
forest_importances.plot.bar(yerr=result.importances_std, ax=ax)
ax.set_title("使用排列在完整模型上的特征重要性")
ax.set_ylabel("平均准确度下降")
fig.tight_layout()
plt.show()
通过比较两种方法,发现使用排列方法计算的特征重要性更加准确,因为它不会受到高基数特征的影响。