PCA主成分分析

news2025/1/18 5:12:40

PCA降维算法

目前图像特征的提取主要有两种方法:传统图像特征提取方法 和 深度学习方法。

  1. 传统的特征提取方法:基于图像本身的特征进行提取(PCA);
  2. 深度学习方法:基于样本自动训练出区分图像的特征分类器;

特征选择(feature selection)和特征提取(Feature extraction)都属于降维(Dimension reduction)

特征提取:

特征提取的主要方法:主要目的是为了排除信息量小的特征,减少计算量等:

主成分分析(PCA)

PCA主成分分析是传统特征提取方法当中最常用的算法,没有之一,传统的特征提取方法没有深度学习那么严谨,智能,准确度也没那么高,但它在做法上没有深度学习那么复杂,因为深度学习还需要训练参数等等,比较耗时。很多情况下并不需要用到深度学习的知识,简单点说,就是杀鸡焉用牛刀。很多人知道PCA是用来降维的,但是却不了解PCA算法的原理,于是深入了解PCA算法原理就成了一个分水岭。基于此,本文主要介绍PCA算法的原理。

PCA算法是如何实现的

简单来说,就是将数据从原始的空间中转换到新的特征空间中,例如原始的空间是三维的(x,y,z),x、y、z分别是原始空间的三个基,我们可以通过某种方法,用新的坐标系(a,b,c)来表示原始的数据,那么a、b、c就是新的基,它们组成新的特征空间。在新的特征空间中,可能所有的数据在c上的投影都接近于0,即可以忽略,那么我们就可以直接用(a,b)来表示数据,这样数据就从三维的(x,y,z)降到了二维的(a,b)。

问题的关键在于如何求新的基(a,b,c)?

步骤:

  1. 对原始数据零均值化(中心化),
  2. 求协方差矩阵,
  3. 对协方差矩阵求特征向量和特征值,这些特征向量组成了新的特征空间。

1. PCA——零均值化(中心化):

把所有的变量都去减掉他们的均值,使得减完之后得到的数据集均值为0,其实本质就是一个平移的过程,平移后得到的所有数据的中心是(0,0)
在这里插入图片描述

公式推导
设均值为E
(1/n) * (x1 + x2 + … +xn) = E
所有的变量都减去均值
(1/n) * (x1 - E + x2 - E + … + xn - E)
= (1/n) * ((x1 + x2 + … +xn) -nE)
= (1/n) * (x1 + x2 + … +xn) - E
= 0

只有“中心化”数据之后,计算得到的方向才能比较好的“概括”原来的数据。
下图描述了“中心化”的几何意义,即将样本集的中心平移到坐标系的原点0上
在这里插入图片描述

对于上左图,蓝色的圈代表数据域,凭肉眼观察,按理来说数据的发展方向是从左上到右下,正好是跟它现在的均值是垂直的。而我们一般而言一组数据的均值是能够代表这组数据的趋势的,但显然现在的均值并不能代表该数据的发展趋势。所以当我们做了零均值化过后,就和我们的预期达到一致了。所以我们做零均值化的原因就在于优化,使得我们在计算的时候更加准确,如果不做这一步,有可能会导致误差变大。

2. PCA——PCA降维的几何意义

对于一组数据,如果它在某一坐标轴上的方差越大,说明坐标点越分散,该属性就能够比较好地反映源数据。

这里举个例子便于理解,假设现在有3个人的人脸特征,他们的特征都有三个维度(眼睛,鼻子,嘴巴),假设对于鼻子这一维度的数据3个人都是一样的,都是大鼻子,那么这个时候鼻子这个维度的方差就为0,这个维度的离散程度就很小。那么如果我们要做分类任务,我们从鼻子这个维度所获得的信息量就基本为0,也就是说我们无法从这个维度得知一张人脸属于谁。所以我要想通过鼻子这一维度来区分出这3个人的话,我需要一个大的方差,比如说他们的鼻子分别是大,中,小鼻子,此时的方差就比较大了,这时就可以通过鼻子这一维度来获得比较大的信息量,通过这一维度来进行人脸识别。这样一来鼻子这一维度就是一个有效的特征。基于此。引出PCA降维算法的目标:

  1. 降维后同一维度的方差最大
  2. 不同维度之间的相关性为0

