Примечание
Перейти к концу для скачивания полного примера кода. или для запуска этого примера в вашем браузере через 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()

Мы видим, что образцы не являются четко разделимыми прямой линией.
Обучение модели 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()
Линейное ядро
Линейное ядро — это скалярное произведение входных образцов:
Затем он применяется к любой комбинации двух точек данных (образцов) в наборе данных. Скалярное произведение двух точек определяет cosine_similarity между обеими точками. Чем выше значение, тем больше сходство точек.
plot_training_data_with_decision_boundary("linear")

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

Полиномиальное ядро с gamma=2` хорошо адаптируется к данным обучения, заставляя отступы по обе стороны от гиперплоскости соответственно изгибаться.
Ядро RBF
Ядро радиальной базисной функции (RBF), также известное как гауссовское ядро, является ядром по умолчанию для машин опорных векторов в scikit-learn. Оно измеряет сходство между двумя точками данных в бесконечномерном пространстве, а затем приближается к классификации большинством голосов. Функция ядра определяется как:
где \({\gamma}\) (gamma) контролирует влияние каждого отдельного образца обучения на границу принятия решений.
Чем больше евклидово расстояние между двумя точками \(\|\mathbf{x}_1 - \mathbf{x}_2\|^2\), тем ближе функция ядра к нулю. Это означает, что две удаленные точки с большей вероятностью будут несходными.
plot_training_data_with_decision_boundary("rbf")

На графике можно увидеть, как границы принятия решений стремятся сжаться вокруг точек данных, которые находятся близко друг к другу.
Ядро сигмоиды
Функция ядра сигмоиды определяется как:
где коэффициент ядра \({\gamma}\) (gamma) контролирует влияние каждого отдельного образца обучения на границу принятия решений, а \({r}\) — член смещения (coef0) , который смещает данные вверх или вниз.
В сигмоидном ядре сходство между двумя точками данных вычисляется с помощью гиперболической функции тангенса (\(\tanh\)). Функция ядра масштабирует и, возможно, смещает скалярное произведение двух точек (\(\mathbf{x}_1\) и \(\mathbf{x}_2\)).
plot_training_data_with_decision_boundary("sigmoid")

Мы видим, что границы принятия решений, полученные с помощью сигмоидного ядра, выглядят изогнутыми и нерегулярными. Граница принятия решений пытается разделить классы, подгоняя кривую в форме сигмоиды, что приводит к сложной границе, которая может не обобщаться хорошо на незасмотренные данные. Из этого примера становится очевидным, что сигмоидное ядро имеет очень специфические области применения при работе с данными, которые демонстрируют сигмоидальную форму. В этом примере тщательная настройка может найти более обобщаемые границы принятия решений. Из-за своей специфичности сигмоидное ядро используется реже на практике по сравнению с другими ядрами.
Заключение
В этом примере мы визуализировали разделяющие границы, обученные на предоставленном наборе данных. Диаграммы служат наглядной демонстрацией того, как различные ядра используют данные обучения для определения границ классификации.
Гиперплоскости и маржины, хотя и вычисляются косвенно, можно представить как плоскости в преобразованном пространстве признаков. Однако на диаграммах они представлены относительно исходного пространства признаков, что приводит к криволинейным разделяющим границам для полиномиальных, 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()

Как видно из диаграмм выше, только ядро rbf может найти разумную разделяющую границу для вышеуказанного набора данных.
Общее время выполнения скрипта: (0 минут 1.364 секунды)
Связанные примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/svm/plot_svm_kernels.html