主成分分析(PCA):探索数据的核心

news2024/11/28 11:37:00

文章目录

  • 前言
  • 1. 什么是 PCA ?
  • 2. PCA 的原理
    • 2.1 协方差和方差
    • 2.2 核心思想
    • 2.3 步骤
  • 3. PCA 的应用场景
  • 4. PCA 的优缺点
  • 5. 示例:人脸识别
    • 5.1 完整代码
    • 5.2 运行结果
  • 结语


前言

当今社会,数据无处不在。从社交媒体到金融交易,从医疗诊断到市场分析,数据的规模不断增长,这些数据往往具有高维度和复杂性,使得我们难以直观地理解其内在结构。而如何从海量的数据中提取出有用的信息和模式成为了一个巨大的挑战。这就是主成分分析(Principal Component Analysis,PCA)发挥作用的地方,它作为一种强大的降维技术,可以帮助我们发现数据背后的规律和奥秘。



1. 什么是 PCA ?

主成分分析(Principal Component Analysis,PCA)是一种统计学方法,旨在通过线性变换将原始数据转化为一组新的变量,这些新变量称为主成分。每个主成分都是原始数据的线性组合,且彼此之间相互独立。主成分按照方差的大小排列,前几个主成分包含了数据中大部分的信息。

在机器学习和数据科学领域,主成分分析是一种经典且常用的降维技术。通过将原始数据转换为一组新的无关变量,我们可以摒弃其中的噪声和冗余,提取出数据的主要特征。与其他降维技术相比,主成分分析不仅可以降低数据维度,还能保留尽可能多的信息。

2. PCA 的原理

为了理解主成分分析的原理,首先需要了解协方差和方差的概念。协方差描述了两个变量之间的线性关系程度,方差则衡量单个变量的离散程度。主成分分析基于这些概念,通过寻找投影轴使得数据方差最大化,实现降维的目标。

2.1 协方差和方差

协方差描述了两个变量之间的线性关系程度。对于两个变量 x x x y y y ,它们的协方差可以通过以下公式计算:

cov ( x , y ) = 1 n − 1 ∑ i = 1 n ( x i − x ˉ ) ( y i − y ˉ ) \text{cov}(\mathbf{x}, \mathbf{y}) = \frac{1}{n-1} \sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y}) cov(x,y)=n11i=1n(xixˉ)(yiyˉ)

其中, n n n 表示样本的数量, x i x_i xi y i y_i yi 分别表示变量 x x x y y y 的取值, x ˉ \bar{x} xˉ y ˉ \bar{y} yˉ 表示变量 x x x y y y 的均值。协方差的值可以为正、负或零,分别表示正相关、负相关和无关。

方差衡量单个变量的离散程度,可以通过以下公式计算:

Var ( x ) = 1 n − 1 ∑ i = 1 n ( x i − x ˉ ) 2 \text{Var}(\mathbf{x}) = \frac{1}{n-1} \sum_{i=1}^{n} (x_i - \bar{x})^2 Var(x)=n11i=1n(xixˉ)2

其中, x i x_i xi 表示变量 x x x 的取值, x ˉ \bar{x} xˉ 表示变量 x x x 的均值。

2.2 核心思想

PCA 的核心思想是通过线性变换将原始数据投影到一个新的坐标系中,该坐标系的特点是使得投影后的数据在各个维度上的方差最大化。通过选择最大方差的特征向量,我们可以得到一个保留了数据主要信息的低维表示。

2.3 步骤

具体来说,PCA 的步骤如下:

  1. 标准化数据:对原始数据进行均值中心化和标准差归一化,保证每个特征具有零均值和单位方差,以避免不同尺度的特征对主成分分析的影响。

  2. 计算协方差矩阵:根据标准化后的数据计算协方差矩阵,该矩阵描述了各个特征之间的相关性。

  3. 特征值分解:对协方差矩阵进行特征值分解,得到特征值和对应的特征向量。

    特征向量描述了数据在新的坐标系中的方向,而特征值表示了以该特征向量作为基的重要性。

  4. 选择主成分:按照特征值的大小,选择前k个特征向量作为主成分,其中k是我们希望降低后的维度数目。

    在选择主成分时,我们通常会选择特征值较大的特征向量。这是因为特征值越大,说明对应的特征向量所表示的主成分包含的信息越多。通过选择适当数量的主成分,我们可以将数据从原始的高维空间投影到低维的空间中,以实现数据降维的目的。

  5. 投影数据:将标准化后的数据投影到选择的主成分上,得到降维后的数据表示。

