Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.
Проверка значимости оценки классификации с помощью перестановок
В этом примере показано использование permutation_test_score для оценки значимости кросс-валидационной оценки с помощью перестановок.
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
Набор данных
Мы будем использовать набор данных о растениях ириса, содержащий измерения для 3 видов ириса. Наша модель будет использовать эти измерения для предсказания вида ириса.
from sklearn.datasets import load_iris iris = load_iris() X = iris.data y = iris.target
Для сравнения мы также сгенерируем случайные данные признаков (то есть 20 признаков), не коррелирующие с метками классов в наборе данных ириса.
import numpy as np n_uncorrelated_features = 20 rng = np.random.RandomState(seed=0) # Use same number of samples as in iris and 20 features X_rand = rng.normal(size=(X.shape[0], n_uncorrelated_features))
Оценка с помощью теста перестановок
Затем мы вычислим permutation_test_score для исходного набора данных ириса (в котором есть сильная связь между признаками и метками) и для случайно сгенерированных признаков с метками ириса (где ожидается отсутствие зависимости между признаками и метками). Для оценки модели на каждом шаге мы используем классификатор SVC и оценку точности.
permutation_test_score строит нулевое распределение, вычисляя точность классификатора для 1000 различных перестановок набора данных, в которых признаки остаются прежними, а метки случайным образом переставляются. Это распределение соответствует нулевой гипотезе об отсутствии зависимости между признаками и метками. Затем вычисляется эмпирическое p-значение как доля перестановок, для которых оценка модели, обученной на переставленных данных, больше или равна оценке, полученной на исходных данных.
from sklearn.model_selection import StratifiedKFold, permutation_test_score
from sklearn.svm import SVC
clf = SVC(kernel="linear", random_state=7)
cv = StratifiedKFold(n_splits=2, shuffle=True, random_state=0)
score_iris, perm_scores_iris, pvalue_iris = permutation_test_score(
clf, X, y, scoring="accuracy", cv=cv, n_permutations=1000
)
score_rand, perm_scores_rand, pvalue_rand = permutation_test_score(
clf, X_rand, y, scoring="accuracy", cv=cv, n_permutations=1000
)
Исходные данные
Ниже мы строим гистограмму оценок для перестановок (нулевого распределения). Красная линия показывает оценку классификатора на исходных данных (без переставленных меток). Эта оценка значительно выше оценок, полученных на переставленных данных, поэтому p-значение очень низкое. Это означает, что вероятность получить столь высокую оценку случайно крайне мала. Это служит свидетельством того, что в наборе данных ириса существует реальная зависимость между признаками и метками, которую классификатор смог использовать для получения хороших результатов. Низкое p-значение позволяет нам отвергнуть нулевую гипотезу.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.hist(perm_scores_iris, bins=20, density=True)
ax.axvline(score_iris, ls="--", color="r")
score_label = (
f"Score on original\niris data: {score_iris:.2f}\n(p-value: {pvalue_iris:.3f})"
)
ax.text(0.7, 10, score_label, fontsize=12)
ax.set_xlabel("Accuracy score")
_ = ax.set_ylabel("Probability density")

Случайные данные
Ниже мы строим нулевое распределение для случайных данных. Оценки для перестановок похожи на оценки, полученные на исходном наборе данных ириса, поскольку перестановка всегда разрушает любую имеющуюся зависимость между признаками и метками. Однако оценка на случайных данных в этом случае очень низкая. В результате получается большое p-значение, подтверждающее отсутствие зависимости между признаками и метками в случайных данных.
fig, ax = plt.subplots()
ax.hist(perm_scores_rand, bins=20, density=True)
ax.set_xlim(0.13)
ax.axvline(score_rand, ls="--", color="r")
score_label = (
f"Score on original\nrandom data: {score_rand:.2f}\n(p-value: {pvalue_rand:.3f})"
)
ax.text(0.14, 7.5, score_label, fontsize=12)
ax.set_xlabel("Accuracy score")
ax.set_ylabel("Probability density")
plt.show()

Ещё одной возможной причиной высокого p-значения может быть то, что классификатор не смог использовать структуру данных. В этом случае низкое p-значение было бы только у классификаторов, способных использовать имеющуюся зависимость. В нашем примере выше, где данные случайны, у всех классификаторов было бы высокое p-значение, поскольку в данных нет структуры. В зависимости от того, будет ли p-значение также высоким у более подходящей модели, мы можем как отвергнуть, так и не отвергнуть нулевую гипотезу.
Наконец, отметим, что было показано: этот тест может давать низкие p-значения, даже если структура данных выражена слабо [1].
Литература
Общее время выполнения скрипта: (0 минут 16.749 секунды)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/model_selection/plot_permutation_tests_for_classification.html