因为我们的目的在于用尽量少维度来表示物体特征,那么我一定是希望每个维度的特征越明显越好,所以要求方差最大。并且我不能有a和b能够推出c的情况,因为这样的话就形成了冗余特征,所以不同维度之间不能有相关性

由于不同维度之间相关性应为0,由此便引出协方差概念

3. PCA——协方差

协方差是用来度量两个随机变量关系的统计量
同一元素的协方差就表示该元素的方差,不同元素之间的协方差就表示它们的相关性
协方差>0 , 表示X和Y正相关
协方差=0 , 表示X和Y不相关(我们要找的就是这个点)
协方差<0 , 表示X和Y负相关
在这里插入图片描述

在理解协方差时应将其与方差结合起来,因为方差描述的是变量和均值之间的关系,那对于协方差而言,如果两个变量之中有一个是均值,那此时协方差就变成了方差,所以方差实际上是协方差的一个特例,当X和Y为同一特征时,此时的协方差就是方差。所以说同一元素的协方差就表示该元素的方差,不同元素之间的协方差就表示它们的相关性。所以说我们最后得到的几个特征,两两之间的协方差都应该为0。
这里有一个问题在于协方差只能处理二维的数据,但是我们的整个数据集当中,特征维度肯定不止2维,可能有100维,那我们两两之间都要做协方差,所以这时就引入了矩阵来组织多维数据,所以我们就用到了协方差矩阵

4. PCA——协方差矩阵

定义:
在这里插入图片描述

这里其实就是把两两之间的协方差都列举出来了
协方差矩阵的特点:

  • 协方差矩阵计算的是不同维度之间的协方差,而不是不同样本的
  • 样本矩阵的每行是一个样本,每列为一个维度,所以我们要按列计算均值
  • 协方差矩阵的对角线就是各个维度上的方差

这里需要区分样本矩阵协方差矩阵

特别的,如果做了中心化,则协方差矩阵为(中心化矩阵的协方差矩阵公式,m为样本个数):
在这里插入图片描述

5. PCA——对协方差矩阵求特征值,特征矩阵

A为n阶矩阵(在应用中,A为协方差矩阵),若数λ和n维非0列向量x满足Ax=λx,那么数λ称为A的特征值,x称为A的对应于特征值λ 的特征向量。
式Ax=λx也可写成( A-λE)x=0,E是单位矩阵,并且|A-λE|叫做A 的特征多项式。当特征多项式等于0的 时候,称为A的特征方程,特征方程是一个齐次线性方程组,求解特征值的过程其实就是求解特征方程的解。
对于协方差矩阵A,其特征值( 可能有多个)计算方法为:
在这里插入图片描述

对数字图像矩阵做特征值分解,其实是在提取这个图像中的特征,这些提取出来的特征是一个个的向量,即 对应着特征向量。而这些特征在图像中到底有多重要,这个重要性则通过特征值来表示。
比如一个100x100的图像矩阵A分解之后,会得到一个100x100的特征向量组成的矩阵Q,以及一个100x100 的只有对角线上的元素不为0的矩阵E,这个矩阵E对角线上的元素就是特征值,而且还是按照从大到小排列 的(取模,对于单个数来说,其实就是取绝对值),也就是说这个图像A提取出来了100个特征,这100个特 征的重要性由100个数字来表示,这100个数字存放在对角矩阵E中。
所以归根结底,特征向量其实反应的是矩阵A本身固有的一些特征,而此时A表示的是协方差矩阵,所以此时的特征向量反映的是协方差矩阵的特征。本来一个矩阵就是一个线性变换, 当把这个矩阵作用于一个向量的时候,通常情况绝大部分向量都会被这个矩阵A变换得“面目全非”, 但是偏偏刚好存在这么一些向量,被矩阵A变换之后居然还能保持原来的样子,于是这些向量就可以 作为矩阵的核心代表了。 于是我们可以说:一个变换(即一个矩阵)可以由其特征值和特征向量完全表述,这是因为从数学上 看,这个矩阵所有的特征向量组成了这个向量空间的一组基底。而矩阵作为变换的本质其实就是把一个基底下的东西变换到另一个基底表示的空间中。

