机器学习算法之主成分分析法(PCA)

作者名片
🤵‍♂️ 个人主页:@抱抱宝
😄微信公众号:宝宝数模AI(见文末)
✍🏻作者简介:阿里云专家博主 | 持续分享机器学习、数学建模、数据分析、AI人工智能领域相关知识,和大家一起进步!
🐋 如果文章对你有帮助的话,
欢迎👍🏻点赞📂收藏 +关注


在机器学习领域,降维是一个非常重要的步骤。它不仅可以减少数据的复杂性,还能在一定程度上去除噪声,提高模型的性能。主成分分析(Principal Component Analysis,简称PCA) 作为一种经典的降维算法,广泛应用于数据预处理、特征提取和可视化等方面。本文将深入介绍PCA的算法原理,并通过案例分析展示其实际应用。

一、算法介绍

主成分分析(PCA)是一种线性降维技术,旨在通过正交变换将高维数据投影到一个低维空间中,同时尽可能保留数据的主要信息。PCA通过找到数据中方差最大的方向(即主成分),将数据沿这些方向进行投影,从而实现降维。

PCA的主要步骤包括:

  1. 数据标准化:对原始数据进行均值归一化,使得每个特征的均值为零,方差为一。
  2. 计算协方差矩阵:衡量不同特征之间的线性相关性。
  3. 求解特征值和特征向量:协方差矩阵的特征值和特征向量决定了主成分的方向和重要性。
  4. 选择主成分:根据特征值的大小选择前 k k k个主成分。
  5. 转换数据:将原始数据投影到选定的主成分上,得到降维后的数据。

二、算法原理

2.1 数据标准化

假设我们有一个包含 n n n个样本和 m m m个特征的数据集,表示为矩阵 X ∈ R n × m X \in \mathbb{R}^{n \times m} XRn×m。首先,对每个特征进行标准化处理,使其均值为零,方差为一:

X n o r m = X − μ σ X_{norm} = \frac{X - \mu}{\sigma} Xnorm=σXμ

其中, μ \mu μ是每个特征的均值, σ \sigma σ是标准差。

2.2 计算协方差矩阵

协方差矩阵 C C C用于描述不同特征之间的线性相关性:

C = 1 n − 1 X n o r m T X n o r m C = \frac{1}{n-1} X_{norm}^T X_{norm} C=n11XnormTXnorm

2.3 求解特征值和特征向量

通过对协方差矩阵 C C C进行特征值分解,得到特征值 λ i \lambda_i λi和对应的特征向量 v i v_i vi。特征值反映了对应特征向量所代表的主成分的重要性。

2.4 选择主成分

选择前 k k k个最大的特征值对应的特征向量,构成投影矩阵 W W W

W = [ v 1 , v 2 , … , v k ] W = [v_1, v_2, \dots, v_k] W=[v1,v2,,vk]

2.5 转换数据

将原始数据投影到选定的主成分上,得到降维后的数据 Y Y Y

Y = X n o r m W Y = X_{norm} W Y=XnormW

三、案例分析

为了更好地理解PCA的应用,我们将使用Wine(葡萄酒)数据集进行案例分析。Wine数据集包含178个样本,每个样本有13个特征,如酒精含量、苹果酸含量、灰分含量等。由于特征数量较多,我们将通过累计方差贡献度来确定合适的降维维数,并最终进行可视化展示。

3.1 数据准备

首先,导入必要的库,并加载Wine数据集。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import StandardScaler

# 加载Wine数据集
wine = datasets.load_wine()
X = wine.data  # 特征数据
y = wine.target  # 类别标签
feature_names = wine.feature_names
target_names = wine.target_names

3.2 数据标准化

对数据进行标准化处理,使每个特征的均值为零,方差为一。

# 标准化
scaler = StandardScaler()
X_std = scaler.fit_transform(X)

3.3 计算协方差矩阵

计算标准化后的数据的协方差矩阵。

# 计算协方差矩阵
cov_matrix = np.cov(X_std.T)
print("协方差矩阵:\n", cov_matrix)

部分计算结果:

