Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.

Построение вероятностей классификации

В этом примере показано использование sklearn.inspection.DecisionBoundaryDisplay для построения предсказанных вероятностей классов различных классификаторов в двумерном пространстве признаков, в основном в учебных целях.

В первых трёх столбцах показана предсказанная вероятность для различных значений двух признаков. Круглые маркеры обозначают тестовые данные, которым предсказан соответствующий класс.

В последнем столбце на каждом графике представлены все три класса; для каждой точки отображается класс с наибольшей предсказанной вероятностью. Круглые маркеры обозначают тестовые данные и окрашены в соответствии с их истинной меткой.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import cm

from sklearn import datasets
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.kernel_approximation import Nystroem
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, log_loss, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import (
    KBinsDiscretizer,
    PolynomialFeatures,
    SplineTransformer,
)

Данные: двумерная проекция набора данных ирисов

iris = datasets.load_iris()
X = iris.data[:, 0:2]  # we only take the first two features for visualization
y = iris.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.5, random_state=42
)

Вероятностные классификаторы

Мы построим границы решений нескольких классификаторов, у которых есть метод predict_proba. Это позволит визуализировать неопределённость классификатора в тех областях, где он не уверен в своём предсказании.

classifiers = {
    "Logistic regression\n(C=0.1)": LogisticRegression(C=0.1),
    "Logistic regression\n(C=100)": LogisticRegression(C=100),
    "Gaussian Process": GaussianProcessClassifier(kernel=1.0 * RBF([1.0, 1.0])),
    "Logistic regression\n(RBF features)": make_pipeline(
        Nystroem(kernel="rbf", gamma=5e-1, n_components=50, random_state=1),
        LogisticRegression(C=10),
    ),
    "Gradient Boosting": HistGradientBoostingClassifier(random_state=42),
    "Logistic regression\n(binned features)": make_pipeline(
        KBinsDiscretizer(n_bins=5, quantile_method="averaged_inverted_cdf"),
        PolynomialFeatures(interaction_only=True),
        LogisticRegression(C=10),
    ),
    "Logistic regression\n(spline features)": make_pipeline(
        SplineTransformer(n_knots=5),
        PolynomialFeatures(interaction_only=True),
        LogisticRegression(C=10),
    ),
}

Построение границ решений

Для каждого классификатора в первых трёх столбцах мы строим вероятности для каждого класса, а в последнем столбце — вероятности наиболее вероятного класса.

n_classifiers = len(classifiers)
scatter_kwargs = {
    "s": 25,
    "marker": "o",
    "linewidths": 0.8,
    "edgecolor": "k",
    "alpha": 0.7,
}
y_unique = np.unique(y)

# Ensure legend not cut off
mpl.rcParams["savefig.bbox"] = "tight"
fig, axes = plt.subplots(
    nrows=n_classifiers,
    ncols=len(iris.target_names) + 1,
    figsize=(4 * 2.2, n_classifiers * 2.2),
)
evaluation_results = []
levels = 100
for classifier_idx, (name, classifier) in enumerate(classifiers.items()):
    y_pred = classifier.fit(X_train, y_train).predict(X_test)
    y_pred_proba = classifier.predict_proba(X_test)
    accuracy_test = accuracy_score(y_test, y_pred)
    roc_auc_test = roc_auc_score(y_test, y_pred_proba, multi_class="ovr")
    log_loss_test = log_loss(y_test, y_pred_proba)
    evaluation_results.append(
        {
            "name": name.replace("\n", " "),
            "accuracy": accuracy_test,
            "roc_auc": roc_auc_test,
            "log_loss": log_loss_test,
        }
    )
    for label in y_unique:
        # plot the probability estimate provided by the classifier
        disp = DecisionBoundaryDisplay.from_estimator(
            classifier,
            X_train,
            response_method="predict_proba",
            class_of_interest=label,
            ax=axes[classifier_idx, label],
            vmin=0,
            vmax=1,
            cmap="Blues",
            levels=levels,
        )
        axes[classifier_idx, label].set_title(f"Class {iris.target_names[label]}")
        # plot data predicted to belong to given class
        mask_y_pred = y_pred == label
        axes[classifier_idx, label].scatter(
            X_test[mask_y_pred, 0], X_test[mask_y_pred, 1], c="w", **scatter_kwargs
        )

        axes[classifier_idx, label].set(xticks=(), yticks=())
    # add column that shows all classes by plotting class with max 'predict_proba'
    max_class_disp = DecisionBoundaryDisplay.from_estimator(
        classifier,
        X_train,
        response_method="predict_proba",
        class_of_interest=None,
        ax=axes[classifier_idx, len(y_unique)],
        vmin=0,
        vmax=1,
        levels=levels,
    )
    for label in y_unique:
        mask_label = y_test == label
        max_col = len(y_unique)
        axes[classifier_idx, max_col].scatter(
            X_test[mask_label, 0],
            X_test[mask_label, 1],
            c=max_class_disp.multiclass_colors_[[label], :],
            **scatter_kwargs,
        )

    axes[classifier_idx, 3].set(xticks=(), yticks=())
    axes[classifier_idx, 3].set_title("Max class")
    axes[classifier_idx, 0].set_ylabel(name)