3. PCA 的应用场景

PCA 在各个领域都有广泛的应用。以下是一些常见的应用场景:

  • 数据压缩:对于大规模数据集,PCA 可以大幅度减小数据的维度,从而节省存储空间和计算成本。
  • 数据可视化:通过将高维数据投影到二维或三维空间中,我们可以更好地理解数据集的结构和分布。
  • 特征选择和提取:PCA 能够从原始数据中发现潜在的重要特征,帮助我们理解数据背后的信息。通过选取最重要的主成分,PCA 可以减少模型复杂度和数据存储需求,同时仍能保持较高的分类或回归性能。
  • 去除噪声:如果数据包含了噪声或冗余信息,PCA 可以通过去除其中的低方差分量来消除不相关的噪声和冗余数据,以提高数据质量。
  • 图像处理:使用 PCA 可以对图像进行降噪、压缩和特征提取,对于图像识别、人脸识别等任务具有重要意义。
  • 探索性数据分析:PCA 可以帮助发现数据集中存在的模式和结构,从而帮助决策和洞察。
  • 机器学习:通过降低数据的维度,PCA可以减少模型的复杂性,并提高训练速度和模型的泛化能力。

4. PCA 的优缺点

PCA 作为一种降维技术具有以下优点:

  • 可以简化数据集,降低数据维度,减少冗余和噪声,节省存储和计算的开销。
  • 可以帮助我们理解数据之间的关联性、模式和趋势。
  • 能够保持数据之间的最大差异性,提取主要特征,消除不相关的特征,发现数据中的关键信息。
  • 可以用于数据的可视化,方便数据的分析和理解。

然而,PCA 也存在一些限制和不足:

  • 在应用 PCA 之前,数据需要进行标准化处理,使得不同特征具有相同的权重。
  • 依赖于线性假设,可能无法捕捉非线性关系,对于非线性数据可能效果不佳。
  • 不保证可解释性,可能难以直接解释降维后的每个主成分的意义。
  • 对异常值敏感,在面临异常值时可能会对数据中的异常点过度拟合。
  • 降维过程中可能丢失一些信息,使得某些细节无法完全还原。

因此,在应用 PCA 时,需要根据具体问题的需求和数据的特点来进行权衡和选择。

5. 示例:人脸识别

人脸识别是 PCA 应用的一个典型例子。通过将人脸图像转换为主成分,我们可以捕捉到人脸的主要特征,从而实现人脸识别的任务。

以下是 PCA 实现人脸识别的Python代码:

  1. 导入所需的库:
import numpy as np
import os
import cv2
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split

在这里,我们导入了numpy用于数组操作,os用于文件路径操作,cv2用于读取和调整图像,sklearn库中的PCA用于主成分分析,KNeighborsClassifier用于K最近邻分类器,train_test_split用于划分训练集和测试集。

  1. 选择数据集并读取数据:
dataset_folder = 'Face'
selected_dataset = 'ORL_Faces'

X = []  # 存储人脸图像数据
y = []  # 存储对应的标签

images_folder = os.path.join(dataset_folder, selected_dataset)
for root, dirs, files in os.walk(images_folder):
    for file in files:
        if file.endswith('.pgm') or file.endswith('.jpg'):
            img_path = os.path.join(root, file)
            label = os.path.basename(os.path.dirname(img_path))
            face_img = cv2.imread(img_path, 0)
            face_img = cv2.resize(face_img, (100, 100))
            X.append(face_img.flatten())
            y.append(label)

在这里,我们首先指定数据集所在的文件夹(dataset_folder),然后选择一个数据集(selected_dataset)。我们遍历数据集文件夹中的每个人脸图像,读取图像并将其存储在x列表中,同时将对应的标签存储在y列表中。

  1. 将数据转换为numpy数组,并划分训练集和测试集:
X = np.array(X)
y = np.array(y)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