协方差矩阵:
 [[ 1.00564972  0.09493026  0.21273976 -0.31198788  0.27232816  0.29073446
   0.23815287 -0.15681042  0.13747022  0.549451   -0.07215255  0.07275191
   0.64735687]
 [ 0.09493026  1.00564972  0.16497228  0.29013035 -0.05488343 -0.3370606
  -0.41332866  0.29463237 -0.22199334  0.25039204 -0.56446685 -0.37079354
  -0.19309537]
 [ 0.21273976  0.16497228  1.00564972  0.44587209  0.28820583  0.12970824
   0.11572743  0.1872826   0.00970647  0.2603499  -0.07508874  0.00393333
   0.22488969]
 [-0.31198788  0.29013035  0.44587209  1.00564972 -0.0838039  -0.32292752
  -0.353355    0.36396647 -0.19844168  0.01883781 -0.27550299 -0.27833221
  -0.44308618]

3.4 求解特征值和特征向量

对协方差矩阵进行特征值分解,获取特征值和特征向量。

# 特征值分解
eig_vals, eig_vecs = np.linalg.eig(cov_matrix)
print("特征值:\n", eig_vals)
print("特征向量:\n", eig_vecs)

计算结果:

特征值:
 [4.73243698 2.51108093 1.45424187 0.92416587 0.85804868 0.64528221
 0.55414147 0.10396199 0.35046627 0.16972374 0.29051203 0.22706428
 0.25232001]
 部分特征向量:
 [[-0.1443294  -0.48365155  0.20738262 -0.0178563   0.26566365 -0.21353865
  -0.05639636  0.01496997 -0.39613926  0.26628645  0.50861912 -0.22591696
   0.21160473]
 [ 0.24518758 -0.22493093 -0.08901289  0.53689028 -0.03521363 -0.53681385
   0.42052391  0.02596375 -0.06582674 -0.12169604 -0.07528304  0.07648554
  -0.30907994]
 [ 0.00205106 -0.31606881 -0.6262239  -0.21417556  0.14302547 -0.15447466
  -0.14917061 -0.14121803  0.17026002  0.04962237 -0.30769445 -0.49869142
  -0.02712539]
 [ 0.23932041  0.0105905  -0.61208035  0.06085941 -0.06610294  0.10082451
  -0.28696914  0.09168285 -0.42797018  0.05574287  0.20044931  0.47931378
   0.05279942]

3.5 计算累计方差贡献度

为了确定保留多少个主成分,我们需要计算累计方差贡献度,并绘制其随主成分个数变化的曲线。

# 5. 计算累计方差贡献度
explained_variances = eig_vals / np.sum(eig_vals)
cumulative_explained_variances = np.cumsum(explained_variances)

# 绘制累计方差贡献度曲线
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(cumulative_explained_variances)+1), cumulative_explained_variances, marker='o', linestyle='--', color='b')
plt.xlabel('主成分个数')
plt.ylabel('累计方差贡献度')
plt.title('累计方差贡献度随主成分个数的变化')
plt.grid(True)
plt.axhline(y=0.85, color='r', linestyle='-')  # 设定85%的参考线
plt.text(0.5, 0.86, '85% 参考线', color = 'red', fontsize=12)
plt.show()

通过观察累计方差贡献度曲线,我们可以选择主成分个数 k k k,使得累计方差贡献度达到一个预设的阈值(如85%),从而在尽量保留原始数据信息的前提下,实现有效降维。

3.6 选择主成分

根据累计方差贡献度曲线,我们选择保留前6个主成分,以达到85%的方差解释率。

# 6. 根据累计方差贡献图选择前6个主成分
k = 6
sorted_indices = np.argsort(eig_vals)[::-1]
topk_indices = sorted_indices[:k]
W = eig_vecs[:, topk_indices]
print(f"投影矩阵 W(前{k}个主成分):\n", W)

计算结果:

投影矩阵 W(前6个主成分):
 [[-0.1443294  -0.48365155  0.20738262 -0.0178563   0.26566365 -0.21353865]
 [ 0.24518758 -0.22493093 -0.08901289  0.53689028 -0.03521363 -0.53681385]
 [ 0.00205106 -0.31606881 -0.6262239  -0.21417556  0.14302547 -0.15447466]
 [ 0.23932041  0.0105905  -0.61208035  0.06085941 -0.06610294  0.10082451]
 [-0.14199204 -0.299634   -0.13075693 -0.35179658 -0.72704851 -0.03814394]
 [-0.39466085 -0.06503951 -0.14617896  0.19806835  0.14931841  0.0841223 ]
 [-0.4229343   0.00335981 -0.1506819   0.15229479  0.10902584  0.01892002]
 [ 0.2985331  -0.02877949 -0.17036816 -0.20330102  0.50070298  0.25859401]
 [-0.31342949 -0.03930172 -0.14945431  0.39905653 -0.13685982  0.53379539]
 [ 0.0886167  -0.52999567  0.13730621  0.06592568  0.07643678  0.41864414]
 [-0.29671456  0.27923515 -0.08522192 -0.42777141  0.17361452 -0.10598274]
 [-0.37616741  0.16449619 -0.16600459  0.18412074  0.10116099 -0.26585107]
 [-0.28675223 -0.36490283  0.12674592 -0.23207086  0.1578688  -0.11972557]]

