PCA:
主成分分析(PCA, Principal Component Analysis)是一种常用的数据降维技术,它可以将高维数据转换为较低维数据,同时尽可能保留数据的主要信息。PCA通过寻找数据的主要方向,即方差最大的方向,来完成降维。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。
降维:
-
降维就是一种对高维度特征数据预处理方法。降维是将高维度的数据保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的。在实际的生产和应用中,降维在一定的信息损失范围内,可以为我们节省大量的时间和成本。降维也成为应用非常广泛的数据预处理方法。
-
数据降维,直观地好处是维度降低了,便于计算和可视化,其更深层次的意义在于有效信息的提取综合及无用信息的摈弃。
擒贼先擒王:
PCA(Principal Components Analysis)即主成分分析,是图像处理中经常用到的降维方法。它不仅仅是对高维数据进行降维,更重要的是经过降维去除了噪声,发现了数据中的模式。PCA把原先的n个特征用数目更少的m个特征取代,新特征是旧特征的线性组合,这些线性组合最大化样本方差,尽量使新的m个特征互不相关。
PCA方法通过消除数据的相关性,找到一个空间,使得各个类别的数据在该空间上能够很好地分离。在下图中,有一些离散的二维分布点,其中棕色表示一类集合,黄色表示另一类集合,假设这两个类别可以用特征X和特征Y进行描述,由图可知,在X轴和Y轴上这两个类别的投影是重叠的,表明这些点的两个特征X和Y没有表现出突出的识别性。但是两个类的投影在Z轴上区分度较大,显示出很好的识别性。PCA就是这样的一个工具,它可以产生非常好的降维效果。
示例:
二维数据降到一维:
PCA算法在二维数据集上的可视化图示,展示了如何将数据从二维降维到一维。图中显示了原始数据点、主成分向量以及数据点投影到第一个主成分上的过程。
使用numpy
实现PCA:
import numpy as np# 定义PCA函数
def pca(X, num_components):# 1. 数据标准化(均值归一化)X_meaned = X - np.mean(X, axis=0)# 2. 计算协方差矩阵cov_matrix = np.cov(X_meaned, rowvar=False)# 3. 计算协方差矩阵的特征值和特征向量eigen_values, eigen_vectors = np.linalg.eigh(cov_matrix)# 4. 对特征值排序sorted_index = np.argsort(eigen_values)[::-1]sorted_eigenvalue = eigen_values[sorted_index]sorted_eigenvectors = eigen_vectors[:, sorted_index]# 5. 选择前num_components个特征向量(主成分)eigenvector_subset = sorted_eigenvectors[:, 0:num_components]# 6. 将数据投影到新空间X_reduced = np.dot(X_meaned, eigenvector_subset)return X_reduced, sorted_eigenvalue, sorted_eigenvectors# 示例数据
X = np.array([[2.5, 2.4],[0.5, 0.7],[2.2, 2.9],[1.9, 2.2],[3.1, 3.0],[2.3, 2.7],[2, 1.6],[1, 1.1],[1.5, 1.6],[1.1, 0.9]])# 执行PCA
X_reduced, eigen_values, eigen_vectors = pca(X, 1)print("降维后的数据:\n", X_reduced)
print("特征值:\n", eigen_values)
print("特征向量:\n", eigen_vectors)
运行结果分析:
降维后的数据:[[ 0.82797019][-1.77758033][ 0.99219749][ 0.27421042][ 1.67580142][ 0.9129491 ][-0.09910944][-1.14457216][-0.43804614][-1.22382056]]特征值:[0.0490834 1.28402771]特征向量:[[-0.73517866 -0.6778734 ][-0.6778734 0.73517866]]
解释:
- 降维后的数据:原本二维数据集现在被降到了1维。每个样本在新的主成分方向上都有一个值,数据被映射到了这个新的空间。
- 特征值:两个特征值中,
1.28402771
对应的主成分解释了数据中的大部分方差(信息量)。特征值越大,表明该方向上的方差越大,信息量越多。- 特征向量:每个特征向量表示PCA找到的主成分方向。第一个向量是方向,它解释了最多的方差。
使用sklearn
实现PCA:
from sklearn.decomposition import PCApca = PCA(n_components=1)
X_reduced_sklearn = pca.fit_transform(X)
print("降维后的数据:\n", X_reduced_sklearn)
print("解释方差比:\n", pca.explained_variance_ratio_)
运行结果分析:
降维后的数据:[[-0.82797019][ 1.77758033][-0.99219749][-0.27421042][-1.67580142][-0.9129491 ][ 0.09910944][ 1.14457216][ 0.43804614][ 1.22382056]]
解释方差比:[0.96318131]
解释:
- 降维后的数据:
sklearn
的结果和numpy
的实现相同。 - 解释方差比:第一个主成分解释了大约96.32%的数据方差。这意味着几乎所有的主要信息都保留在这个一维空间中。
三维数据降到二维:
使用numpy
实现PCA:
import numpy as np# 定义PCA函数
def pca(X, num_components):# 1. 数据标准化(均值归一化)X_meaned = X - np.mean(X, axis=0)# 2. 计算协方差矩阵cov_matrix = np.cov(X_meaned, rowvar=False)# 3. 计算协方差矩阵的特征值和特征向量eigen_values, eigen_vectors = np.linalg.eigh(cov_matrix)# 4. 对特征值排序sorted_index = np.argsort(eigen_values)[::-1]sorted_eigenvalue = eigen_values[sorted_index]sorted_eigenvectors = eigen_vectors[:, sorted_index]# 5. 选择前num_components个特征向量(主成分)eigenvector_subset = sorted_eigenvectors[:, 0:num_components]# 6. 将数据投影到新空间X_reduced = np.dot(X_meaned, eigenvector_subset)return X_reduced, sorted_eigenvalue, sorted_eigenvectors# 示例数据
X_3D = np.array([[2.5, 2.4, 1.5],[0.5, 0.7, 0.9],[2.2, 2.9, 2.1],[1.9, 2.2, 1.8],[3.1, 3.0, 2.9],[2.3, 2.7, 1.9],[2.0, 1.6, 1.5],[1.0, 1.1, 0.6],[1.5, 1.6, 1.1],[1.1, 0.9, 0.7]])
X_reduced_3D, eigen_values_3D, eigen_vectors_3D = pca(X_3D, 2)
print("降维后的数据:\n", X_reduced_3D)
print("特征值:\n", eigen_values_3D)
print("特征向量:\n", eigen_vectors_3D)
运行结果分析:
降维后的数据:[[-0.70889453 -0.46108745][ 1.83196957 0.42891188][-1.16005691 0.12212606][-0.38989499 0.15041607][-2.15763363 0.25019311][-0.98864791 -0.06737495][ 0.08538904 -0.06151523][ 1.4447941 -0.15563484][ 0.58162174 -0.10471513][ 1.46135351 -0.10131952]]
特征值:[1.7286401 0.06116445 0.04775101]
特征向量:[[-0.57953314 -0.5637771 -0.58846981][-0.63064625 -0.14710458 0.76200102][-0.51616533 0.81272112 -0.27029193]]
解释:
- 降维后的数据:原本三维的数据集现在降到了二维,表示数据在新的两个主成分方向上的投影。
- 特征值:第一个特征值
1.7286401
远大于另外两个,意味着第一个主成分解释了绝大部分的数据方差。第二个主成分解释了少量的方差,而第三个几乎没有方差,因此可以忽略。- 特征向量:这些向量表示主成分的方向,第一个向量是解释方差最多的方向
使用sklearn
实现PCA:
from sklearn.decomposition import PCApca_3D = PCA(n_components=2)
X_reduced_3D_sklearn = pca_3D.fit_transform(X_3D)
print("降维后的数据:\n", X_reduced_3D_sklearn)
print("解释方差比:\n", pca_3D.explained_variance_ratio_)
运行结果分析:
降维后的数据:[[ 0.70889453 0.46108745][-1.83196957 -0.42891188][ 1.16005691 -0.12212606][ 0.38989499 -0.15041607][ 2.15763363 -0.25019311][ 0.98864791 0.06737495][-0.08538904 0.06151523][-1.4447941 0.15563484][-0.58162174 0.10471513][-1.46135351 0.10131952]]
解释方差比:[0.94072807 0.03328577]
解释:
- 降维后的数据:与
numpy
的实现结果一致。- 解释方差比:两个主成分一共解释了约97.40%的方差,其中第一个主成分解释了绝大部分数据方差(约94.07%),第二个主成分解释了少量方差(约3.30%)。
鸢尾花数据集:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler# 1. 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names# 2. 标准化数据
X_standardized = StandardScaler().fit_transform(X)# 3. 执行PCA
pca = PCA(n_components=2) # 选择前两个主成分
X_pca = pca.fit_transform(X_standardized)# 4. 绘制PCA散点图
plt.figure(figsize=(8, 6))
colors = ['navy', 'turquoise', 'darkorange']
lw = 2for color, i, target_name in zip(colors, [0, 1, 2], target_names):plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], color=color, alpha=.8, lw=lw,label=target_name)plt.title('PCA of IRIS Dataset')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.grid()
plt.show()# 5. 绘制投影图
plt.figure(figsize=(10, 6))
plt.scatter(X_standardized[:, 0], X_standardized[:, 1], alpha=0.5)
plt.quiver(0, 0, pca.components_[0, 0], pca.components_[0, 1], angles='xy', scale_units='xy', scale=1, color='r')
plt.quiver(0, 0, pca.components_[1, 0], pca.components_[1, 1], angles='xy', scale_units='xy', scale=1, color='g')
plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.title('PCA Projection of IRIS Dataset')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.grid()
plt.show()# 6. 解释方差图
plt.figure(figsize=(8, 4))
plt.bar(range(1, len(pca.explained_variance_ratio_) + 1), pca.explained_variance_ratio_, alpha=0.7)
plt.ylabel('Explained Variance Ratio')
plt.xlabel('Principal Components')
plt.title('Explained Variance by Principal Components')
plt.xticks(range(1, len(pca.explained_variance_ratio_) + 1))
plt.show()# 7. 降维效果图
plt.figure(figsize=(8, 6))
plt.scatter(X_pca[:, 0], X_pca[:, 1], alpha=0.7, c=y, edgecolor='k', cmap=plt.cm.Paired)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('PCA Result on IRIS Dataset')
plt.colorbar()
plt.grid()
plt.show()
PCA(主成分分析)图示通常包括以下几种代表性的图:
原始数据点与主成分向量:显示数据点和主成分方向的二维散点图。主成分向量通常以箭头表示,显示数据方差最大的方向。
数据投影到主成分上的图:显示原始数据点投影到主成分上后的图形,展示如何从高维数据降维到低维空间。
特征值与主成分的解释方差:条形图或饼图显示各主成分解释的方差比例,帮助理解每个主成分在数据中所占的比重。
降维后的数据分布:数据在降维后的低维空间中的分布图,通常用于可视化降维效果。
下面是这些图的描述:
原始数据点与主成分向量:
- 散点图显示原始数据点,主成分方向作为箭头,通常两个主成分向量互相垂直。
数据投影图:
- 显示数据点如何沿主成分方向投影到低维空间,突出显示主成分方向和投影后的数据点。
特征值图:
- 条形图或饼图展示每个主成分的解释方差比例,说明主成分对数据总方差的贡献。
降维后数据分布图:
- 降维后(例如从三维到二维)的数据点分布,通常用散点图展示,显示数据的结构和分布。