在这一步中,我们将图像数据和标签转换为numpy数组,并使用train_test_split函数将数据集划分为训练集和测试集,其中 20% 的数据作为测试集。

  1. 使用 PCA 降维:
n_components = 100
pca = PCA(n_components=n_components, whiten=True)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)

在这一步中,我们使用 PCA 进行降维。我们选择了 100 个主成分(n_components = 100),并通过fit_transform方法对训练集数据进行降维操作,然后使用transform方法对测试集数据进行降维。

  1. 使用 K最近邻分类器 进行人脸识别:
n_neighbors = 3
knn = KNeighborsClassifier(n_neighbors=n_neighbors)
knn.fit(X_train_pca, y_train)
y_pred = knn.predict(X_test_pca)

在这一步中,我们使用K最近邻分类器进行人脸识别。我们选择了3个邻居(n_neighbors = 3),并使用fit方法对降维后的训练数据进行分类器训练,然后使用predict方法对降维后的测试数据进行预测。

  1. 计算分类准确率:
accuracy = np.mean(y_pred == y_test) * 100
print(f"人脸识别准确率:{accuracy}%")

在这一步中,我们计算出人脸识别的准确率。我们比较预测结果(y_pred) 和 实际标签(y_test),计算预测值等于实际值的比例,并将其乘以 100 得到准确率。

  1. 可视化人脸识别结果:
random_index = np.random.randint(0, len(y_test))
test_img = X_test[random_index].reshape((100, 100))
predicted_label = y_pred[random_index]
true_label = y_test[random_index]

plt.subplot(1, 2, 1)
plt.imshow(test_img, cmap='gray')
plt.title('原始图像')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(test_img, cmap='gray')
plt.title(f'预测: {predicted_label}\n实际: {true_label}')
plt.axis('off')

plt.tight_layout()
plt.show()

在这一步中,我们随机选择一个测试图像进行可视化。我们首先获取原始图像(test_img),然后获取预测标签(predicted_label)和实际标签(true_label)。然后,我们使用subplot函数将原始图像和预测结果以子图的形式显示出来,并用标题显示预测标签。

5.1 完整代码

import numpy as np
import os
import cv2
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
import matplotlib

matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为中文可显示的字体

dataset_folder = 'Face'  # 数据集所在的文件夹
selected_dataset = 'ORL_Faces'  # 选择ORL_Faces数据集

# 读取数据集
# 首先创建一个空的图像列表和对应的标签列表
X = []  # 存储人脸图像数据
y = []  # 存储对应的标签

# 遍历数据集文件夹中的每个人脸图像
images_folder = os.path.join(dataset_folder, selected_dataset)  # 数据集文件夹的路径
for root, dirs, files in os.walk(images_folder):
    for file in files:
        if file.endswith('.pgm') or file.endswith('.jpg'):
            img_path = os.path.join(root, file)
            label = os.path.basename(os.path.dirname(img_path))
            face_img = cv2.imread(img_path, 0)  # 以灰度图像格式读取人脸图像
            face_img = cv2.resize(face_img, (100, 100))  # 将人脸图像调整为统一大小,以便进行PCA
            X.append(face_img.flatten())  # 将人脸图像展平成一维数组并添加到列表中
            y.append(label)  # 添加对应的标签

# 将图像数据和标签转换为numpy数组
X = np.array(X)
y = np.array(y)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 主成分分析(PCA)降维
n_components = 100  # 设置PCA选择的主成分数量
pca = PCA(n_components=n_components, whiten=True)  # 初始化PCA模型
X_train_pca = pca.fit_transform(X_train)  # 对训练数据进行PCA降维
X_test_pca = pca.transform(X_test)  # 对测试数据进行PCA降维

# 使用K最近邻分类器进行人脸识别
n_neighbors = 3  # 设置K最近邻的邻居数量
knn = KNeighborsClassifier(n_neighbors=n_neighbors)  # 初始化K最近邻分类器
knn.fit(X_train_pca, y_train)  # 对降维后的训练数据进行分类器训练
y_pred = knn.predict(X_test_pca)  # 对降维后的测试数据进行分类器预测

# 计算分类准确率
accuracy = np.mean(y_pred == y_test) * 100
print(f"人脸识别准确率:{accuracy}%")

