审稿人:PCA的误区就是"分类",但Python可以画得很漂亮!

文摘   2024-12-15 09:02   爱尔兰  

先把结论放在第一句:

PCA不应与分类(classification)或判别分析(discrimination)中的“分组”概念混为一谈。

在数据分析中,主成分分析(PCA) 是一种广泛使用的降维方法。然而,在许多论文和项目展示中,人们常常误解PCA的本质,错误地将其视为一种分组或分类工具。例如,在PCA可视化图中为不同类别画圈或用颜色区分,导致许多人误以为PCA本身进行了分组或类别判别。但是:请记住,PCA的核心目标是降维! 它的任务是通过寻找数据中“信息量最大”的方向,将高维数据映射到更低的维度,从而实现数据的简化和可视化。

为何会产生这种误解?

这是因为PCA降维后的数据往往能在低维空间中呈现出一定的结构,尤其在可视化时,不同类别的样本可能自然地分散开来。但这只是降维过程中数据分布的客观结果,而非PCA本身具备分组的能力。因此,在PCA可视化时,画圈或用颜色区分类别仅仅是为了辅助展示,而不是PCA的“功能”或“目标”。今天的更新将带你深入浅出地理解PCA的基本概念,掌握如何用Python实现PCA,并通过高度美学优化的可视化,让结果一目了然!

一、PCA理论直观理解

在不涉及复杂公式的情况下,我们来理解PCA的核心思想:

  1. 高维数据如何降维?
    数据有很多个特征,有时候,我们并不需要每个特征。PCA会找到数据中“信息量”最大的方向(称为主成分),并将数据映射到这些方向上。

  2. 如何保留关键信息?
    PCA会按顺序排列这些“信息量最大的方向”,确保尽量少的维度下,仍能保留最多的数据变化信息。

  3. 结果是什么?

  • 降维后的数据(更少的特征)。

  • 每个主成分对应的重要性(解释方差比例)。

简单来说,PCA帮你找到数据“最重要的几个方面”,然后通过降维让数据更易于分析、可视化。

二、PCA实现:手把手代码教程

我们将使用Python的sklearn库和matplotlib/seaborn进行实现和美学优化的可视化。这里,我们使用经典的iris数据集(鸢尾花数据集),它包含4个特征:花萼长度、花萼宽度、花瓣长度和花瓣宽度。

代码如下:


import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from matplotlib.patches import Ellipse
import seaborn as sns

# 设置Seaborn风格
sns.set(style="whitegrid", palette="muted", font_scale=1.2)

# 加载Iris数据集
data = load_iris()
X = data.data # 特征矩阵
y = data.target # 标签
target_names = data.target_names

# PCA降维到2维
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# 计算置信椭圆
def plot_confidence_ellipse(ax, x, y, n_std=2.0, facecolor='none', edgecolor='black', alpha=0.3, **kwargs):
"""
在给定的轴上绘制置信椭圆
"""

if x.size != y.size:
raise ValueError("x 和 y 的尺寸必须相同")

cov = np.cov(x, y) # 计算协方差矩阵
mean_x, mean_y = np.mean(x), np.mean(y) # 计算均值

# 计算椭圆的主轴长度和角度
lambda_, v = np.linalg.eig(cov)
lambda_ = np.sqrt(lambda_)
angle = np.degrees(np.arctan2(*v[:, 0][::-1]))

# 绘制椭圆
ellipse = Ellipse((mean_x, mean_y), width=lambda_[0]*n_std*2, height=lambda_[1]*n_std*2,
angle=angle, facecolor=facecolor, edgecolor=edgecolor, alpha=alpha, linewidth=2, **kwargs)
ax.add_patch(ellipse)

# 创建图形
fig, ax = plt.subplots(figsize=(10, 7))

# 调色板
colors = sns.color_palette("husl", n_colors=3)

# 绘制数据点和置信椭圆
for i, target_name in enumerate(target_names):
x_pca = X_pca[y == i, 0]
y_pca = X_pca[y == i, 1]
ax.scatter(x_pca, y_pca, s=100, label=target_name, color=colors[i], edgecolor='k', linewidth=0.8, alpha=0.7)
plot_confidence_ellipse(ax, x_pca, y_pca, n_std=2.0, edgecolor=colors[i], alpha=0.2)

# 美化坐标轴
ax.set_xlabel('PCA Component 1', fontsize=14, fontweight='bold')
ax.set_ylabel('PCA Component 2', fontsize=14, fontweight='bold')
ax.set_title('PCA of IRIS Dataset with 95% Confidence Ellipses', fontsize=16, fontweight='bold', pad=15)

# 设置图例位置在坐标系外部
ax.legend(
title='Species',
loc='upper left',
bbox_to_anchor=(1.05, 1), # 将图例放在右侧外部
fontsize=12,
title_fontsize=13
)

# 美化网格与边框
ax.grid(True, linestyle='--', alpha=0.5)
sns.despine(trim=True, offset=10)

# 显示图形
plt.tight_layout()
plt.show()

PCA不仅降维,还可以告诉我们每个主成分的重要性。

# 查看主成分的重要性
explained_variance_ratio = pca.explained_variance_ratio_
print(f'PC1解释的方差比例: {explained_variance_ratio[0]:.2f}')

## PC1解释的方差比例: 0.92

print(f'PC2解释的方差比例: {explained_variance_ratio[1]:.2f}')

## PC2解释的方差比例: 0.05

主成分的重要性可以直观地反映每个主成分所包含的信息量。在实际分析中,这有助于我们判断降维后的数据是否保留了足够的信息。

三、总结

希望今天的示例能直观展示PCA的核心思想,其实,只要根据你的原始数据适当调整代码,即可将今天的知识无缝衔接到你的数据分析中。欢迎大胆尝试!有问题评论区留言!

感谢关注,你的支持是我不懈的动力!

科研代码
专注R和Python的数据分析。
 最新文章