3.7 转换数据

将原始数据投影到选定的主成分上,得到降维后的数据。

# 7. 转换数据
Y = X_std.dot(W)
print("降维后的数据(前6个样本):\n", Y[:6])

计算结果:

降维后的数据(前6个样本):
 [[-3.31675081 -1.44346263  0.16573904 -0.21563119 -0.69304284 -0.22388013]
 [-2.20946492  0.33339289  2.02645737 -0.29135832  0.25765463 -0.92712024]
 [-2.51674015 -1.0311513  -0.98281867  0.72490231  0.25103312  0.54927605]
 [-3.75706561 -2.75637191  0.17619184  0.56798331  0.31184159  0.114431  ]
 [-1.00890849 -0.86983082 -2.02668822 -0.40976579 -0.2984575  -0.4065196 ]
 [-3.05025392 -2.12240111  0.62939583 -0.51563749  0.63201873  0.12343056]]

3.8 可视化

由于选择了6个主成分,为了便于可视化,我们可以进一步将数据降维到2维,或者使用前两个主成分进行二维可视化。

# 8. 可视化(选择前2个主成分)
W_2d = eig_vecs[:, sorted_indices[:2]]
Y_2d = X_std.dot(W_2d)

plt.figure(figsize=(10, 8))
for target, color, label in zip([0,1,2], ['r', 'g', 'b'], target_names):
    plt.scatter(Y_2d[y == target, 0], Y_2d[y == target, 1], 
                c=color, label=label, edgecolor='k', s=60)
plt.xlabel('主成分1')
plt.ylabel('主成分2')
plt.title('PCA 降维后的Wine数据(2维)')
plt.legend()
plt.grid(True)
plt.show()

3.9 使用Scikit-learn实现PCA

为了验证手动计算的结果,我们还可以使用scikit-learn库中的PCA模块进行降维,并绘制累计方差贡献度曲线。

# 9. 使用Scikit-learn的PCA
pca = PCA(n_components=13)  # 保留所有主成分以计算累计方差
pca.fit(X_std)
cumulative_explained_variances_sklearn = np.cumsum(pca.explained_variance_ratio_)

# 绘制累计方差贡献度曲线
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(cumulative_explained_variances_sklearn)+1), cumulative_explained_variances_sklearn, marker='o', linestyle='--', color='g')
plt.xlabel('主成分个数')
plt.ylabel('累计方差贡献度')
plt.title('Scikit-learn PCA 累计方差贡献度')
plt.grid(True)
plt.axhline(y=0.85, color='r', linestyle='-')  # 设定85%的参考线
plt.text(0.5, 0.86, '85% 参考线', color = 'red', fontsize=12)
plt.show()

# 选择前6个主成分
pca = PCA(n_components=6)
Y_sklearn = pca.fit_transform(X_std)
print("scikit-learn降维后的数据(前6个主成分,前6个样本):\n", Y_sklearn[:5])

# 使用前两个主成分进行可视化
pca_2d = PCA(n_components=2)
Y_sklearn_2d = pca_2d.fit_transform(X_std)

# 可视化
plt.figure(figsize=(10, 8))
for target, color, label in zip([0,1,2], ['r', 'g', 'b'], target_names):
    plt.scatter(Y_sklearn_2d[y == target, 0], Y_sklearn_2d[y == target, 1], 
                c=color, label=label, edgecolor='k', s=60)
plt.xlabel('主成分1')
plt.ylabel('主成分2')
plt.title('Scikit-learn PCA 降维后的Wine数据(2维)')
plt.legend()
plt.grid(True)
plt.show()

scikit-learn降维后的数据(前6个主成分,前6个样本):
 [[ 3.31675081  1.44346263 -0.16573904 -0.21563119  0.69304284  0.22388013]
 [ 2.20946492 -0.33339289 -2.02645737 -0.29135832 -0.25765463  0.92712024]
 [ 2.51674015  1.0311513   0.98281867  0.72490231 -0.25103312 -0.54927605]
 [ 3.75706561  2.75637191 -0.17619184  0.56798331 -0.31184159 -0.114431  ]
 [ 1.00890849  0.86983082  2.02668822 -0.40976579  0.2984575   0.4065196 ]]

四、总结

主成分分析(PCA)是一种强大的降维工具,通过线性变换将高维数据映射到低维空间,同时保留数据中的主要信息。在实际应用中,PCA不仅可以用于数据压缩和特征提取,还可以帮助我们更好地理解数据结构。希望通过本文的介绍和案例分析,能够让你对PCA有更深入的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抱抱宝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值