6. PCA——对特征值进行排序

在这里插入图片描述

7. PCA——评价模型的好坏,k值的确定

通过特征值的计算我们可以得到主成分所占的百分比,用来衡量模型的好坏。
对于前k个特征值所保留下的信息量计算方法如下:
在这里插入图片描述

8. PCA——代码实现

1. 手动实现

# -*- coding: utf-8 -*-
"""
使用PCA求样本矩阵X的K阶降维矩阵Z
"""
 
import numpy as np
 
class CPCA(object):
    '''用PCA求样本矩阵X的K阶降维矩阵Z
    Note:请保证输入的样本矩阵X shape=(m, n),m行样例,n个特征
    '''
    def __init__(self, X, K):
        '''
        :param X,训练样本矩阵X
        :param K,X的降维矩阵的阶数,即X要特征降维成k阶
        '''
        self.X = X       #样本矩阵X
        self.K = K       #K阶降维矩阵的K值
        self.centrX = [] #矩阵X的中心化
        self.C = []      #样本集的协方差矩阵C
        self.U = []      #样本矩阵X的降维转换矩阵
        self.Z = []      #样本矩阵X的降维矩阵Z
        
        self.centrX = self._centralized()
        self.C = self._cov()
        self.U = self._U()
        self.Z = self._Z() #Z=XU求得
        
    def _centralized(self):
        '''矩阵X的中心化'''
        print('样本矩阵X:\n', self.X)
        centrX = []
        mean = np.array([np.mean(attr) for attr in self.X.T]) #样本集的特征均值
        print('样本集的特征均值:\n',mean)
        centrX = self.X - mean ##样本集的中心化
        print('样本矩阵X的中心化centrX:\n', centrX)
        return centrX
        
    def _cov(self):
        '''求样本矩阵X的协方差矩阵C'''
        #样本集的样例总数
        ns = np.shape(self.centrX)[0]
        #样本矩阵的协方差矩阵C
        C = np.dot(self.centrX.T, self.centrX)/(ns - 1)
        print('样本矩阵X的协方差矩阵C:\n', C)
        return C
        
    def _U(self):
        '''求X的降维转换矩阵U, shape=(n,k), n是X的特征维度总数,k是降维矩阵的特征维度'''
        #先求X的协方差矩阵C的特征值和特征向量
        a,b = np.linalg.eig(self.C) #特征值赋值给a,对应特征向量赋值给b。函数doc:https://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.linalg.eig.html 
        print('样本集的协方差矩阵C的特征值:\n', a)
        print('样本集的协方差矩阵C的特征向量:\n', b)
        #给出特征值降序的topK的索引序列
        ind = np.argsort(-1*a)
        #构建K阶降维的降维转换矩阵U
        UT = [b[:,ind[i]] for i in range(self.K)]
        U = np.transpose(UT)
        print('%d阶降维转换矩阵U:\n'%self.K, U)
        return U
        
    def _Z(self):
        '''按照Z=XU求降维矩阵Z, shape=(m,k), n是样本总数,k是降维矩阵中特征维度总数'''
        Z = np.dot(self.X, self.U)
        print('X shape:', np.shape(self.X))
        print('U shape:', np.shape(self.U))
        print('Z shape:', np.shape(Z))
        print('样本矩阵X的降维矩阵Z:\n', Z)
        return Z
        
