1. 什么是PCA降维?
PCA(Principal Component Analysis),即主成分分析,是一种经典的降维技术。简单来说,PCA就是将高维的数据转换为低维的数据,使得数据仍能保留大部分的信息。在许多机器学习和数据分析的任务中,高维度数据会导致分类或聚类等算法的效率很低,甚至出现维数灾难。PCA的出现就解决了这个问题。
1.1 PCA的原理
PCA的主要思想是将高维数据转换成低维数据,使得低维数据集中大部分的方差能够得到保留。具体来说,PCA是通过线性变换将原有的数据投影到一个新的坐标系中,使得投影后的数据在各个维度上的方差依次递减,也就是说,第一维度上的方差最大,第二维度上的方差次之,以此类推,最后一维度上的方差最小,也就是说,将数据投影到前k个维度上即可达到降维的目的。
1.2 PCA降维的步骤
标准化数据
由于PCA是通过方差来衡量维度的重要性,因此需要将所有维度上的数据规范化为均值为0,标准差为1的标准正态分布,也就是将原始数据进行标准化。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
计算协方差矩阵
协方差矩阵是衡量两个变量之间线性关系强度的一个量,可以帮我们衡量不同维度之间的相关性。PCA是通过计算数据协方差矩阵来确定数据的主要方向。协方差矩阵的计算公式是:
cov(X) = (X - mean(X)).T.dot(X - mean(X)) / (n-1)
其中,X是标准化后的数据矩阵,mean(X)是每一维度的均值,n是样本数量。
cov_matrix = np.cov(X_scaled.T)
计算特征值和特征向量
在特征向量和特征值的计算过程中,我们需要先求解方程组Ax=λx,其中λ为特征值,x为特征向量。特征向量即我们所求的主成分方向。
cov_matrix.dot(eig_vec[:, i]) = eig_vals[i] * eig_vec[:, i]
特征值是一个向量,其每一个元素表示一个特征向量的重要程度。特征值越大,相应的特征向量所表示的维度就越重要。
eig_vals, eig_vec = np.linalg.eig(cov_matrix)
选择主成分并计算新数据集
我们要通过贡献率来决定选择哪些主成分,贡献率越大的主成分越重要,方差解释割越高代表主成分所占有的信息量越大。
tot = sum(eig_vals)
var_exp = [(i / tot) for i in sorted(eig_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)
n_components = 2 # 选择2个新维度
new_X = X_scaled.dot(eig_vec[:, :n_components])
2. 实例演示
下面通过一个实例来演示如何使用Python进行PCA降维。
2.1 导入需要的库
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
2.2 导入数据集
这里我们使用sklearn自带的iris数据集。
iris = load_iris()
X = iris.data
y = iris.target
2.3 标准化数据
将所有维度上的数据规范化为均值为0,标准差为1的标准正态分布,也就是将原始数据进行标准化。
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
2.4 计算协方差矩阵
cov_matrix = np.cov(X_scaled.T)
2.5 计算特征值和特征向量
eig_vals, eig_vec = np.linalg.eig(cov_matrix)
2.6 选择主成分并计算新数据集
选择前2个主成分。
tot = sum(eig_vals)
var_exp = [(i / tot) for i in sorted(eig_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)
n_components = 2
new_X = X_scaled.dot(eig_vec[:, :n_components])
2.7 可视化结果
将降维后的数据集进行可视化展示。
plt.scatter(new_X[:, 0], new_X[:, 1], c=y)
plt.show()
运行结果如下图所示: