乳腺癌数据集上的排列重要性

Beginner

This tutorial is from open-source community. Access the source code

简介

本实验展示了如何使用 sklearn.inspection 中的 permutation_importance 函数,对威斯康星乳腺癌数据集使用排列重要性。随机森林分类器用于对数据进行分类,并计算其在测试集上的准确率。我们还将展示如何使用层次聚类来处理特征中的多重共线性。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到 笔记本 标签页,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。

训练随机森林分类器

我们首先加载威斯康星乳腺癌数据集,并将其拆分为训练集和测试集。然后,我们在训练集上训练一个随机森林分类器,并在测试集上评估其准确率。

data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)
print("Accuracy on test data: {:.2f}".format(clf.score(X_test, y_test)))

绘制特征重要性

我们绘制基于树的特征重要性和排列重要性。排列重要性图显示,对某个特征进行排列最多会使准确率下降 0.012,这表明没有一个特征是重要的。这与上面计算出的高测试准确率相矛盾:肯定有一些特征是重要的。排列重要性是在训练集上计算的,以显示模型在训练期间对每个特征的依赖程度。

result = permutation_importance(clf, X_train, y_train, n_repeats=10, random_state=42)
perm_sorted_idx = result.importances_mean.argsort()

tree_importance_sorted_idx = np.argsort(clf.feature_importances_)
tree_indices = np.arange(0, len(clf.feature_importances_)) + 0.5

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 8))
ax1.barh(tree_indices, clf.feature_importances_[tree_importance_sorted_idx], height=0.7)
ax1.set_yticks(tree_indices)
ax1.set_yticklabels(data.feature_names[tree_importance_sorted_idx])
ax1.set_ylim((0, len(clf.feature_importances_)))
ax2.boxplot(
    result.importances[perm_sorted_idx].T,
    vert=False,
    labels=data.feature_names[perm_sorted_idx],
)
fig.tight_layout()
plt.show()

处理多重共线性特征

当特征存在共线性时,对一个特征进行排列对模型性能的影响很小,因为它可以从相关特征中获取相同的信息。处理多重共线性特征的一种方法是对斯皮尔曼等级相关性进行层次聚类,选择一个阈值,并从每个聚类中保留一个特征。首先,我们绘制相关特征的热图。

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 8))
corr = spearmanr(X).correlation

## Ensure the correlation matrix is symmetric
corr = (corr + corr.T) / 2
np.fill_diagonal(corr, 1)

## We convert the correlation matrix to a distance matrix before performing
## hierarchical clustering using Ward's linkage.
distance_matrix = 1 - np.abs(corr)
dist_linkage = hierarchy.ward(squareform(distance_matrix))
dendro = hierarchy.dendrogram(
    dist_linkage, labels=data.feature_names.tolist(), ax=ax1, leaf_rotation=90
)
dendro_idx = np.arange(0, len(dendro["ivl"]))

ax2.imshow(corr[dendro["leaves"], :][:, dendro["leaves"]])
ax2.set_xticks(dendro_idx)
ax2.set_yticks(dendro_idx)
ax2.set_xticklabels(dendro["ivl"], rotation="vertical")
ax2.set_yticklabels(dendro["ivl"])
fig.tight_layout()
plt.show()

选择一个阈值将特征分组为聚类

我们通过直观检查树形图来手动选择一个阈值,以便将特征分组为聚类,并从每个聚类中选择一个特征保留下来,从数据集中选择这些特征,然后训练一个新的随机森林。与在完整数据集上训练的随机森林相比,新随机森林的测试准确率变化不大。

cluster_ids = hierarchy.fcluster(dist_linkage, 1, criterion="distance")
cluster_id_to_feature_ids = defaultdict(list)
for idx, cluster_id in enumerate(cluster_ids):
    cluster_id_to_feature_ids[cluster_id].append(idx)
selected_features = [v[0] for v in cluster_id_to_feature_ids.values()]

X_train_sel = X_train[:, selected_features]
X_test_sel = X_test[:, selected_features]

clf_sel = RandomForestClassifier(n_estimators=100, random_state=42)
clf_sel.fit(X_train_sel, y_train)
print(
    "Accuracy on test data with features removed: {:.2f}".format(
        clf_sel.score(X_test_sel, y_test)
    )
)

总结

本实验展示了如何使用排列重要性,通过随机森林分类器在威斯康星乳腺癌数据集上计算特征重要性。我们还展示了如何使用层次聚类来处理多重共线性特征。