if __name__=='__main__':
    '10样本3特征的样本集, 行为样例,列为特征维度'
    X = np.array([[10, 15, 29],
                  [15, 46, 13],
                  [23, 21, 30],
                  [11, 9,  35],
                  [42, 45, 11],
                  [9,  48, 5],
                  [11, 21, 14],
                  [8,  5,  15],
                  [11, 12, 21],
                  [21, 20, 25]])
    K = np.shape(X)[1] - 1
    print('样本集(10行3列,10个样例,每个样例3个特征):\n', X)
    pca = CPCA(X,K)

2. 利用numpy库封装好的函数简化代码

#coding=utf-8

import numpy as np
class PCA():
    def __init__(self,n_components):
        self.n_components = n_components
    
    def fit_transform(self,X):
        self.n_features_ = X.shape[1]
        # 求协方差矩阵
        X = X - X.mean(axis=0)
        self.covariance = np.dot(X.T,X)/X.shape[0]
        # 求协方差矩阵的特征值和特征向量
        eig_vals,eig_vectors = np.linalg.eig(self.covariance)
        # 获得降序排列特征值的序号
        idx = np.argsort(-eig_vals)
        # 降维矩阵
        self.components_ = eig_vectors[:,idx[:self.n_components]]
        # 对X进行降维
        return np.dot(X,self.components_)
 
# 调用
pca = PCA(n_components=2)
X = np.array([[-1,2,66,-1], [-2,6,58,-1], [-3,8,45,-2], [1,9,36,1], [2,10,62,1], [3,5,83,2]])  #导入数据,维度为4
newX=pca.fit_transform(X)
print(newX)                  #输出降维后的数据

3. 利用sklearn库简化

sklearn是一个第三方库,里面提供了一个PCA函数,调用它可以直接进行降维
在这里插入图片描述

#coding=utf-8

import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1,2,66,-1], [-2,6,58,-1], [-3,8,45,-2], [1,9,36,1], [2,10,62,1], [3,5,83,2]])  #导入数据,维度为4
pca = PCA(n_components=2)   #降到2维
pca.fit(X)                  #训练
newX=pca.fit_transform(X)   #降维后的数据
# PCA(copy=True, n_components=2, whiten=False)
print(pca.explained_variance_ratio_)  #输出贡献率
print(newX)                  #输出降维后的数据

9. PCA——鸢尾花实例

我们通过Python的sklearn库来实现鸢尾花数据 进行降维,数据本身是4维的,降维后变成2维。
其中样本总数为150,鸢尾花的类别有三种。
在这里插入图片描述

#!/usr/bin/env python
# encoding=gbk

import matplotlib.pyplot as plt
import sklearn.decomposition as dp
from sklearn.datasets.base import load_iris

x,y=load_iris(return_X_y=True) # 加载数据,x表示数据集中的属性数据,y表示数据标签
pca=dp.PCA(n_components=2) # 加载PCA算法,设置降维后主成分数目为2
reduced_x=pca.fit_transform(x) # 对原始数据进行降维,保存在reduced_x中
red_x,red_y=[],[]
blue_x,blue_y=[],[]
green_x,green_y=[],[]
for i in range(len(reduced_x)): # 按鸢尾花的类别将降维后的数据点保存在不同的表中
    if y[i]==0:
        red_x.append(reduced_x[i][0])
        red_y.append(reduced_x[i][1])
    elif y[i]==1:
        blue_x.append(reduced_x[i][0])
        blue_y.append(reduced_x[i][1])
    else:
        green_x.append(reduced_x[i][0])
        green_y.append(reduced_x[i][1])
plt.scatter(red_x,red_y,c='r',marker='x')
plt.scatter(blue_x,blue_y,c='b',marker='D')
plt.scatter(green_x,green_y,c='g',marker='.')
plt.show()

结果:
在这里插入图片描述

10. PCA——算法优缺点

优点:

  1. 完全无参数限制的。在PCA的计算过程中完全不需要人为的设定参数或是根据任何经验模型对计算 进行干预,最后的结果只与数据相关,与用户是独立的。
  2. 用PCA技术可以对数据进行降维,同时对新求出的“主元”向量的重要性进行排序,根据需要取前面 最重要的部分,将后面的维数省去,可以达到降维从而简化模型或是对数据进行压缩的效果。同时 最大程度的保持了原有数据的信息。
  3. 计算方法简单,易于在计算机上实现。

