Spec-Zone.ru › scikit-learn

Примечание

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

Ядерный PCA

В этом примере показано различие между методом анализа главных компонент (Principal Components Analysis, 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,563 секунды)

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

Разложение набора данных лиц

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

Spec-Zone.ru

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