Spec-Zone.ru › scikit-learn

Примечание

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

Ядерный PCA

В этом примере показана разница между анализом главных компонент (PCA) и его версией с ядром (KernelPCA).

С одной стороны, мы показываем, что KernelPCA позволяет найти проекцию данных, которая линейно разделяет их, в отличие от PCA.

Наконец, мы показываем, что обратное преобразование этой проекции с помощью KernelPCA является приближением, тогда как с помощью PCA оно точное.

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

Проекция данных: PCA и KernelPCA

В этом разделе мы покажем преимущества использования ядра при проецировании данных с помощью анализа главных компонент (PCA). Мы создадим набор данных из двух вложенных окружностей.

from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split

X, y = make_circles(n_samples=1_000, factor=0.3, noise=0.05, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)

Для начала бегло взглянем на созданный набор данных.

import matplotlib.pyplot as plt

_, (train_ax, test_ax) = plt.subplots(ncols=2, sharex=True, sharey=True, figsize=(8, 4))

train_ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train)
train_ax.set_ylabel("Feature #1")
train_ax.set_xlabel("Feature #0")
train_ax.set_title("Training data")

test_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
test_ax.set_xlabel("Feature #0")
_ = test_ax.set_title("Testing data")
Training data, Testing data

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

Теперь мы применим PCA с ядром и без него, чтобы увидеть, как влияет использование ядра. Здесь используется ядро радиальной базисной функции (RBF).

from sklearn.decomposition import PCA, KernelPCA

pca = PCA(n_components=2)
kernel_pca = KernelPCA(
    n_components=None, kernel="rbf", gamma=10, fit_inverse_transform=True, alpha=0.1
)

X_test_pca = pca.fit(X_train).transform(X_test)
X_test_kernel_pca = kernel_pca.fit(X_train).transform(X_test)
fig, (orig_data_ax, pca_proj_ax, kernel_pca_proj_ax) = plt.subplots(
    ncols=3, figsize=(14, 4)
)

orig_data_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
orig_data_ax.set_ylabel("Feature #1")
orig_data_ax.set_xlabel("Feature #0")
orig_data_ax.set_title("Testing data")

pca_proj_ax.scatter(X_test_pca[:, 0], X_test_pca[:, 1], c=y_test)
pca_proj_ax.set_ylabel("Principal component #1")
pca_proj_ax.set_xlabel("Principal component #0")
pca_proj_ax.set_title("Projection of testing data\n using PCA")

kernel_pca_proj_ax.scatter(X_test_kernel_pca[:, 0], X_test_kernel_pca[:, 1], c=y_test)
kernel_pca_proj_ax.set_ylabel("Principal component #1")
kernel_pca_proj_ax.set_xlabel("Principal component #0")
_ = kernel_pca_proj_ax.set_title("Projection of testing data\n using KernelPCA")
Testing data, Projection of testing data  using PCA, Projection of testing data  using KernelPCA

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

Рассматривая проекцию, полученную с помощью PCA (то есть средний график), мы видим, что масштабирование не изменилось: поскольку данные представляют собой две концентрические окружности с центром в нуле, исходные данные уже изотропны. Однако видно, что данные были повёрнуты. Следовательно, такая проекция не поможет, если задать линейный классификатор для разделения образцов двух классов.

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

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

Проекция в исходное пространство признаков

При использовании KernelPCA важно учитывать одну особенность, связанную с реконструкцией (то есть обратным преобразованием в исходное пространство признаков). При использовании PCA реконструкция будет точной, если n_components равно числу исходных признаков. В данном примере это условие выполняется.

Проверим, получим ли мы исходный набор данных при обратном преобразовании с помощью KernelPCA.

X_reconstructed_pca = pca.inverse_transform(pca.transform(X_test))
X_reconstructed_kernel_pca = kernel_pca.inverse_transform(kernel_pca.transform(X_test))
fig, (orig_data_ax, pca_back_proj_ax, kernel_pca_back_proj_ax) = plt.subplots(
    ncols=3, sharex=True, sharey=True, figsize=(13, 4)
)

orig_data_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
orig_data_ax.set_ylabel("Feature #1")
orig_data_ax.set_xlabel("Feature #0")
orig_data_ax.set_title("Original test data")

pca_back_proj_ax.scatter(X_reconstructed_pca[:, 0], X_reconstructed_pca[:, 1], c=y_test)
pca_back_proj_ax.set_xlabel("Feature #0")
pca_back_proj_ax.set_title("Reconstruction via PCA")

kernel_pca_back_proj_ax.scatter(
    X_reconstructed_kernel_pca[:, 0], X_reconstructed_kernel_pca[:, 1], c=y_test
)
kernel_pca_back_proj_ax.set_xlabel("Feature #0")
_ = kernel_pca_back_proj_ax.set_title("Reconstruction via KernelPCA")
Original test data, Reconstruction via PCA, Reconstruction via KernelPCA

Мы видим, что с помощью PCA реконструкция идеальна, тогда как результат для KernelPCA отличается.

Дело в том, что inverse_transform не может использовать аналитическое обратное преобразование и, следовательно, обеспечить точную реконструкцию. Вместо этого внутри обучается KernelRidge, чтобы установить соответствие между базисом PCA с ядром и исходным пространством признаков. Таким образом, этот метод является приближённым и при обратном преобразовании в исходное пространство признаков вносит небольшие различия.

Чтобы улучшить реконструкцию с помощью inverse_transform, можно настроить alpha в KernelPCA — параметр регуляризации, который определяет, насколько сильно обучение соответствия опирается на обучающие данные.

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

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_kernel_pca.ipynb

Download Python source code: plot_kernel_pca.py

Download zipped: plot_kernel_pca.zip

Связанные примеры

Удаление шума с изображений с помощью ядерного PCA

Важность масштабирования признаков

Анализ главных компонент (PCA) на наборе данных Iris

Инкрементальный PCA

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

Spec-Zone.ru

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