缺点:

  1. 如果用户对观测对象有一定的先验知识,掌握了数据的一些特征,却无法通过参数化等方法对处理 过程进行干预,可能会得不到预期的效果,效率也不高。

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

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

相关文章

【算法与数据结构】19、LeetCode删除链表的倒数第 N 个结点

文章目录 一、题目二、双指针法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、双指针法 思路分析&#xff1a;这道题使用双指针一次遍历就能删除目标节点。快慢指针同一位置出发&#xff08;虚节点&#x…

博采众长!我全都要!Allen AI推出集成主流大语言模型的LLM-BLENDER框架

深度学习自然语言处理 原创作者&#xff1a;wkk 随着大语言模型(LLM)的迅速发展&#xff0c;众多开源的LLM性能参差不齐。今天分享的是由Allen AI实验室联合南加大和浙江大学的最新研究论文&#xff0c;发表在ACL上。本文提出了一个集成框架(LLM-BLENDER)&#xff0c;旨在通过利…

6.11下周黄金行情分析及开盘多空交易策略

近期有哪些消息面影响黄金走势&#xff1f;下周黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;金价周五(6月8日)收低&#xff0c;但在美元整体走软的支撑下&#xff0c;本周录得连续第二周上升。美市尾盘&#xff0c;现货黄金收报1960.83美元/盎司&#xff0c;…

分布式项目 16 购物车系统,dubbo框架(重点是拦截器),优化userId,配合拦截器

01.创建jt-cart项目 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a; 在pom.xml文件中添加jt-common的依赖&#xff0c;如图所示&#xff1a; 第五步&#xff1a; 添加插件 <build> <plugins> <!--跳过测试类打包 --> <…

支撑臂爬楼履带车实现爬楼梯功能

1. 功能说明 本文示例将实现R018a支撑臂爬楼履带车爬楼梯的功能。 2. 结构说明 支撑臂爬楼履带车主要是由 小型平行履带底盘 和2个 舵机关节模组 组成。 3. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#…

MIT 6.S081 (BOOK-RISCV-REV1)教材第二章内容

MIT 6.S081 第二章内容 引言操作系统架构抽象系统资源用户态&#xff0c;核心态&#xff0c;以及系统调用内核组织代码&#xff08;XV6架构篇&#xff09;进程概述代码&#xff08;启动XV6和第一个进程&#xff09;真实世界 引言 MIT 6.S081 2020 操作系统 本文为MIT 6.S081课…

用饭店来形象比喻线程池的工作原理

一、线程池解决的问题&#xff1f; 使用线程池主要解决在程序中频繁创建和销毁线程导致的资源浪费&#xff0c;线程池可以维护一定量的线程来执行所需要的任务&#xff0c;维护的线程也可以重复使用。 二、用形象的饭店来解释工作原理 线程池就相当于一家饭店&#xff0c; 任…

SpringBoot框架的学生宿舍管理系统

项目介绍 主要功能&#xff1a; 管理员登录权限&#xff1a; ①学生管理&#xff1a;根据编号姓名搜索、可以新增修改删除、导入导出 ②楼宇管理&#xff1a;根据楼宇搜索、可以新增修改删除、导入导出 ③宿舍管理&#xff1a;根据宿舍编号搜索、可以新增修改删除、导入导出 ④…

HCIA-RS实验-配置FTP 业务

FTP简单说明 FTP&#xff08;File Transfer Protocol&#xff09;是一种用于文件传输的协议&#xff0c;可以在计算机之间进行文件的上传和下载。FTP使用客户端-服务器模型&#xff0c;客户端通过FTP客户端软件连接到服务器端的FTP服务端口&#xff0c;进行文件传输和管理。 F…

在fpga上开发音视频是一种什么体验?

