24/11/7 算法笔记 PCA主成分分析

news2024/11/28 0:41:32

假如我们的数据集是n维的,共有m个数据(x^{(1)},x^{(2)},...,x^{(m)})。我们希望将这m个数据的维度从n维降到k维,希望这m个k维的数据集尽可能的代表原始数据集。我们知道数据从n维降到k维肯定会有损失,但是我们希望损失尽可能的小。那么如何让这k维的数据尽可能表示原来的数据呢?

        我们先看看最简单的情况,也就是n=2,K=1,也就是将数据从二维降维到一维。数据如下图。我们希望找到某一个维度方向,它可以代表这两个维度的数据。图中列了两个向量方向,u1和u2,那么哪个向量可以更好的代表原始数据集呢?从直观上也可以看出,u1比u2好。

可以有两种解释,第一种解释是样本点到这个直线的距离足够近,第二种解释是样本点在这个直线上的投影能尽可能的分开。

        假如我们把K从1维推广到任意维,我们希望降维的标准为:样本点到这个超平面的距离足够近,或者说样本点在这个超平面上的投影能尽可能的分开。

PCA(主成分分析)是一种统计技术,它通过正交变换将一组可能相关的变量转换为一组线性不相关的变量,称为主成分。这些主成分按照方差的大小排序,第一个主成分具有最大的方差,第二个主成分具有第二大的方差,依此类推。以下是PCA的工作原理和关键步骤:

1. 标准化数据

由于PCA对数据的尺度敏感,因此在进行PCA之前,通常需要对数据进行标准化处理,使得每个特征的均值为0,标准差为1。这一步是必要的,因为PCA依赖于协方差矩阵,而协方差矩阵会因特征的尺度差异而产生偏差。

2. 计算协方差矩阵

在数据标准化之后,计算数据的协方差矩阵。协方差矩阵是一个方阵,其元素表示不同特征之间的协方差。对于数据集 XX(假设已经中心化),协方差矩阵 ΣΣ 定义为:

其中 n 是样本数量。

3. 计算协方差矩阵的特征值和特征向量

协方差矩阵的特征值和特征向量可以提供关于数据结构的重要信息。特征值表示每个特征的方向上的数据方差量,而特征向量表示这些特征的方向。

4. 选择主成分

根据特征值的大小,选择最大的 k 个特征值对应的特征向量。这些特征向量代表了数据中最重要的 k 个主成分。特征值的大小表示了每个主成分的重要性或方差贡献。

5. 构造新的特征空间

使用选定的特征向量作为新特征空间的基,将原始数据投影到这个新的特征空间上。这个过程实际上是将原始数据集转换为一个新的数据集,其中每个数据点由 k 个主成分的线性组合表示。

6. 解释结果

新数据集中的每个维度(即每个主成分)都代表了原始数据集中的某种结构或模式。通常,第一个主成分捕获了数据中最大的方差,第二个主成分捕获了第二大的方差,且与第一个主成分正交。

PCA的应用

  • 降维:通过减少数据的维度来简化数据集,同时保留最重要的信息。
  • 数据可视化:将高维数据投影到二维或三维空间,以便可视化。
  • 去噪:通过去除小的特征值对应的成分来减少数据中的噪声。
  • 特征提取:在机器学习中,PCA可以作为预处理步骤,提取更有意义的特征。

下面是他的代码:

import numpy as np
from scipy.linalg import svd

class PCA:
    def __init__(self, n_components=None, whiten=False, copy=True):
        self.n_components = n_components
        self.whiten = whiten
        self.copy = copy

    def fit(self, X, y=None):
        X = np.asarray(X)
        if X.ndim == 1:
            X = X[:, np.newaxis]
        
        # Center the data
        self.mean_ = np.mean(X, axis=0)
        X = X - self.mean_

        # Perform SVD
        U, S, V = svd(X, full_matrices=False)
        if self.n_components is None:
            self.n_components_ = V.shape[1]
        else:
            self.n_components_ = min(self.n_components, V.shape[1])

        # Store the components
        self.components_ = V[:self.n_components_]

        # Store the explained variance
        self.explained_variance_ = S[:self.n_components_]**2 / X.shape[0]
        
        return self

    def transform(self, X):
        check_is_fitted(self)
        X = np.asarray(X)
        if X.shape[1] != self.mean_.shape[0]:
            raise ValueError("Shape of X is different from the shape used to fit the model")
        
        X = X - self.mean_
        return np.dot(X, self.components_.T)

    def fit_transform(self, X, y=None, **kwargs):
        self.fit(X)
        return self.transform(X)

    def inverse_transform(self, X):
        check_is_fitted(self)
        X = np.asarray(X)
        return np.dot(X, self.components_) + self.mean_

    def score_samples(self, X):
        X = self.transform(X)
        return np.sum(X**2, axis=1)

    def score(self, X, y=None):
        # This method is not implemented in this simplified version
        pass

# Helper function to check if the model is fitted
def check_is_fitted(model):
    if not hasattr(model, 'components_'):
        raise ValueError("Model is not fitted")


