PCA主成分分析与Python应用
一.原理简介
主成分分析(Principal Compoent Analysis,PCA)是一种常用的统计方法和降维技术,用于从高维数据中提取重要信息,减少数据的维度,同时尽可能保留数据的关键特征和变化信息。
PCA通过将原始数据投射到新的坐标系统中,使得新的坐标轴(主成分)能够最大程度地解释数据的方差
在PCA中方差是一个非常重要的概念,它可以帮助我们理解数据的分布和变化情况。
方差表示数据点与数据集平均值之间的差异程度。方差越大表明数据点在平均值周围的分布越分散:方差越小,数据点越集中在平均值附近
对于一组数据X={x1,x2,…,xn},其方差 Var(X) 的计算公式为:
其中n是数据点的数量,是第i个书记点,
是数据的平均值
在特征选择中,方差较小的特征通常包含的信息较少,因为它们的值变化不大。这样的特征对模型的预测能力有限,甚至可能引入噪声。所以一般都是选择高方差的特征
而PCA其目标是找到数据中方差最大的方向(主成分),并将数据投影到这些方向上,通过保留方差较大的主成分,可以最大程度地保留数据的信息
二.原理实现(简述)
计算数据的协方差矩阵,求解其特征值和特征向量。特征值表示每个主成分的方差,特征向量表示主成分的方向
1.解释方差贡献率(explained_variance_ratio_)
解释方差贡献率表示每个主成分对数据方差的贡献比例。通过选择累计解释方差贡献率达到一定的比例(比如80%到95%)的主成分,可以有效降低数据维度,同时保留大部分信息
方差贡献率的数学计算公式:
方差贡献率 =
其中是第i个主成分的特征值,n是原始变量的维度
from sklearn.decomposition import PCA
import numpy as np# 示例数据
X = np.array([[2.5, 2.4, 3.1],[0.5, 0.7, 0.9],[2.2, 2.9, 3.0],[1.9, 2.2, 2.8],[3.1, 3.0, 3.5],[2.3, 2.9, 3.2],[2.0, 1.8, 2.7],[1.0, 1.5, 1.2],[1.5, 1.0, 1.8],[1.1, 0.9, 1.0]])# 数据标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# 应用PCA
pca = PCA()
pca.fit(X_scaled)# 获取方差贡献率
explained_variance_ratio = pca.explained_variance_ratio_
print("方差贡献率:", explained_variance_ratio)
输出:方差贡献率: [0.72770452 0.23943054 0.03286494]
解释:第一个主成分(PC1)解释了总方差的约72.77%
第二个主成分(PC2)解释了总方差的约23.94%
第三个主成分(PC3)解释了总方差的约3.29%
2.累计方差贡献率
累计方差贡献率表示前k个主成分对数据总方差的累计贡献比例。通常用于确定保留多少个主成分
数学计算公式:
累计方差贡献率 = 方差贡献率_{i}
# 计算累计方差贡献率
cumulative_explained_variance_ratio = np.cumsum(pca.explained_variance_ratio_)
print("累计方差贡献率:", cumulative_explained_variance_ratio)
输出:累计方差贡献率: [0.72770452 0.96713506 1. ]
解释:前两个主成分累计解释了总方差的约96.71%
3.方差值(pca.explain_variance_)
方差值表示每个主成分的方差大小
# 获取方差值
explained_variance = pca.explained_variance_
print("方差值:", explained_variance)
输出:方差值: [2.18285492 0.71743287 0.09846213]
解释:第一个主成分的方差值约为2.18
第二个主成分的方差值约为0.72
可以根据累计方差贡献率来选择保留的主成分数量。通常保留能够解释80%到95%累计方差的主成分数量
4.主成分的载荷,也称特征向量(pca.components_)
载荷表示主成分与原始变量之间的线性关系
正载荷表示原始变量与主成分之间存在正相关关系,负载荷则表示负相关关系
作用:
pca.components_返回一个数组,每一行代表一个主成分,每一列对于原始变量的载荷
通过载荷,可以理解每个主成分是由哪些原始变量主导的,可以使用这些载荷将原始数据转换到主成分空间,即进行降维
假设我们有一个数据集,包含3个原始变量:x1,x2,x3,我们对数据进行主成分分析,并保留两个主成分
import numpy as np
from sklearn.decomposition import PCA# 示例数据
X = np.array([[2.5, 2.4, 3.1],[0.5, 0.7, 0.9],[2.2, 2.9, 3.0],[1.9, 2.2, 2.8],[3.1, 3.0, 3.5],[2.3, 2.9, 3.2],[2.0, 1.8, 2.7],[1.0, 1.5, 1.2],[1.5, 1.0, 1.8],[1.1, 0.9, 1.0]])# 数据标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# 应用PCA
pca = PCA(n_components=2) # 保留2个主成分
pca.fit(X_scaled)# 获取主成分载荷
components = pca.components_
print(components)
输出可能是这样的:
[[ 0.65659969 0.73016143 0.73016143]
[-0.73016143 0.65659969 0.65659969]]
含义解释:
第一主成分:载荷为[0.6566, 0.7302, 0.7302],表示PC1 = 0.6566·x1 + 0.7302·x2 + 0.7302 ·x3
这个成分主要由x2和x3主导
第二主成分:载荷为[-0.7302, 0.6566, 0.6566],表示PC2 = -0.7302·x1 + 0.6566 · x2 + 0.6566 ·x3 这个成分主要由x1主导
三.原理的一些小应用
1.主成分和贡献率相乘
主成分和贡献率相乘实际是对每个主成分进行加权。贡献率作为权重,反应了每个主成分的重要性
将加权后的主成分相加得到一个综合得分F,F是一个综合指标,用于评估每个样本的综合表现
将主成分与贡献率相乘后求和,可以构造一个综合得分,用于评估每个样本的综合表现。贡献率作为权重确保更重要的主成分对综合得分的影响更大。这种方法在实际应用中非常有用,尤其是在需要对样本进行排序或评估的场景中
import numpy as np
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt# 随机生成10个公司的财务数据,每个公司有5个财务指标
np.random.seed(42)
X = np.random.rand(10, 5) * 100 # 10个公司,5个财务指标# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# 应用PCA,保留所有主成分以便查看贡献率
pca = PCA()
pca.fit(X_scaled)# 输出主成分载荷和贡献率
components = pca.components_
explained_variance_ratio = pca.explained_variance_ratio_
print("主成分载荷:\n", components)
print("贡献率:\n", explained_variance_ratio)# 计算综合得分
Y = pca.transform(X_scaled) # 获取主成分
F = np.zeros(Y.shape[0]) # 初始化综合得分数组
for i in range(Y.shape[1]):F += Y[:, i] * explained_variance_ratio[i] # 将每个主成分乘以贡献率并相加# 输出综合得分
print("综合得分:\n", F)# 绘制综合得分柱状图
plt.figure(figsize=(10, 6))
plt.bar(range(1, 11), F, color='skyblue')
plt.xlabel('公司编号')
plt.ylabel('综合得分')
plt.title('公司综合财务得分')
plt.xticks(range(1, 11))
plt.show()# 绘制主成分和综合得分的散点图
plt.figure(figsize=(10, 6))
plt.scatter(Y[:, 0], Y[:, 1], c=F, cmap='viridis')
plt.colorbar(label='综合得分')
plt.xlabel('主成分1')
plt.ylabel('主成分2')
plt.title('公司主成分与综合得分关系')
plt.show()