1. 前言
主成分分析(Principal Component Analysis, PCA)是一种常用的数据降维技术,可以通过将高维数据转化为低维数据,实现压缩数据量和提高计算效率的目的。PCA 旨在找到一个正交(orthogonal)的坐标系,将数据向这个坐标系进行映射,使得映射后的数据方差最大,从而实现降维的效果。
Python 的 scikit-learn 库提供了 PCA 的实现方法,这使得 PCA 很容易地通过 Python 进行实现。
2. PCA 的基本原理
PCA 将数据映射到一个新的坐标系(新的特征空间),这个坐标系需要满足以下条件:
2.1. 方差最大化
在新的坐标系中,第一个新特征的方差应该最大化。这意味着我们的数据在这个方向上最具有信息量。
我们可以通过以下步骤,得到第一个新特征(新的坐标系):
import numpy as np
from sklearn.decomposition import PCA
X = np.array([[2, 3], [3, 5], [4, 7], [5, 11]])
pca = PCA(n_components=1).fit(X)
new_X = pca.transform(X)
执行完成后,new_X 中保存的就是映射后的新特征值。在这个例子中,我们将 X 映射到了一个一维坐标系上,也即我们获得了一个一维的新特征。
2.2. 正交性
在求得第一个新特征的基础上,第二个特征应该设置为原始特征与第一个新特征正交的方向(垂直于第一个新特征),这样我们能够保证新的特征之间不相关。我们接着寻找第二个新特征。
2.3. 方差依次递减
新特征的数量应该等于原始特征的数量,但通常情况下我们不需要所有的新特征。我们可以将新特征按照对数据集解释变异最大的顺序,依次进行选择。一般地,我们可以通过控制新特征上的成分方差比例来制定选择新特征的数量。例如,我们可以只选择那些方差被说明百分之 x 的特征,其中 x 是一个合适数值(比如 95%)。
3. PCA 的应用
3.1.数据压缩
PCA 可以用于数据压缩。通过保留数据的主要信息,PCA 可以将高维数据压缩到低维空间中。下面是一个简单的例子:
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
digits = load_digits()
fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(10, 5))
for i, ax in enumerate(axes.flat):
ax.imshow(digits.data[i].reshape(8, 8), cmap=plt.cm.gray_r)
ax.set_xticks([]); ax.set_yticks([])
ax.set_title(f"image {i+1}")
pca = PCA(n_components=5)
X_pca = pca.fit_transform(digits.data)
print(f"Original data shape: {digits.data.shape}")
print(f"Reduced data shape: {X_pca.shape}")
fig, axes = plt.subplots(nrows=1, ncols=5, figsize=(10, 3))
for i, ax in enumerate(axes.flat):
ax.imshow(pca.components_[i].reshape(8, 8), cmap=plt.cm.gray_r)
ax.set_xticks([]); ax.set_yticks([])
ax.set_title(f"PC {i+1}")
输出结果显示,原始数据是一个 8x8 的图像,共有 64 个特征。
我们将数据压缩到 5 个特征,可以看到图片的信息并没有丢失,只是变得稍有模糊。下面还显示了前 5 个主成分,可以看到它们描述的是原始图像中主要的变化模式。
3.2. 特征提取
PCA 也可以用于特征提取。在训练多个分类器时,往往需要先构建特征集,然后再用这些特征构建对应的分类器。在这个过程中,我们可以使用 PCA 从原始特征中提取出最具有分类性的特征。
在以下示例中,我们使用 PCA 从鸢尾花数据集(Iris Dataset)中选择出最有用的特征。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=0)
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)
clf = LogisticRegression()
clf.fit(X_train_pca, y_train)
print(f"Train Score: {clf.score(X_train_pca, y_train)}")
print(f"Test Score: {clf.score(X_test_pca, y_test)}")
输出结果显示,使用 PCA 提取出的特征集比使用完整特征集得到的结果更好:
Train Score: 0.9417
Test Score: 0.9667
4. 总结
PCA 是一种非常有用的数据降维技术,可以实现数据压缩和特征提取。Python 中的 scikit-learn 库提供了 PCA 的实现方法,可以非常方便地应用于各种机器学习问题。