目标
本实验通过主成分分析(PCA)技术对鸢尾花数据集进行降维,旨在:使用PCA将原始4维数据降到2维,并进行可视化。分析降维前后数据的分布和类别区分情况。评估PCA对数据方差解释率的贡献,以便在最少维度中保留最多信息。
环境
Python编程语言
Scikit-learn库
Matplotlib(用于数据可视化)
NumPy和Pandas库(用于数据处理)
Jupyter Notebook或类似IDE(用于代码编写和结果展示)
实验数据集
本实验使用的是鸢尾花数据集(Iris dataset),它是一个经典的多分类数据集,包含150个样本,4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度),以及3个目标类别(Setosa、Versicolor、Virginica)。
步骤
1. 数据加载与初步探索
加载鸢尾花数据集,获取特征数据X和目标标签y。
2. 标准化特征
使用StandardScaler对特征数据进行标准化,使每个特征的均值为0,方差为1,以便消除量纲差异。
3. 原始数据可视化
使绘制原始数据的前两个特征,以便在降维前观察数据的分布。
4. 应用PCA降维
使用PCA将标准化后的数据从4维降到2维。
5. 降维后数据可视化
将降维后的2维数据进行可视化,用颜色区分类别,展示PCA在二维空间中的数据表现。
6. 方差解释率分析
计算每个主成分对方差的解释率,并绘制累计方差解释率图,观察PCA如何保留主要信息。
结果展示
原始数据的前两个特征图:展示了降维前的原始数据(4维中的两个特征)的分布情况。
降维后的2维数据图:在降维后的二维空间中显示各类别数据点的分布情况,展示了PCA保留的主要信息。
累计方差解释率图:通过累计方差解释率图观察不同数量主成分对信息量的保留情况,以帮助决定在降维中需要保留的维度数。
实验代码
以下是一个PCA实现的实验代码(使用鸢尾花数据集):
导入必要的库
imporimport numpy as np # 数值计算库,用于数组操作
import matplotlib.pyplot as plt # 绘图库,用于数据可视化
from sklearn.datasets import load_iris # 数据集模块,用于加载鸢尾花数据集
from sklearn.preprocessing import StandardScaler # 数据标准化模块
from sklearn.decomposition import PCA # 主成分分析模块
加载鸢尾花数据集(Iris Dataset)
# 加载鸢尾花数据集,X为特征数据,y为类别标签,target_names为类别名称
iris = load_iris()
X = iris.data # 特征矩阵 (150x4)
y = iris.target # 类别标签 (0, 1, 2)
target_names = iris.target_names # 类别名称 ('setosa', 'versicolor', 'virginica')
数据标准化
# 通过StandardScaler将数据进行标准化,使每个特征均值为0,方差为1,消除量纲差异
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
原始数据的前两个特征可视化(4维降到2维前的对比)
# 可视化原始数据的前两个特征,以便与PCA降维后的数据进行对比
plt.figure(figsize=(10, 8)) # 增加图形大小
colors = ["navy", "turquoise", "darkorange"]
markers = ['o', 's', 'x'] # 为每个类别设置不同的标记点样式
target_names = ["Setosa", "Versicolour", "Virginica"]
for i, color, marker, label in zip(range(len(target_names)), colors, markers, target_names):
plt.scatter(
X[y == i, 0], X[y == i, 1], # 前两个特征
color=color, alpha=0.7, edgecolor='k', label=label, marker=marker, s=100
)
# 设置标题和坐标轴标签的字体
plt.xlabel("Feature 1 (Sepal length)", fontsize=14, fontweight='bold')
plt.ylabel("Feature 2 (Sepal width)", fontsize=14, fontweight='bold')
plt.title("Original Data: First Two Features", fontsize=16, fontweight='bold')
# 添加网格线和图例
plt.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.7)
plt.legend(fontsize=12, frameon=True, shadow=True, loc="upper right")
# 美化刻度
plt.xticks(fontsxize=12)
plt.yticks(fontsize=12)
# 调整图形边距
plt.tight_layout()
plt.show()
图1
应用PCA将数据降维到2维
# 使用PCA将数据从4维降到2维,以便在2D图中进行可视化
pca = PCA(n_components=2)# 设置降维的目标维度为2
X_pca = pca.fit_transform(X_standardized)# 对标准化数据进行PCA降维
降维后的数据可视化
# 可视化降维后的2维数据,展示PCA在2维空间中重构的主要信息
plt.figure(figsize=(10, 8)) # 调整图形大小
colors = ["navy", "turquoise", "darkorange"] # 定义颜色
markers = ['o', 's', 'x'] # 不同类别的标记点样式
target_names = ["Setosa", "Versicolour", "Virginica"]
# 绘制降维后的数据散点图
for i, color, marker, label in zip(range(len(target_names)), colors, markers, target_names):
plt.scatter(
X_pca[y == i, 0], X_pca[y == i, 1], # 主成分 1 和 2
color=color, alpha=0.7, edgecolor='k', label=label, marker=marker, s=120
)
# 设置标题和轴标签
plt.xlabel("Principal Component 1", fontsize=14, fontweight='bold')
plt.ylabel("Principal Component 2", fontsize=14, fontweight='bold')
plt.title("PCA: Data Projected to 2D", fontsize=16, fontweight='bold')
# 添加网格线和图例
plt.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.7)
plt.legend(fontsize=12, frameon=True, shadow=True, loc="best")
# 优化刻度
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
# 调整图形布局
plt.tight_layout()
plt.show()
图2
方差解释率
pca_full = PCA()
pca_full.fit(X_standardized)
explained_variance_ratio = np.cumsum(pca_full.explained_variance_ratio_) # 累计方差解释率
explained_variance_ratio
图3
使用完整的PCA分析各主成分的方差贡献率
# 绘制主成分数量与累计方差解释率的关系曲线
plt.figure(figsize=(10, 6)) # 调整图形大小
#xplained_variance_ratio 是累积方差解释率
# 绘制曲线
plt.plot(
range(1, len(explained_variance_ratio) + 1), # x轴:主成分数量
explained_variance_ratio, # y轴:累计方差解释率
marker='o', color='royalblue', linestyle='-', linewidth=2, markersize=8, label="Cumulative Variance"
)
# 添加每个点的值标注
for i, value in enumerate(explained_variance_ratio, start=1):
plt.text(i, value + 0.02, f"{value:.2f}", fontsize=10, ha='center', color='black')
# 设置坐标轴标签和标题
plt.xlabel("Number of Principal Components", fontsize=14, fontweight='bold')
plt.ylabel("Cumulative Explained Variance Ratio", fontsize=14, fontweight='bold')
plt.title("Cumulative Explained Variance by Number of Components", fontsize=16, fontweight='bold')
# 设置y轴范围
plt.ylim(0, 1.05)
# 添加网格线
plt.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.7)
# 优化刻度
plt.xticks(range(1, len(explained_variance_ratio) + 1), fontsize=12)
plt.yticks(fontsize=12)
# 添加图例
plt.legend(fontsize=12, loc="lower right")
# 显示图形
plt.tight_layout()
plt.show()
图4
降成三维如图所示
import matplotlib.pyplot as plt
# unused but required import for doing 3d projections with matplotlib < 3.2
import mpl_toolkits.mplot3d # noqa: F401
import numpy as np
from sklearn import datasets, decomposition
np.random.seed(5)
iris = datasets.load_iris()
X = iris.data
y = iris.target
fig = plt.figure(1, figsize=(4, 3))
plt.clf()
ax = fig.add_subplot(111, projection="3d", elev=48, azim=134)
ax.set_position([0, 0, 0.95, 1])
plt.cla()
pca = decomposition.PCA(n_components=3)
pca.fit(X)
X = pca.transform(X)
for name, label in [("Setosa", 0), ("Versicolour", 1), ("Virginica", 2)]:
ax.text3D(
X[y == label, 0].mean(),
X[y == label, 1].mean() + 1.5,
X[y == label, 2].mean(),
name,
horizontalalignment="center",
bbox=dict(alpha=0.5, edgecolor="w", facecolor="w"),
)
# Reorder the labels to have colors matching the cluster results
y = np.choose(y, [1, 2, 0]).astype(float)
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=y, cmap=plt.cm.nipy_spectral, edgecolor="k")
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])
ax.zaxis.set_ticklabels([])
plt.show()
图5
Pca与LAD对比
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
iris = datasets.load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names
pca = PCA(n_components=2)
X_r = pca.fit(X).transform(X)
lda = LinearDiscriminantAnalysis(n_components=2)
X_r2 = lda.fit(X, y).transform(X)
# Percentage of variance explained for each components
print(
"explained variance ratio (first two components): %s"
% str(pca.explained_variance_ratio_)
)
plt.figure()
colors = ["navy", "turquoise", "darkorange"]
lw = 2
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
plt.scatter(
X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=0.8, lw=lw, label=target_name
)
plt.legend(loc="best", shadow=False, scatterpoints=1)
plt.title("PCA of IRIS dataset")
plt.figure()
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
plt.scatter(
X_r2[y == i, 0], X_r2[y == i, 1], alpha=0.8, color=color, label=target_name
)
plt.legend(loc="best", shadow=False, scatterpoints=1)
plt.title("LDA of IRIS dataset")
plt.show()
PCA 降维
- 方法:主成分分析(PCA),是一种无监督学习的降维方法。
- 目标:在保持数据最大方差的基础上,找到新的特征空间,并将数据投影到二维平面上。
- 图内容:
- 三种鸢尾花类别分别以不同颜色绘制(navy、turquoise、darkorange)。
- 每个点代表一个样本,其位置是原始数据通过 PCA 投影后的坐标。
- 特征解释:图中显示了原始数据在前两个主成分上的分布情况,主成分 1 和主成分 2 是捕捉最大方差的两个方向。
- 适用场景:观察数据整体分布、类别间的分离程度和数据的主要变化趋势。
图6
LDA 降维
- 方法:线性判别分析(LDA),是一种监督学习的降维方法。
- 目标:最大化类别间的距离,同时最小化类别内的散度,以增强类别可分性。
- 图内容:
- 同样用三种颜色表示三个类别。
- 每个点的位置是原始数据通过 LDA 映射到二维空间后的坐标。
- 特征解释:图中的两个轴是通过 LDA 计算得到的判别方向。LDA 优化了类别的可分性,因此可以看出不同类别之间的分离程度更明显。
- 适用场景:分类问题的降维与可视化,强调类别间的分隔效果。
图7