PCA降维算法的介绍、多角度推导及python实现

2023-10-27

一、算法原理及数学推导
在对于数据的处理上,特征维度过高经常是一个无法忽视的问题,但是单纯的降维压缩对于数据本身会使得数据信息遭到严重损失。不过以PCA为代表的线性降维算法对这方面有所保证,它的目标是通过某种线性投影,将高维的数据映射到低维的空间中,并期望在所投影的维度上数据的信息量最大(方差最大),以此使用较少的数据维度,同时保留住较多的原数据点的特性。
PCA算法所做的工作相当于原始特征空间的重构,只不过这个重构的过程是一个寻找主成分(正交方向),使得投影于该方向上的点足够离散的过程,其优化方向有两个,一是保证投影方差最大,二是保证重构代价最小。
以下为推导求解过程:
假设有N个样本数据,P个特征组成的数据集X,X (i=1,2,3…N)表示第i个数据。特征的均值向量为:
在这里插入图片描述

每个样本与均值向量的差为:
在这里插入图片描述

那么数据集(X_1,X_2,X_3…,X_m)的协方差矩阵为:
在这里插入图片描述

假设所选择的主成分方向为u_1,在这里插入图片描述
则特征向量在该方向上的投影为:
在这里插入图片描述

投影的二范式为:
在这里插入图片描述

1、投影方差最大化求解
在这里插入图片描述

如此,便可转化为最优化问题,引入拉格朗日乘子λ:
在这里插入图片描述

对L求偏导得:
在这里插入图片描述

在这里插入图片描述
得:
在这里插入图片描述

显然,此等式意在求S的特征值及特征向量。则对投影方差最大化问题的求解可直接等价为求协方差矩阵的特征值及特征向量。
2、重构代价最小化求解
重构代价即投影后的点在新的坐标系下反向投影回原坐标系后所得向量的长度。
在这里插入图片描述

在二维空间中,x_i为向量,u_1和u_2为投影后含主成分方向的坐标轴,求其重构后向量为:在这里插入图片描述

得出m维空间中:在这里插入图片描述

以此求重构代价:
在这里插入图片描述

其中:
P为数据维度即特征维度
q为降维后数据的维度
重构代价最小化:
在这里插入图片描述

转化为二次优化问题,可发现求解过程与最大投影方差的角度一样,同时,此处取的是最小的P-q个λ值,可等价于求最大的q个,故而两个角度所求得的解是一样的。
两角度后续共同的求解:
计算协方差矩阵S的P个特征值及特征向量(α_1,α_2,α…,α_P),按特征值非递减排序后,取前面的q个特征值,使用其对应的特征向量组成一个q维的特征空间,记为U。同时,为衡量每个样本向量的贡献度,引入贡献度计算公式:
在这里插入图片描述

则原始数据集在特征向量集U下可通过如下方式投影到低维空间:
在这里插入图片描述

二、算法代码实现
1、代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs


class DimensionValueError(ValueError):
    """定义异常类"""
    pass


class PCA(object):
    """定义PCA类"""

    def __init__(self, x, n_components=None):
        """x的数据结构应为ndarray"""
        self.x = x
        self.dimension = x.shape[1]

        if n_components and n_components >= self.dimension:
            raise DimensionValueError("n_components error")

        self.n_components = n_components

    def cov(self):
        """求x的协方差矩阵"""
        x_T = np.transpose(self.x)  # 矩阵转秩
        x_cov = np.cov(x_T)  # 协方差矩阵
        return x_cov

    def get_feature(self):
        """求协方差矩阵C的特征值和特征向量"""
        x_cov = self.cov()
        a, b = np.linalg.eig(x_cov)
        m = a.shape[0]
        c = np.hstack((a.reshape((m, 1)), b))
        c_df = pd.DataFrame(c)
        c_df_sort = c_df.sort_values(by=0,ascending=False)  # 按照特征值大小降序排列特征向量
        return c_df_sort

    def explained_varience_(self):
        c_df_sort = self.get_feature()
        return c_df_sort.values[:, 0]

    def paint_varience_(self):
        explained_variance_ = self.explained_varience_()
        plt.figure()
        plt.plot(explained_variance_, 'k')
        plt.xlabel('n_components', fontsize=16)
        plt.ylabel('explained_variance_', fontsize=16)
        plt.show()

    def reduce_dimension(self):
        """指定维度降维和根据方差贡献率自动降维"""
        c_df_sort = self.get_feature()
        varience = self.explained_varience_()

        if self.n_components:  # 指定降维维度
            p = c_df_sort.values[0:self.n_components, 1:]
            y = np.dot(p, np.transpose(self.x))  # 矩阵叉乘
            return np.transpose(y)

        varience_sum = sum(varience)  # 利用方差贡献度自动选择降维维度
        varience_radio = varience / varience_sum

        varience_contribution = 0
        for R in range(self.dimension):
            varience_contribution += varience_radio[R]  # 前R个方差贡献度之和
            if varience_contribution >= 0.99:
                break

        p = c_df_sort.values[0:R + 1, 1:]  # 取前R个特征向量
        y = np.dot(p, np.transpose(self.x))  # 矩阵叉乘
        return np.transpose(y)


