主成分回归与偏最小二乘回归的比较

在这个例子中,将比较主成分回归(PCR)和偏最小二乘回归(PLS)在一个小数据集上的表现。目标是展示当目标变量与数据中的某些低方差方向强相关时,PLS如何能够超越PCR。

主成分回归(PCR)

主成分回归是一种包含两个步骤的回归器:首先,对训练数据应用主成分分析(PCA),可能进行降维;然后,在转换后的样本上训练一个回归器(例如线性回归器)。在PCA中,转换是纯粹的无监督的,这意味着没有使用关于目标变量的信息。因此,PCR可能在某些数据集中表现不佳,其中目标变量与具有低方差的方向强相关。实际上,PCA的降维将数据投影到低维空间,其中投影数据的方差沿着每个轴被贪婪地最大化。尽管它们对目标变量具有最大的预测能力,但具有较低方差的方向将被丢弃,最终的回归器将无法利用它们。

偏最小二乘回归PLS

偏最小二乘回归既是转换器又是回归器,它与PCR非常相似:它也在应用线性回归器之前对样本进行降维。与PCR的主要区别在于PLS转换是监督的。因此,正如将在本例中看到的,它不会受到刚刚提到的问题的影响。

首先创建一个具有两个特征的简单数据集。在深入研究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 # 按其方差解释能力缩放成分 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。在将数据输入PCR的PCA步骤之前,首先对其进行标准化,这是推荐的最佳实践。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"] # 检索管道中的PCA步骤 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()

正如预期的那样,PCR的无监督PCA转换丢弃了第二成分,即具有最低方差的方向,尽管它是最具预测力的方向。这是因为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}")

作为最后的评论,注意到具有2个组件的PCR表现得和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}")
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485