# colorbar for single class plots
ax_single = fig.add_axes([0.15, 0.01, 0.5, 0.02])
plt.title("Probability")
_ = plt.colorbar(
    cm.ScalarMappable(norm=None, cmap=disp.surface_.cmap),
    cax=ax_single,
    orientation="horizontal",
)

# colorbars for max probability class column
max_class_cmaps = [s.cmap for s in max_class_disp.surface_]

for label in y_unique:
    ax_max = fig.add_axes([0.73, (0.06 - (label * 0.04)), 0.16, 0.015])
    plt.title(f"Probability class {label}", fontsize=10)
    _ = plt.colorbar(
        cm.ScalarMappable(norm=None, cmap=max_class_cmaps[label]),
        cax=ax_max,
        orientation="horizontal",
    )
    if label in (0, 1):
        ax_max.set(xticks=(), yticks=())
Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Class setosa, Class versicolor, Class virginica, Max class, Probability, Probability class 0, Probability class 1, Probability class 2

Количественная оценка

pd.DataFrame(evaluation_results).round(2)
название точность ROC AUC логарифмическая потеря
0 Логистическая регрессия (C=0.1) 0.83 0.92 0.71
1 Логистическая регрессия (C=100) 0.81 0.93 0.36
2 Гауссовский процесс 0.80 0.93 0.54
3 Логистическая регрессия (признаки RBF) 0.77 0.93 0.40
4 Градиентный бустинг 0.83 0.92 0.40
5 Логистическая регрессия (разбитые на интервалы признаки) 0.81 0.92 0.48
6 Логистическая регрессия (сплайновые признаки) 0.79 0.92 0.42


Анализ

Обе модели логистической регрессии, обученные на исходных признаках, имеют линейные границы решений, как и ожидалось. Для этой конкретной задачи это, по-видимому, не является недостатком: при количественной оценке на тестовом наборе обе модели показывают результаты, сопоставимые с нелинейными моделями. Можно заметить, что степень регуляризации влияет на уверенность модели: у модели с сильной регуляризацией и меньшим значением C цвета светлее. Регуляризация также влияет на ориентацию границы решений, что приводит к небольшим различиям в ROC AUC.

С другой стороны, log-loss оценивает и резкость, и калибровку, поэтому существенно отдаёт предпочтение модели логистической регрессии со слабой регуляризацией — вероятно, потому что модель с сильной регуляризацией недостаточно уверена в предсказаниях. Это можно проверить, построив кривую калибровки с помощью sklearn.calibration.CalibrationDisplay.

Модель логистической регрессии с признаками RBF имеет «пятнистую» границу решений, нелинейную в исходном пространстве признаков и довольно похожую на границу решений классификатора на основе гауссовского процесса, настроенного на использование ядра RBF.

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

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

В заключение интересно отметить, что инженерия признаков для моделей логистической регрессии может использоваться для имитации некоторых индуктивных смещений различных нелинейных моделей. Однако для этого конкретного набора данных достаточно использовать исходные признаки, чтобы обучить конкурентоспособную модель. Для других наборов данных это может быть не так.

Общее время выполнения скрипта: (0 минут 2.563 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_classification_probability.ipynb

Download Python source code: plot_classification_probability.py

Download zipped: plot_classification_probability.zip

Похожие примеры

Визуализация вероятностных предсказаний VotingClassifier

Признаки ограниченной машины Больцмана для классификации цифр

Границы решений мультиномиальной логистической регрессии и логистической регрессии «один против остальных»

Сравнение калибровки классификаторов

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/classification/plot_classification_probability.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API