x, y = make_blobs(n_samples=10000, n_features=3, centers=[[3, 3, 3], [0, 0, 0], [1, 1, 1], [2, 2, 2]],
                  cluster_std=[0.2, 0.1, 0.2, 0.2],
                  random_state=9)

if __name__ == '__main__':
    fig=plt.figure()
    ax=plt.axes(projection='3d')
    ax.scatter(x[:,0],x[:,1],x[:,2])
    plt.show()
    plt.savefig("C://Users//hasee//Desktop")
    pca = PCA(x)
    y = pca.reduce_dimension()
    plt.scatter(x[:,0],x[:,1])
    plt.show()
    plt.savefig("C://Users//hasee//Desktop")
    print(y.shape)

2、数据降维实例
(1)原数据集
在这里插入图片描述

(2)降维后保留2个特征
在这里插入图片描述

降维后数据分布特点与之前在很大程度上相似,说明保留了大部分的数据信息。
3、算法存在的问题
用主成分解释数据含义往往具有一定的模糊性,不如原始数据完整。其次,PCA方法寻找的是用来有效表示同一类样本共同特点的主轴方向,这对于表示同一类数据样本的共同特征是非常有效的,但PCA不适合用于区分不同的样本类。Fisher线性判别分析(FDA)是用于寻找最有效地对不同样本类进行区分的方向。其主要思想是考虑将d维空间中的点投影到一条直线上。通过适当地选择直线的方向,有可能找到能够最大限度地区分各类样本数据点的投影方向。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PCA降维算法的介绍、多角度推导及python实现 的相关文章