# Example usage
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
pca = PCA(n_components=2)
X_r = pca.fit_transform(X)
print(X_r.shape)  # Output: (150, 2)

1. 导入依赖

import numpy as np
from scipy.linalg import svd

svd用于执行奇异值分解,我有讲过。

2. PCA 类定义

class PCA:
    def __init__(self, n_components=None, whiten=False, copy=True):
        self.n_components = n_components
        self.whiten = whiten
        self.copy = copy

这是 PCA 类的构造函数,它初始化了几个重要的属性:

  • n_components:要保留的主成分数量。如果设置为 None,则保留所有成分。
  • whiten:是否进行白化处理,即是否将主成分的方差缩放到1。
  • copy:是否在处理数据时复制数据,以避免修改原始数据。

3. 拟合方法

def fit(self, X, y=None):
    X = np.asarray(X)
    if X.ndim == 1:
        X = X[:, np.newaxis]
        
    # Center the data
    self.mean_ = np.mean(X, axis=0)
    X = X - self.mean_

    # Perform SVD
    U, S, V = svd(X, full_matrices=False)
    if self.n_components is None:
        self.n_components_ = V.shape[1]
    else:
        self.n_components_ = min(self.n_components, V.shape[1])

    # Store the components
    self.components_ = V[:self.n_components_]

    # Store the explained variance
    self.explained_variance_ = S[:self.n_components_]**2 / X.shape[0]
        
    return self

fit 方法用于计算数据的PCA变换:

  • 首先,将数据转换为 numpy 数组,并确保数据是二维的。
  • 计算数据的均值,并中心化数据(减去均值)。
  • 执行SVD,得到 US 和 V 三个矩阵。
  • SVD可以看之前的文章24/11/6 算法笔记 SVD-CSDN博客
  • 根据 n_components 的设置,确定保留的主成分数量。
  • 保存主成分(V 矩阵的列)和解释的方差。

主成分有什么用:

  • PCA可以减少数据的维度,同时保留最重要的特征。这有助于去除噪声和冗余信息,使得数据集更易于管理和分析。

4. 转换方法

def transform(self, X):
    check_is_fitted(self)
    X = np.asarray(X)
    if X.shape[1] != self.mean_.shape[0]:
        raise ValueError("Shape of X is different from the shape used to fit the model")
        
    X = X - self.mean_
    return np.dot(X, self.components_.T)

transform 方法用于将新数据投影到主成分上:

  • 确保模型已经被拟合。
  • 将输入数据转换为 numpy 数组,并检查数据的形状是否与拟合时的数据一致。
  • 中心化数据。
  • 将数据与主成分的转置矩阵相乘,得到降维后的数据。

5. 拟合和转换方法

def fit_transform(self, X, y=None, **kwargs):
    self.fit(X)
    return self.transform(X)

fit_transform 方法结合了 fittransform 方法,先拟合模型,然后将数据投影到主成分上。

6. 逆变换方法

def inverse_transform(self, X):
    check_is_fitted(self)
    X = np.asarray(X)
    return np.dot(X, self.components_) + self.mean_

7.样本得分函数

def score_samples(self, X):
    X = self.transform(X)
    return np.sum(X**2, axis=1)

8.辅助函数

def check_is_fitted(model):
    if not hasattr(model, 'components_'):
        raise ValueError("Model is not fitted")

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

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

相关文章

wxWidgets布局管理及XRC界面使用解惑

wxWidgets布局,通常就是wxBoxSizer,当然还有别的Sizer,就像Qt中的Layout一样,各种布局管理类。只是如今的wxWidgets尚未发展起来,一般其他的你用的比较少,因为这个最简单,最容易布局&#xff0c…

【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)

博主说明:本文项目编号 T 062 ,文末自助获取源码 \color{red}{T062,文末自助获取源码} T062,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

【循环引用及格式化输出】

垃圾回收机制 当一个值在内存中直接引用跟间接引用的量为0时,(即这个值没有任何入口可以找到它)那么这个值就会被清空回收♻️,释放内存空间; 列表在内存中的存储方式 1)引用计数的两种方式 x "ea…

31.7K+ Star!AgentGPT:一个在浏览器中运行的Agent

AgentGPT 简介 AgentGPT[1] 是一个可以让你在浏览器中组装、配置和部署自主AI代理的项目。你可以为你的自定义AI命名,并让它去实现任何你想象中目标。它将尝试通过思考要执行的任务、执行它们并从结果中学习来达成目标。 项目特点 主要特点 自主AI代理:用户可以自定义AI并赋…

【大模型】通过Crew AI 公司的崛起之路学习 AI Agents 的用法

AI 技术的迅猛发展正以前所未有的速度重塑商业格局,而 AI Agents,作为新一代的智能自动化工具,正逐步成为创新型公司的核心力量。在本文中,我们将探讨如何利用 AI Agents 构建一家 AI 驱动的公司,并详细了解 Crew AI 创…

【Uniapp】Uniapp Android原生插件开发指北

