Spec-Zone.ru › scikit-learn

Примечание

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

Построение границ классификации для разных ядер SVM

В этом примере показано, как разные ядра в SVC (классификаторе опорных векторов) влияют на границы классификации в задаче бинарной классификации на плоскости.

Цель SVC — найти гиперплоскость, которая эффективно разделяет классы в обучающих данных, максимизируя зазор между крайними точками данных каждого класса. Для этого находится наилучший вектор весов \(w\), задающий гиперплоскость границы принятия решения и минимизирующий сумму потерь шарнира для ошибочно классифицированных образцов, вычисляемую с помощью функции hinge_loss. По умолчанию применяется регуляризация с параметром C=1, допускающим некоторую степень ошибок классификации.

Если данные не являются линейно разделимыми в исходном пространстве признаков, можно задать нелинейный параметр ядра. В зависимости от ядра процесс включает добавление новых признаков или преобразование существующих, чтобы обогатить данные и, возможно, придать им дополнительный смысл. Если задано ядро, отличное от "linear", SVC применяет ядерный трюк, вычисляющий сходство между парами точек данных с помощью функции ядра без явного преобразования всего набора данных. Ядерный трюк позволяет избежать необходимого в противном случае матричного преобразования всего набора данных, учитывая только отношения между всеми парами точек данных. Функция ядра сопоставляет два вектора (каждую пару наблюдений) с мерой их сходства, используя их скалярное произведение.

Затем гиперплоскость можно вычислить с помощью функции ядра так, как если бы набор данных был представлен в пространстве большей размерности. Использование функции ядра вместо явного матричного преобразования повышает производительность, поскольку временная сложность функции ядра составляет \(O({n}^2)\), тогда как сложность матричного преобразования зависит от конкретного применяемого преобразования.

В этом примере мы сравним наиболее распространённые типы ядер машин опорных векторов: линейное ядро ("linear"), полиномиальное ядро ("poly"), ядро радиальной базисной функции ("rbf") и сигмоидальное ядро ("sigmoid").

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Создание набора данных

Мы создадим двумерный набор данных для классификации из 16 образцов и двух классов. Отобразим образцы, раскрасив их в соответствии с целевыми значениями.

import matplotlib.pyplot as plt
import numpy as np

X = np.array(
    [
        [0.4, -0.7],
        [-1.5, -1.0],
        [-1.4, -0.9],
        [-1.3, -1.2],
        [-1.1, -0.2],
        [-1.2, -0.4],
        [-0.5, 1.2],
        [-1.5, 2.1],
        [1.0, 1.0],
        [1.3, 0.8],
        [1.2, 0.5],
        [0.2, -2.0],
        [0.5, -2.4],
        [0.2, -2.3],
        [0.0, -2.7],
        [1.3, 2.1],
    ]
)

y = np.array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1])

# Plotting settings
fig, ax = plt.subplots(figsize=(4, 3))
x_min, x_max, y_min, y_max = -3, 3, -3, 3
ax.set(xlim=(x_min, x_max), ylim=(y_min, y_max))

# Plot samples by color and add legend
scatter = ax.scatter(X[:, 0], X[:, 1], s=150, c=y, label=y, edgecolors="k")
ax.legend(*scatter.legend_elements(), loc="upper right", title="Classes")
ax.set_title("Samples in two-dimensional feature space")
plt.show()
Samples in two-dimensional feature space

Видно, что образцы нельзя чётко разделить прямой линией.

Обучение модели SVC и построение границ принятия решения

Определим функцию, которая обучает классификатор SVC, принимает параметр kernel и строит границы принятия решения, выученные моделью, с помощью DecisionBoundaryDisplay.

Обратите внимание, что для простоты в этом примере параметр C задан значением по умолчанию (C=1), а параметр gamma установлен в gamma=2 для всех ядер, хотя для линейного ядра он автоматически игнорируется. В реальной задаче классификации, где важна производительность, настоятельно рекомендуется подбирать параметры (например, с помощью GridSearchCV), чтобы учитывать различные структуры данных.

