Примечание
Перейти к концу, чтобы скачать весь пример кода. или запустить этот пример в браузере через JupyterLite или Binder
Регрессия на основе главных компонент против регрессии на основе наименьших квадратов
В этом примере сравниваются регрессия на основе главных компонент (PCR) и регрессия на основе наименьших квадратов (PLS) на наборе данных для игрушечных данных. Цель — проиллюстрировать, как PLS может превзойти PCR, когда целевая переменная сильно коррелирует с некоторыми направлениями в данных, которые имеют низкую дисперсию.
PCR — это регрессор, состоящий из двух шагов: сначала к обучающим данным применяется PCA, возможно, для уменьшения размерности; затем на преобразованных выборках обучается регрессор (например, линейный регрессор). В PCA преобразование является чисто неконтролируемым, то есть никакая информация о целевых переменных не используется. В результате PCR может плохо работать на некоторых наборах данных, где целевая переменная сильно коррелирует с *направлениями*, имеющими низкую дисперсию. Действительно, уменьшение размерности с помощью PCA проектирует данные в пространство меньшей размерности, где дисперсия спроецированных данных жадно максимизируется по каждой оси. Несмотря на то, что у них наибольшая предсказательная сила по отношению к целевой переменной, направления с меньшей дисперсией будут отброшены, и конечный регрессор не сможет воспользоваться ими.
PLS — это как преобразователь, так и регрессор, и он довольно похож на PCR: он также применяет уменьшение размерности к выборкам перед применением линейного регрессора к преобразованным данным. Основное различие с PCR заключается в том, что преобразование PLS контролируется. Поэтому, как мы увидим в этом примере, он не страдает от проблемы, которую мы только что упомянули.
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
Данные
Мы начинаем с создания простого набора данных с двумя признаками. Прежде чем углубиться в PCR и PLS, мы подгоняем оценщик PCA, чтобы отобразить две главные компоненты этого набора данных, то есть два направления, которые объясняют наибольшую дисперсию в данных.
import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA
rng = np.random.RandomState(0)
n_samples = 500
cov = [[3, 3], [3, 4]]
X = rng.multivariate_normal(mean=[0, 0], cov=cov, size=n_samples)
pca = PCA(n_components=2).fit(X)
plt.scatter(X[:, 0], X[:, 1], alpha=0.3, label="samples")
for i, (comp, var) in enumerate(zip(pca.components_, pca.explained_variance_)):
comp = comp * var # scale component by its variance explanation power
plt.plot(
[0, comp[0]],
[0, comp[1]],
label=f"Component {i}",
linewidth=5,
color=f"C{i + 2}",
)
plt.gca().set(
aspect="equal",
title="2-dimensional dataset with principal components",
xlabel="first feature",
ylabel="second feature",
)
plt.legend()
plt.show()

В целях этого примера мы теперь определяем целевую переменную y таким образом, чтобы она сильно коррелировала с направлением, имеющим небольшую дисперсию. Для этого мы спроецируем X на вторую компоненту и добавим к ней немного шума.
y = X.dot(pca.components_[1]) + rng.normal(size=n_samples) / 2 fig, axes = plt.subplots(1, 2, figsize=(10, 3)) axes[0].scatter(X.dot(pca.components_[0]), y, alpha=0.3) axes[0].set(xlabel="Projected data onto first PCA component", ylabel="y") axes[1].scatter(X.dot(pca.components_[1]), y, alpha=0.3) axes[1].set(xlabel="Projected data onto second PCA component", ylabel="y") plt.tight_layout() plt.show()

Проекция на одну компоненту и предсказательная способность
Теперь мы создаем два регрессора: PCR и PLS, и для целей иллюстрации мы устанавливаем количество компонент в 1. Перед подачей данных на шаг PCA в PCR мы сначала стандартизируем их, как рекомендует лучшая практика. Оценщик PLS имеет встроенные возможности масштабирования.
Для обеих моделей мы строим график спроецированных данных на первую компоненту против целевой переменной. В обоих случаях эти спроецированные данные будут использованы регрессорами для обучения.
from sklearn.cross_decomposition import PLSRegression
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=rng)
pcr = make_pipeline(StandardScaler(), PCA(n_components=1), LinearRegression())
pcr.fit(X_train, y_train)
pca = pcr.named_steps["pca"] # retrieve the PCA step of the pipeline
pls = PLSRegression(n_components=1)
pls.fit(X_train, y_train)
fig, axes = plt.subplots(1, 2, figsize=(10, 3))
axes[0].scatter(pca.transform(X_test), y_test, alpha=0.3, label="ground truth")
axes[0].scatter(
pca.transform(X_test), pcr.predict(X_test), alpha=0.3, label="predictions"
)
axes[0].set(
xlabel="Projected data onto first PCA component", ylabel="y", title="PCR / PCA"
)
axes[0].legend()
axes[1].scatter(pls.transform(X_test), y_test, alpha=0.3, label="ground truth")
axes[1].scatter(
pls.transform(X_test), pls.predict(X_test), alpha=0.3, label="predictions"
)
axes[1].set(xlabel="Projected data onto first PLS component", ylabel="y", title="PLS")
axes[1].legend()
plt.tight_layout()
plt.show()

Как и ожидалось, неконтролируемое преобразование PCA в PCR отбросило вторую компоненту, то есть направление с наименьшей дисперсией, несмотря на то, что это направление является наиболее предсказательным. Это связано с тем, что PCA является полностью неконтролируемым преобразованием и приводит к тому, что спроецированные данные имеют низкую предсказательную способность по отношению к целевой переменной.
С другой стороны, регрессор PLS удается уловить эффект направления с наименьшей дисперсией благодаря использованию информации о целевой переменной во время преобразования: он может распознать, что это направление фактически является наиболее предсказательным. Обратите внимание, что первая компонента PLS отрицательно коррелирует с целевой переменной, что обусловлено произвольностью знаков собственных векторов.
Мы также выводим значения R-квадрат для обеих оценок, что еще раз подтверждает, что PLS в этом случае является лучшей альтернативой PCR. Отрицательное значение R-квадрат указывает на то, что PCR работает хуже, чем регрессор, который просто предсказывает среднее значение целевой переменной.
print(f"PCR r-squared {pcr.score(X_test, y_test):.3f}")
print(f"PLS r-squared {pls.score(X_test, y_test):.3f}")
PCR r-squared -0.026 PLS r-squared 0.658
В качестве заключительного замечания отметим, что PCR с 2 компонентами работает так же хорошо, как и PLS: это связано с тем, что в этом случае PCR смог использовать вторую компоненту, которая имеет наибольшую предсказательную силу по отношению к целевой переменной.
pca_2 = make_pipeline(PCA(n_components=2), LinearRegression())
pca_2.fit(X_train, y_train)
print(f"PCR r-squared with 2 components {pca_2.score(X_test, y_test):.3f}")
PCR r-squared with 2 components 0.673
Общее время выполнения скрипта: (0 минут 0,531 секунды)
Связанные примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/cross_decomposition/plot_pcr_vs_pls.html