当前位置: 首页 > news >正文

【机器学习】PCA主成成分分析

文章目录

    • 一、算法介绍
  • 1.算法概述
  • 2.关键名词
  • 3.PCA的计算过程
  • 4.PCA的优缺点
    • 二、实验
  • 1.代码介绍
  • 2.实验结果
  • 3.实验小结

一、算法介绍

1.算法概述

主成分分析(PCA)作为一种常用的数据降维技术,其主要目的是通过线性变换,将原始数据投影到一个新的坐标系中,使得数据在新坐标系中的方差尽可能大,从而减少数据的维度。即找到数据中方差最大的方向,将数据映射到这个方向上,形成第一个主成分。然后,在与第一个主成分正交的方向上找到第二大方差的方向,形成第二个主成分,依此类推。通过选择最大方差的前几个主成分,就可以实现对数据维度的降低。
进行降维时,我们希望损失尽可能小,即我们希望降维的标准为:样本点到这个超平面的距离足够近,或者说样本点在这个超平面上的投影能尽可能的分开。

2.关键名词

维度:就是数据的“特征数量”。比如,房子的面积、房间数是 2 个维度,加个价格就变成 3 维。 降维:把维度变少。比如,原来有 10个特征,降维后只剩 2 个。
主成分:PCA 找到的“新坐标轴”。这些新坐标轴是原来特征的某种组合,能抓住数据里最大的变化。比如:如果数据是一堆散乱的点,主成分就像是你找到的最粗的那根“趋势线”,能概括大部分点的走向。
方差:数据的“散乱程度”。方差越大,说明数据点越分散,越能体现差异。 比如:如果所有学生的数学成绩都是 80 分,方差就很小;如果有人100 分,有人 20 分,方差就很大。

3.PCA的计算过程

去除平均值

  1. 计算协方差矩阵
  2. 计算协方差矩阵的特征值和特征向量
  3. 将特征值排序
  4. 保留前N个最大的特征值对应的特征向量
  5. 将原始特征转换到上面得到的N个特征向量构建的新空间中(最后两步,实现了特征压缩)

4.PCA的优缺点

优点

  1. 降低数据维度:PCA能够有效减少数据集的特征数量,从而简化数据分析的复杂度和提高数据处理的效率。

  2. 保留主要信息:通过提取最大的几个主成分,PCA能够在保留大部分重要信息的前提下实现数据降维。

  3. 计算过程简单:PCA的计算主要涉及协方差矩阵的特征值分解,这一过程数学上成熟且易于实施。

  4. 无监督特性:作为一种无监督学习算法,PCA的应用不需要数据的标签信息,只依赖于数据本身的结构特征。

  5. 消除相关性:PCA生成的主成分之间相互正交,这有助于消除原始数据特征间的相互影响和多重共线性问题。

缺点

  1. 解释性差:PCA产生的主成分是原变量的线性组合,这种组合可能难以直观地解释或关联到具体物理意义。

  2. 可能损失信息:由于PCA基于方差大小选择主成分,可能会忽视方差小但实际重要的特征。

  3. 对异常值敏感:PCA在计算过程中对异常值非常敏感,异常值的存在可能会对结果产生较大影响。

  4. 线性假设限制:PCA假设数据间的关系是线性的,对于存在非线性关系的数据,PCA可能无法有效地提取特征。

  5. 主观性强:确定保留主成分的数量时通常需要依据累计贡献率或其他准则,这一过程带有一定的主观性。

  6. 对数据规模要求:PCA需要足够的数据量来准确计算协方差矩阵,小规模数据可能不适用于PCA分析。

二、实验

1.代码介绍

import os
import numpy as np
from PIL import Image
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt

功能:导入处理文件路径、数值计算、图像处理、机器学习和可视化所需的库。