Задание response_method="predict" в DecisionBoundaryDisplay окрашивает области в зависимости от предсказанного для них класса. Параметр response_method="decision_function" позволяет также построить границу принятия решения и отступы по обе стороны от неё. Наконец, опорные векторы, использованные при обучении (которые всегда находятся на границах отступов), определяются с помощью атрибута support_vectors_ обученных SVC и также отображаются на графике.

from sklearn import svm
from sklearn.inspection import DecisionBoundaryDisplay


def plot_training_data_with_decision_boundary(
    kernel, ax=None, long_title=True, support_vectors=True
):
    # Train the SVC
    clf = svm.SVC(kernel=kernel, gamma=2).fit(X, y)

    # Settings for plotting
    if ax is None:
        _, ax = plt.subplots(figsize=(4, 3))
    x_min, x_max, y_min, y_max = -3, 3, -3, 3
    ax.set(xlim=(x_min, x_max), ylim=(y_min, y_max))

    # Plot decision boundary and margins
    common_params = {"estimator": clf, "X": X, "ax": ax}
    DecisionBoundaryDisplay.from_estimator(
        **common_params,
        response_method="predict",
        plot_method="pcolormesh",
        alpha=0.3,
    )
    DecisionBoundaryDisplay.from_estimator(
        **common_params,
        response_method="decision_function",
        plot_method="contour",
        levels=[-1, 0, 1],
        colors=["k", "k", "k"],
        linestyles=["--", "-", "--"],
    )

    if support_vectors:
        # Plot bigger circles around samples that serve as support vectors
        ax.scatter(
            clf.support_vectors_[:, 0],
            clf.support_vectors_[:, 1],
            s=150,
            facecolors="none",
            edgecolors="k",
        )

    # Plot samples by color and add legend
    ax.scatter(X[:, 0], X[:, 1], c=y, s=30, edgecolors="k")
    ax.legend(*scatter.legend_elements(), loc="upper right", title="Classes")
    if long_title:
        ax.set_title(f" Decision boundaries of {kernel} kernel in SVC")
    else:
        ax.set_title(kernel)

    if ax is None:
        plt.show()

Линейное ядро

Линейное ядро — это скалярное произведение входных образцов:

\[K(\mathbf{x}_1, \mathbf{x}_2) = \mathbf{x}_1^\top \mathbf{x}_2\]

Затем оно применяется к любым двум точкам данных (образцам) из набора данных. Скалярное произведение двух точек определяет меру cosine_similarity между ними. Чем выше значение, тем больше сходство между точками.

plot_training_data_with_decision_boundary("linear")
Decision boundaries of linear kernel in SVC

Обучение SVC с линейным ядром выполняется в непреобразованном пространстве признаков, где гиперплоскость и отступы представляют собой прямые линии. Из-за ограниченной выразительности линейного ядра обученные классы не идеально соответствуют обучающим данным.

Полиномиальное ядро

Полиномиальное ядро изменяет понятие сходства. Функция ядра определяется следующим образом:

\[K(\mathbf{x}_1, \mathbf{x}_2) = (\gamma \cdot \ \mathbf{x}_1^\top\mathbf{x}_2 + r)^d\]

где \({d}\) — степень полинома (degree), \({\gamma}\) (gamma) определяет влияние каждого отдельного обучающего образца на границу принятия решения, а \({r}\) — свободный член (coef0), смещающий данные вверх или вниз. Здесь мы используем значение степени полинома в функции ядра по умолчанию (degree=3). Если coef0=0 (значение по умолчанию), данные только преобразуются, но дополнительное измерение не добавляется. Использование полиномиального ядра эквивалентно созданию PolynomialFeatures с последующим обучением SVC с линейным ядром на преобразованных данных, хотя такой альтернативный подход был бы вычислительно затратным для большинства наборов данных.

plot_training_data_with_decision_boundary("poly")
Decision boundaries of poly kernel in SVC