# 可视化人脸识别结果
# 随机选择一个测试样本进行可视化
random_index = np.random.randint(0, len(y_test))  # 随机选择一个索引
test_img = X_test[random_index].reshape((100, 100))  # 获取对应的图像
predicted_label = y_pred[random_index]  # 预测的标签
true_label = y_test[random_index]  # 实际的标签

# 显示原始图像
plt.subplot(1, 2, 1)
plt.imshow(test_img, cmap='gray')
plt.title('原始图像')
plt.axis('off')

# 显示预测结果
plt.subplot(1, 2, 2)
plt.imshow(test_img, cmap='gray')
plt.title(f'预测: {predicted_label}\n实际: {true_label}')
plt.axis('off')

plt.tight_layout()
plt.show()

5.2 运行结果

在这里插入图片描述



结语

在本篇博客中,我们探讨了 PCA 的概念、原理、应用以及其优缺点。PCA 作为一种简化数据和发现隐藏信息的利器,对于数据分析和特征提取具有重要意义。希望读者通过本文的学习,能够深入理解 PCA,并将其应用于实际问题中。然而,在应用 PCA 时,我们需要考虑数据的特点和具体问题的需求选择合适的主成分数量,并对结果进行解释和验证。

希望这篇博客对您有所帮助!如果您对主成分分析有更多的兴趣,建议进一步学习和探索相关的算法和应用。如果您有任何问题或疑惑,欢迎在下方留言讨论。感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1348944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot快速集成多数据源(自动版)

有些人因为看见所以相信,有些人因为相信所以看见 有目录,不迷路 前期准备实现演示参考 最近研究了一下多数据源,这篇博客讲的是简单模式,下篇博客预计写自动切换模式 前期准备 本篇博客基于SpringBoot整合MyBatis-plus&#xff0…

IBM介绍?

IBM,全名国际商业机器公司(International Business Machines Corporation),是一家全球知名的美国科技公司。它成立于1911年,总部位于美国纽约州阿蒙克市(Armonk),是世界上最大的信息…

通过国家网络风险管理方法提供安全的网络环境

印度尼西亚通过讨论网络安全法草案启动了其战略举措。不过,政府和议会尚未就该法案的多项内容达成一致。另一方面,制定战略性、全面的网络安全方法的紧迫性从未像今天这样重要。 其政府官方网站遭受了多起网络攻击,引发了人们对国家网络安全…

PiflowX组件-JDBCWrite

JDBCWrite组件 组件说明 使用JDBC驱动向任意类型的关系型数据库写入数据。 计算引擎 flink 有界性 Sink: Batch Sink: Streaming Append & Upsert Mode 组件分组 Jdbc 端口 Inport:默认端口 outport:默认端口 组件属性 名称展示名称默…

ES应用_ES原理