def load_orl_faces(data_path='ORL_Faces'):"""加载ORL人脸数据集,添加详细的错误检查和日志输出"""# 初始化存储图像和标签的列表images = []labels = []label_id = 0# 检查数据集目录是否存在if not os.path.exists(data_path):raise FileNotFoundError(f"数据集目录不存在: {data_path}")# 遍历所有子目录(每个人)person_dirs = [d for d in os.listdir(data_path) if os.path.isdir(os.path.join(data_path, d))]if not person_dirs:raise ValueError(f"数据集目录 {data_path} 不包含任何子目录")# 处理每个人的图像for person_dir in sorted(person_dirs):person_path = os.path.join(data_path, person_dir)img_files = []# 查找所有图像文件for img_name in sorted(os.listdir(person_path)):if img_name.lower().endswith(('.pgm', '.png', '.jpg', '.jpeg')):img_files.append(img_name)# 处理每个图像for img_name in img_files:img_path = os.path.join(person_path, img_name)try:# 读取并转换为灰度图,调整为标准尺寸(92x112)img = Image.open(img_path).convert('L')img = img.resize((92, 112))# 转换为一维数组并存储img_array = np.array(img).flatten()images.append(img_array)labels.append(label_id)except Exception as e:print(f"无法加载图像 {img_path}: {e}")label_id += 1  # 每个人的标签递增# 验证加载结果if not images:raise ValueError("未成功加载任何图像,请检查数据集格式和路径")return np.array(images), np.array(labels)

从指定路径加载 ORL 人脸数据集(40 人,每人 10 张图)。
支持多种图像格式(PGM、PNG、JPG)。
图像预处理:转为灰度图、调整尺寸、展平为一维向量。
错误处理:检查目录存在性、文件格式、加载失败的图像。

def visualize_pca_reconstruction(original, reconstructed, n_samples=5):"""可视化PCA重构效果"""fig, axes = plt.subplots(2, n_samples, figsize=(15, 5))for i in range(n_samples):h, w = 112, 92# 显示原始人脸axes[0, i].imshow(original[i].reshape(h, w), cmap='gray')axes[0, i].set_title(f'原始人脸 {i+1}')axes[0, i].axis('off')# 显示PCA重构后的人脸axes[1, i].imshow(reconstructed[i].reshape(h, w), cmap='gray')axes[1, i].set_title(f'PCA重构 {i+1}')axes[1, i].axis('off')plt.tight_layout()plt.show()

功能:对比显示原始人脸图像和 PCA 降维后重构的图像,直观评估信息保留程度。

def visualize_eigenfaces(pca, n_components=16):"""可视化特征脸"""fig, axes = plt.subplots(4, 4, figsize=(10, 10))for i, ax in enumerate(axes.flat):if i < n_components:# PCA的每个主成分对应一个"特征脸"eigenface = pca.components_[i].reshape(112, 92)ax.imshow(eigenface, cmap='gray')ax.set_title(f'特征脸 {i+1}')ax.axis('off')plt.tight_layout()plt.show()

功能:将 PCA 计算得到的主成分(特征向量)还原为图像,展示最能代表数据集差异的 “特征脸”。

def main():try:# 加载数据(可自定义路径)data_path = input("请输入数据集路径(默认: ORL_Faces): ") or 'ORL_Faces'X, y = load_orl_faces(data_path)print(f"数据集形状: {X.shape}")# 划分训练集和测试集if len(X) < 2:raise ValueError("样本数量太少,无法进行训练和测试划分")X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)# PCA降维(保留最主要的150个特征)n_components = min(150, len(X_train)-1)print(f"使用 {n_components} 个主成分进行PCA降维")pca = PCA(n_components=n_components, whiten=True).fit(X_train)# 数据转换到PCA空间X_train_pca = pca.transform(X_train)X_test_pca = pca.transform(X_test)# 可视化特征脸和重构效果visualize_eigenfaces(pca)X_train_reconstructed = pca.inverse_transform(X_train_pca)visualize_pca_reconstruction(X_train, X_train_reconstructed)# 训练KNN分类器(基于降维后的特征)knn = KNeighborsClassifier(n_neighbors=5)knn.fit(X_train_pca, y_train)# 评估模型y_pred = knn.predict(X_test_pca)accuracy = accuracy_score(y_test, y_pred)print(f"人脸识别准确率: {accuracy:.2%}")# 可视化预测结果fig, axes = plt.subplots(2, 5, figsize=(15, 6))for i, ax in enumerate(axes.flat):if i < len(X_test):img = X_test[i].reshape(112, 92)ax.imshow(img, cmap='gray')ax.set_title(f'预测: {y_pred[i]}\n真实: {y_test[i]}')ax.axis('off')plt.tight_layout()plt.show()except Exception as e:print(f"程序运行出错: {e}")