Полиномиальное ядро с gamma=2 хорошо подстраивается под обучающие данные, из-за чего отступы по обе стороны гиперплоскости соответственно изгибаются.

Ядро RBF

Ядро радиальной базисной функции (RBF), также известное как гауссово ядро, является ядром по умолчанию для машин опорных векторов в scikit-learn. Оно измеряет сходство двух точек данных в пространстве бесконечной размерности, а затем выполняет классификацию методом голосования большинством. Функция ядра определяется следующим образом:

\[K(\mathbf{x}_1, \mathbf{x}_2) = \exp\left(-\gamma \cdot {\|\mathbf{x}_1 - \mathbf{x}_2\|^2}\right)\]

где \({\gamma}\) (gamma) определяет влияние каждого отдельного обучающего образца на границу принятия решения.

Чем больше евклидово расстояние между двумя точками \(\|\mathbf{x}_1 - \mathbf{x}_2\|^2\), тем ближе значение функции ядра к нулю. Это означает, что точки, расположенные далеко друг от друга, с большей вероятностью будут непохожи.

plot_training_data_with_decision_boundary("rbf")
Decision boundaries of rbf kernel in SVC

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

Сигмоидальное ядро

Функция сигмоидального ядра определяется следующим образом:

\[K(\mathbf{x}_1, \mathbf{x}_2) = \tanh(\gamma \cdot \mathbf{x}_1^\top\mathbf{x}_2 + r)\]

где коэффициент ядра \({\gamma}\) (gamma) определяет влияние каждого отдельного обучающего образца на границу принятия решения, а \({r}\) — свободный член (coef0), смещающий данные вверх или вниз.

В сигмоидальном ядре сходство двух точек данных вычисляется с помощью гиперболического тангенса (\(\tanh\)). Функция ядра масштабирует и, возможно, смещает скалярное произведение двух точек (\(\mathbf{x}_1\) и \(\mathbf{x}_2\)).

plot_training_data_with_decision_boundary("sigmoid")
Decision boundaries of sigmoid kernel in SVC

Видно, что границы принятия решения, полученные с помощью сигмоидального ядра, выглядят изогнутыми и неровными. Граница пытается разделить классы, подстраиваясь под кривую сигмоидальной формы, что приводит к сложной границе, которая может плохо обобщаться на новые данные. Этот пример показывает, что сигмоидальное ядро имеет очень специфические области применения — например, для данных с сигмоидальной формой. В данном примере тщательная настройка параметров может помочь найти границы принятия решения, лучше обобщающиеся на новые данные. Из-за узкой области применения сигмоидальное ядро используется на практике реже, чем другие ядра.

Заключение

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

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

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

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

Набор данных XOR

Классический пример набора данных, который нельзя разделить линейно, — это структура XOR. Здесь мы покажем, как разные ядра работают на таком наборе данных.

xx, yy = np.meshgrid(np.linspace(-3, 3, 500), np.linspace(-3, 3, 500))
np.random.seed(0)
X = np.random.randn(300, 2)
y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)

_, ax = plt.subplots(2, 2, figsize=(8, 8))
args = dict(long_title=False, support_vectors=False)
plot_training_data_with_decision_boundary("linear", ax[0, 0], **args)
plot_training_data_with_decision_boundary("poly", ax[0, 1], **args)
plot_training_data_with_decision_boundary("rbf", ax[1, 0], **args)
plot_training_data_with_decision_boundary("sigmoid", ax[1, 1], **args)
plt.show()
linear, poly, rbf, sigmoid

Как видно на графиках выше, только ядро rbf позволяет найти подходящую границу принятия решения для этого набора данных.

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

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_svm_kernels.ipynb

Download Python source code: plot_svm_kernels.py

Download zipped: plot_svm_kernels.zip

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

Параметры RBF SVM

Построение графиков различных классификаторов SVM на наборе данных ирисов

SVM: разделяющая гиперплоскость с максимальным отступом

SVM: разделяющая гиперплоскость для несбалансированных классов

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

Spec-Zone.ru

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