前言 在uniapp开发中当HBuilderX中提供的能力无法满足App功能需求,需要通过使用Andorid/iOS原生开发实现时,或者是第三方公司提供的是Android的库,这时候可使用App离线SDK开发原生插件来扩展原生能力。 插件类型有两种,Module模…

网页版五子棋——用户模块(服务器开发)

前一篇文章:网页版五子棋—— WebSocket 协议-CSDN博客 目录 前言 一、编写数据库代码 1.数据库设计 2.配置 MyBatis 3.创建实体类 4.创建 UserMapper 二、前后端交互接口 1.登录接口 2.注册接口 3.获取用户信息 三、服务器开发 1.代码编写 2.测试后端…

Jenkins声明式Pipeline流水线语法示例

系列文章目录 docker搭建Jenkins2.346.3版本及常用工具集成配置(ldap、maven、ansible、npm等) docker安装低版本的jenkins-2.346.3,在线安装对应版本插件失败的解决方法 文章目录 系列文章目录jenkins流水线基础1、pipeline1.1、什么是pipeline?1.2、为什么使用pi…

【NLP】使用 SpaCy、ollama 创建用于命名实体识别的合成数据集

命名实体识别 (NER) 是自然语言处理 (NLP) 中的一项重要任务,用于自动识别和分类文本中的实体,例如人物、位置、组织等。尽管它很重要,但手动注释大型数据集以进行 NER 既耗时又费钱。受本文 ( https://huggingface.co/blog/synthetic-data-s…

【数据集】【YOLO】【目标检测】道路裂缝数据集 5466 张,YOLO/VOC格式标注!

数据集介绍 【数据集】道路裂缝数据集 5466 张,目标检测,包含YOLO/VOC格式标注。数据集中包含一种分类,检测范围城市道路裂缝、高速道路裂缝、乡村道路裂缝。 戳我头像获取数据,或者主页私聊博主哈~ 一、数据概述 道路裂缝检测…

C++用string实现字符串相加

. - 力扣(LeetCode) -》》》》》题目链接 实现思路:计算数字符串长度并用数组的方式计算出字符位置,用字符的ask码‘0’计算出字符本身。 class Solution { public:string addStrings(string num1, string num2) {string str;int…

easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头

easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头 原版表头和表体字体美化自动拼接错误提示列自适应宽度自动合并单元格使用Easyexcel使用poi导出 在后台管理开发的工作中,离不开的就是导出excel了. 如果是简单的导出, 直接easyexce…

brainpy 动力学编程基础

文章参考: 《神经计算建模实战——基于brainpy》 吴思 【brainpy学习笔记】基础知识2(动力学模型的编程基础)-CSDN博客 Brainpy手册 文章目录 积分器:定义ODE函数数值积分方法 更新函数和动力系统计算介绍什么是brainpy.DynamicalSystem?如…

高级图像处理工具

图像处理-高级 1、功能概览 随着社交媒体的普及和个人创作需求的增长,图像处理成为了日常生活中不可或缺的一部分。无论是专业的设计师还是爱好者,都需要一款强大的工具来帮助他们完成各种任务。今天,我们将介绍一款基于Python开发的高级图…

【Zookeeper集群搭建】安装zookeeper、zookeeper集群配置、zookeeper启动与关闭、zookeeper的shell命令操作

目录 一、安装Zookeeper 二、配置Zookeeper集群 三、Zookeeper服务的启动与关闭 四、Zookeeper的shell操作 前情提要:延续上篇【Hadoop和Hbase集群配置】继续配置Zookeeper,开启三台虚拟机Hadoop1、Hadoop2、Hadoop3,进入终端&#xff0c…

Transformer和BERT的区别

Transformer和BERT的区别比较表: 两者的位置编码: 为什么要对位置进行编码? Attention提取特征的时候,可以获取全局每个词对之间的关系,但是并没有显式保留时序信息,或者说位置信息。就算打乱序列中token…

Python爬虫如何处理验证码与登录

Python爬虫如何处理验证码与登录 Python 爬虫在抓取需要登录的网站数据时,通常会遇到两个主要问题:登录验证和验证码处理。这些机制是网站用来防止自动化程序过度抓取数据的主要手段。本文将详细讲解如何使用 Python 处理登录与验证码,以便进…

《深入浅出Apache Spark》系列②:Spark SQL原理精髓全解析

导读:SQL 诞生于 20 世纪 70 年代,至今已有半个世纪。SQL 语言具有语法简单,低学习门槛等特点,诞生之后迅速普及与流行开来。由于 SQL 具有易学易用的特点,使得开发人员容易掌握,企业若能在其计算机软件中支…

JS实现,防抖节流 + 闭包

防抖(Debounce) 防抖是指短时间内大量触发同一事件,只会在最后一次事件完成后延迟执行一次函数。 防抖的典型应用场景是输入框的搜索建议功能,用户输入时不需要每次输入都去查询,而是在用户停止输入一段时间后才进行…

安卓编程最方便的读写资料类SharedPreferences,多个APP共享

本文介绍Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用ContentProvider存储数据 5 网络存储数据 下面详细讲解这五种方式的特点 第一种: 使用SharedPreferences存储数据 …