数据加载与预处理:读取图像数据,划分训练集 / 测试集。
特征提取:使用 PCA 降维,将原始图像(10304 维)压缩到 150 维。
模型训练:使用 K 近邻算法训练分类器。
评估与可视化:计算准确率,展示特征脸、重构效果和预测结果。
异常处理:捕获并打印运行时错误。

2.实验结果

在这里插入图片描述
特征脸
这些是 PCA 计算出的主成分,每张图对应一个 “特征向量”,代表数据集中人脸差异的主要模式。
PCA 将高维人脸图像(如 92×112=10304 维)压缩到低维空间,特征脸是压缩的 “基” 。用少量特征脸就能重建人脸,实现降维与去噪。
在这里插入图片描述
上排是原始人脸,下排是用 PCA 降维后重构的人脸(用少量特征脸恢复图像)。
重构图保留了人脸主要特征(五官、轮廓),但丢失细节(如纹理、表情细微差异)。说明 PCA 能在降维时保留 “人脸身份” 的关键信息,同时舍弃冗余噪声。
在这里插入图片描述
每张图显示 模型预测标签( predict ) 和 真实标签( real ),验证 KNN 分类器在 PCA 降维后的效果。
多数结果(如 predict:1 real:1 )预测正确,说明PCA 提取的特征有效,KNN 能准确匹配身份。
少数错误(如 predict:23 real:32 )可能原因:训练样本不足(每人仅 10 张图),表情 / 姿态差异大,PCA 未完全区分,KNN 对高维空间距离敏感(降维后仍有重叠)

3.实验小结

本次基于 PCA 的人脸识别实验,利用 ORL_Faces 数据集展开。通过 PCA 提取特征脸,实现人脸图像降维,保留关键身份信息。从结果看,特征脸清晰呈现人脸差异模式,降维后重构图像保留主要面部特征,验证了 PCA 在压缩数据、去噪的有效性 。KNN 分类器在降维特征上多数预测正确,体现 “PCA + KNN” 方案的简洁实用,但少数错误也暴露局限,如样本量少、表情姿态干扰致特征区分度不足。
整体而言,实验验证了 PCA 提取特征、降维的价值,传统方法在简单场景有可用性,也明晰后续可通过增样本、换 LDA 降维或替换 SVM、CNN 分类器,提升复杂场景下识别性能,为深入探究人脸识别算法提供实践参考 。

相关文章:

  • 19-Oracle 23 ai Database Sharding-知识准备
  • 人工智能学习08-类与对象
  • 常见 DOM 事件全解析
  • JVM 类加载器 详解
  • FreeRTOS同步和互斥
  • JAVA 对象 详解
  • 【2025CVPR】模型融合新范式:PLeaS算法详解(基于排列与最小二乘的模型合并技术)
  • ES6 核心语法手册
  • SQL导出Excel支持正则脱敏
  • AD规则设置-铜皮规则,阻焊规则,实时DRC
  • AI时代:学习永不嫌晚,语言多元共存
  • LambdaqueryWrapper的介绍与使用
  • 第十二讲 | 二叉搜索树
  • JavaScript 语法结构
  • Android 大文件分块上传实战:突破表单数据限制的完整方案
  • 用 AI 开发 AI:原汤化原食的 MCP 桌面客户端
  • 【评测】Qwen3-Embedding模型初体验
  • MSYS2 环境配置与 Python 项目依赖管理笔记
  • android计算器代码
  • typeof运算符 +unll和undefined的区别
  • 免费建网站那个好/东莞网络营销信息推荐
  • 如何进入网站后台管理系统/软文推广代理平台
  • 襄阳的网站建设公司/扫一扫识别图片
  • 手机微信网站开发/南京网站seo
  • 做网站怎么收费/seo学院
  • 香港服务器可以访问国外网站吗/广州推广引流公司