前言&#xff1a; 今天周末回公司解决了解码播放问题&#xff0c;最近周末也没啥事情&#xff0c;一般周六都会过去公司学习音视频开源项目(过去公司&#xff0c;主要是住的近&#xff0c;所以很方便&#xff01;)&#xff0c;待在家里也是无聊&#xff0c;所以就回去看开源项目…

硬件设计电源系列文章-LDO设计

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 本文主要分享LDO的相关设计&#xff0c;尤其是LDO的并联设计 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 主要是讲述LDO的并联&#xff1b;并联以增加输出驱动能力&#xff0c;其具体框架如下&#x…

详解Ribbon

目录 1.概述 2.使用 2.1.引入 2.2.启用 2.3.切换负载均衡算法 3.负载均衡源码分析 3.1.接口 3.2.抽象类 3.3.选择服务器 3.4.原子性 4.自定义负载均衡算法 1.概述 Ribbon是Netflix开源的一个客户端负载均衡库&#xff0c;也是Spring Cloud Netflix项目的核心组件之…

常见网络服务器并发模型

近些年&#xff0c;随着互联网的大发展&#xff0c;高并发服务器技术也快速进步&#xff0c;从简单的循环服务器模型处理少量网络并发请求&#xff0c;演进到解决C10K&#xff0c;C10M问题的高并发服务器模型。本文主要以TCP为例&#xff0c;总结了几种常见的网络服务器模型的实…

巧用文件批量改名高手删除子文件夹一例

比如有很多商品文件夹&#xff0c;里面又分出主图、细节图等&#xff0c;现在因工作需要把主图、细节图这些子文件夹去掉&#xff0c;把子文件夹里面的文件放在商品名称的父文件夹中&#xff0c;如图&#xff1a; 打开主图文件夹&#xff0c;我们可以看到文件名结构为数字编号的…

Git学习 - 2023-06-08

2023暑期学习 Git基础Git Fetch VS Git Pullgit pull --rebase VS git pull几种merge的方法Fork VS Clone CS Branch如何把master的内容更新到分支上详尽介绍 git fetch VS git pull其他命令 Git基础 git branch branch-name # 创建一个新的分支git checkout branch-name # 切…

Golang | Web开发之Gin框架快速入门基础实践

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; 专注 企业运维实践、网络安全、系统运维、应用开发、物联网实战、全栈文章 等知识分享 “ 花开堪折直须折&#xf…

Learning C++ No.30 【lambda表达式实战】

引言&#xff1a; 北京时间&#xff1a;2023/6/9/9:13&#xff0c;今天8:15起床&#xff0c;可能是最近课非常少&#xff0c;导致写博客没什么压力&#xff0c;什么时间都能写&#xff0c;导致7点起不来&#xff0c;哈哈哈&#xff0c;习惯睡懒觉了&#xff0c;但是问题不大&a…

【二十七】springboot之通过threadLocal+参数解析器实现同session一样保存当前登录信息的功能

springboot篇章整体栏目&#xff1a; 【一】springboot整合swagger&#xff08;超详细 【二】springboot整合swagger&#xff08;自定义&#xff09;&#xff08;超详细&#xff09; 【三】springboot整合token&#xff08;超详细&#xff09; 【四】springboot整合mybatis…

绿豆影视系统5.1.8反编译版源码:PC+WAP+APP端【附搭建教程+软件】

简介&#xff1a; 绿豆影视系统5.1.8反编译版源码&#xff1a;PCWAPAPP端【附搭建教程软件】 优化内容 1.专题类目&#xff0c;在后台进行设置 2.短视频类目 &#xff0c;需要有信天翁id 3.优化首页栏目不显示问题 4.去除我的页面 不常用功能 5.修复自定义密码只能输入数字的…

二阳竟然是这样的~

今天周六&#xff0c;家人都出去玩了&#xff0c;把我自己扔家里了&#xff0c;因为我2阳了&#xff0c;出门都不带我玩了。 正好趁这个时间简单写下2阳的症状&#xff0c;和1阳有什么不一样。 先说结论&#xff1a; 我的亲身感受是2阳比1阳轻的多&#xff0c;没有浑身关节疼&a…