1 ES简介 Elasticsearch:基于Apache Lucene并使用Java开发的分布式开源搜索和分析引擎。是 Elastic Stack 的核心,它集中存储您的数据。 Elastic Stack:包括 Elasticsearch、Logstash 、 Kibana 和Beats (也称为 ELK Stack&…

简写英语单词

题目: 思路: 这段代码的主要思路是读取一个字符串,然后将其中每个单词的首字母大写输出。具体来说,程序首先使用 fgets 函数读取一个字符串,然后遍历该字符串中的每个字符。当程序遇到一个字母时,如果此时…

Git使用教程 gittutorial

该教程对该文章的翻译:https://git-scm.com/docs/gittutorial 本文介绍怎用使用 Git 导入新的工程、修改文件及如何其他人同步开发。 首先, 可以使用以下指令获取文档帮助 git help log笔者注:不建议看这个文档,标准的语法介绍…

Yapi接口管理平台Centos7容器部署

文章目录 0.Docker部署1.Docker部署1.1 MongoDB1.2 下载 Yapi 镜像1.3 初始化数据库1.4 启动 Yapi 服务1.5 访问 Yapi 2.docker-compose部署2.1 创建容器网络2.2 创建2.3 创建 mongodb-compose2.4 创建 yapi-compose2.5 启动容器2.6 访问 Yapi 0.Docker部署 参考:C…

modelsim安装使用

目录 modelsim 简介 modelsim 简介 ModelSim 是三大仿真器公司之一mentor的产品,他可以模拟行为、RTL 和门级代码 - 通过独立于平台的编译提高设计质量和调试效率。单内核模拟器技术可在一种设计中透明地混合 VHDL 和 Verilog,常用在fpga 的仿真中。 #…

回溯法解决工作分派问题

解决这个问题的关键有两个: 1.t数组用来在回溯过程暂时存储工作分配关系 2.ans数组用来保存最终答案 3."恢复现场"操作 4.一维数组st,表示该工作是否已经被选 5.solve第k层递归表示第k个人,for循环罗列的是工作.这样,比k表示工作,for循环枚举人更加符合我们的直…

常见位运算模板方法总结(包含五道例题)

哈喽大家好&#xff0c;今天博主给大家带来算法基础常见位运算的模板&#xff0c;可以说大家遇到的百分之九十与位运算有关的题都可以用得上。话不多上我们上干货&#xff1a; 一.基础位运算符 << 左移运算符 >> 右移运算符 ~ 取反 & 与运算 | …

23种设计模式Python版

目录 创建型模式简单工厂模式工厂方法模式抽象工厂模式单例模式原型模式建造者模式 结构型模式适配器模式桥接模式组合模式装饰器模式外观模式享元模式代理模式 行为型模式职责链模式命令模式解释器模式迭代器模式中介者模式备忘录模式观察者模式状态模式策略模式模板方法模式访…

CUMT--Java复习--核心类

目录 一、装箱与拆箱 二、“”与equals 三、字符串类 1、String、StringBuffer、StringBuilder的区别 2、String类 3、StringBuffer类 4、StringBuilder类 四、类与类之间关系 一、装箱与拆箱 基本类型与对应封装类之间能够自动进行转换&#xff0c;本质就是Java的自…

【力扣题解】P105-从前序与中序遍历序列构造二叉树-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P105-从前序与中序遍历序列构造二叉树-Java题解&#x1f30f;题目描述&#x1f4a1;题…

论文速递|Management Science 11月文章合集(下)

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 编者按 在本系列文章中&#xff0c;我们梳理了运筹学顶刊Management Science11月份发布的47篇文章的基本信息&#xff0c;旨在帮助读者快速洞察行业最新动态。本文为第三部分。 文章1 ● 题目&#xff1a;…

Linux:apache优化(7)—— 访问控制

作用&#xff1a;为apache服务提供的页面设置客户端访问权限&#xff0c;为某个组或者某个用户加密访问&#xff1b; /usr/local/httpd/bin/htpasswd -c /usr/local/httpd/conf/htpasswd tarro1 #添加admin用户&#xff0c;可以在两个路径中间添加-c是新建文件删除原文件&#…

当你的电脑在安装Windows更新后出现问题时怎么办,这里提供办法

Windows更新通常会为你的电脑带来错误修复、安全补丁和新功能,但它们也可能会带来性能下降甚至引发恐慌的数据丢失等问题,从而适得其反。如果你在安装更新后发现了一些奇怪之处,你可以将其回滚,尝试重新启动。 Windows更新主要有两种:质量更新和功能更新。高质量的更新包…

16.综合项目实战

一、基础演练&#xff1a; 1、建库、建表 # 创建数据库 create database mysql_exampleTest; use mysql_exampleTest; # 学生表 CREATE TABLE Student( s_id VARCHAR(20), s_name VARCHAR(20) NOT NULL DEFAULT , s_birth VARCHAR(20) NOT NULL DEFAULT , s_sex VARC…

RocketMQ(Linux版本5.1.4)

1、停止之前的运行服务 [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# sh bin/mqshutdown namesrv No mqnamesrv running. [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-r…

【编译原理】期末预习做题向I

新的一年希望可以成为更好的人嘿嘿&#xff01; 这一篇基本就是把 up 讲的题都截了一遍然后加了点自己的笔记啥的 O.o &#xff08;不妥的话会删掉的 qwq&#xff0c;希望没事嘿嘿&#xff09; 来源&#xff1a;混子速成 I. 绪论 记住组成部分 II. 前后无关文法和语言 1.…