随机推荐

  • Python学习小记(1)—命令指示符

    一 命令指示符如何打开使用 1 使用组合快捷键 Win R 打开运行对话框 然后在打开后面输入 cmd 命令操作符快捷名称 2 电脑的开始 附件里面找到命令提示符入口 二 学习Python时 常用的命令语句 1 当先进入某盘时 直接输入盘的
  • Arduino VS 树莓派:哪个才是你的菜?

    假设你正在寻找一台微型计算机 它能够驱动一台激光炮塔向彩色气球射击 作为一名极客 你可能常会幻想到类似的场景 那么你很可能已经听说过Arduino和树莓派 Raspberry Pi 了 但是却拿不定主意 到底哪种微型计算机才适合你的个人项目
  • centos7的一些变化,firewalld替换iptables、systemctl 替换service

    1 防火墙命令用firewalld取代了iptables了 查看防火墙状态 systemctl status firewalld 临时关闭防火墙命令 reboot之后 防火墙自动起来 systemctl stop firewalld 永久关
  • QGIS加载谷歌地图(google map)方法

    目录 第一步 第二步 将Google提供的网络地图 包括地图和卫星影像等 作为图层加载到QGIS中 有时可辅助地学分析 QGIS已经提供了OpenStreetMap 在 XYZ Tiles 里面加载即可 谷歌街道地图 http mt2 go
  • 同样是做自媒体,为什么有的人能月入过万,你只能月入几块?

    经常有粉丝跟大周说 自媒体的红利期是不是已经过去了呢 收益低 做自媒体的收益还不够交电费的呢 同样是做自媒体 为什么有的人可以月入过万甚至更多 而一些人只能收益个位数甚至赚不到钱 我们都知道小马过河的故事 牛告诉小马河很浅 松鼠告诉小马河很
  • server 2003搭建文件服务器,使用Windows Server 2003搭建安全文件服务器

    ZDNetChina服务器站 8月14日x86技巧 启用并配置文件服务 Windows Server 2003的管理工具中有一项功能叫做 管理您的服务器 启动该工具之后 可以看到当前服务器上启用的所有服务 并可对这些服务进行管理 点击该界面
  • IOC和DI的关系

    IOC 控制反转 全称为 Inverse of Control 将对在自身对象中的一个内置对象的控制反转 反转后不再由自己本身的对象进行控制这个内置对象的创建 而是由第三方系统去控制这个内置对象的创建 简单来说就是把本来在类内部控制的对象
  • LLM Data Pipelines: 解析大语言模型训练数据集处理的复杂流程

    编者按 在训练大语言模型的过程中 构建高质量的训练数据集是非常关键的一步 但关于构建大模型训练所需数据集的通用数据处理流程 Data pipelines 的相关资料极为稀少 本文主要介绍了基于Common Crawl数据集的数据处理流程 首
  • 基于Spring Boot+ Vue的健身房管理系统与实现

    小熊学Java全能学 面试指南 https javaxiaobear cn 摘要 随着健身行业的快速发展 健身房管理系统成为了提高管理效率和用户体验的重要工具 本论文旨在设计与实现一种基于前后端分离的健身房管理系统 通过前后端分离的架构模式
  • R语言笔记:机器学习【决策树(Decision Tree】

    写在开头 我是一个学R的小白 因为读研老师要求开始接触R 记一记笔记留给自己以后回顾 顺便分享出来嘻嘻 我把需要深入的的函数进行介绍 方便了解这些函数的用法 一些简单的函数我就不放出来啦 决策树这部分的笔记主要是利用分类回归法哈 rpart
  • Python_集合去重的底层原理

    Python 集合去重的底层原理 https www cnblogs com linshuhui p 9580620 html
  • JAVA枚举类型(enum)的巧妙应用

    枚举类型的应用 实例 总结 根据接口文档的需求 需要使用通用的返回值类型进行返回 实例 return 调用的error方法就是先new一个ApiRestResponse对象 然后返回 之前在controller层调用的ImoocMallEx
  • Java和Java之父

    詹姆斯 高斯林 James Gosling 1955年5月19日出生于加拿大 是Java编程语言的共同创始人之一 一般公认他为 Java之父 1983年高斯林获得了美国卡内基梅隆大学计算机科学博士学位 博士论文的题目是 The Algebr
  • python编程语言介绍-Python基础手册 1 —— Python语言介绍

    python logo png Python 是一门优雅而健壮的编程语言 它继承了传统编译语言的强大性和通用性 同时也借鉴了脚本语言和解释语言的简单性和易用性 一 Python 的历史 Python是由创始人贵铎 范 罗萨姆 Guido v
  • js 字符串转换数字

    本文转载至 http www phpweblog net linxiaobo archive 2008 12 29 6250 html PS 今天用到了 一下子想不起来 所以写下来 省得下次又找 方法主要有三种 转换函数 强制类型转换 利用
  • centos 上安装redis 3.0.5

    官网下载安装包 直接使用make编译 报如下错误 root localhost redis 3 0 5 make cd src make all make 1 进入目录 usr local opentest redis 3 0 5 src
  • 记一次udf提权

    靶场myandmygirlfriend 前面的信息收集就不说了 arp scan l nmap扫描主机和端口 dirsearch扫描目录 打开页面可以看到 only be accessed local 谷歌翻译发现是只能本地访问 看一眼源码
  • Problem:ImageView不能显示图片。

    1 问题分析 要实现的功能是 ImageView被加载进了一个绝对布局对象中 并通过不断地设置LayoutParam来改变其位置 其中ImageView中的图片是以方法setBackgroundDrawable加载的 而用此方法 在过去有一
  • STM32ADC多通道采集(基于DMA)

    首先简单介绍DMA DMA Direct Memory Access 直接内存存取 用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输 无需CPU干预 节省CPU资源 ADC转换出来的值直接赋值给定义好的变量中 配置好的DMA可
  • PCA降维算法的介绍、多角度推导及python实现

    一 算法原理及数学推导 在对于数据的处理上 特征维度过高经常是一个无法忽视的问题 但是单纯的降维压缩对于数据本身会使得数据信息遭到严重损失 不过以PCA为代表的线性降维算法对这方面有所保证 它的目标是通过某种线性投影 将高维的数据映射到低维