Важность перестановок на наборе данных о раке груди

Beginner

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

Введение

В этом практическом занятии показано, как использовать важность перестановок на наборе данных о раке груди Висconsin с использованием функции permutation_importance из sklearn.inspection. Для классификации данных и вычисления точности на тестовом наборе используется классификатор Случайный лес. Также покажем, как обрабатывать мультиколлинеарность признаков с использованием иерархической кластеризации.

Советы по использованию ВМ

После запуска ВМ перейдите в левый верхний угол и переключитесь на вкладку Ноутбук, чтобы приступить к практике в Jupyter Notebook.

Иногда может потребоваться подождать несколько секунд, пока Jupyter Notebook полностью загрузится. Проверка операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Обучить классификатор Случайный лес

Сначала мы загружаем набор данных о раке груди Висconsin и разбиваем его на обучающий и тестовый наборы. Затем мы обучаем классификатор Случайный лес на обучающем наборе и оцениваем его точность на тестовом наборе.

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)
    )
)

Резюме

В этом практическом занятии показано, как использовать важность перестановок для вычисления важности признаков на наборе данных о раке груди Висconsin с использованием классификатора Случайный лес. Мы показали, как обрабатывать мультиколлинеарные признаки с использованием иерархической кластеризации.