python实现PCA降维画分类散点图并标出95%的置信区间

news2024/12/26 11:42:56

此代码以数据集鸢尾花为例,对其使用PCA降维后,绘制了三个类别的样本点和对应的置信圆(即椭圆)。先放效果图。

 下面是完整代码:

from matplotlib.patches import Ellipse

def plot_point_cov(points, nstd=3, ax=None, **kwargs):
    # 求所有点的均值作为置信圆的圆心
    pos = points.mean(axis=0)
    # 求协方差
    cov = np.cov(points, rowvar=False)

    return plot_cov_ellipse(cov, pos, nstd, ax, **kwargs)

def plot_cov_ellipse(cov, pos, nstd=3, ax=None, **kwargs):
    def eigsorted(cov):
        cov = np.array(cov)
        vals, vecs = np.linalg.eigh(cov)
        order = vals.argsort()[::-1]
        return vals[order], vecs[:, order]
    if ax is None:
        ax = plt.gca()
    vals, vecs = eigsorted(cov)

    theta = np.degrees(np.arctan2(*vecs[:, 0][::-1]))
    width, height = 2 * nstd * np.sqrt(vals)
    ellip = Ellipse(xy=pos, width=width, height=height, angle=theta, **kwargs)
    ax.add_artist(ellip)
    return ellip

'''画置信圆'''
def show_ellipse(X_pca, y, pca, flag=1):
    # 定义颜色

    colors = ['tab:blue', 'tab:orange', 'seagreen']
    regions = ['Ethiopia', 'Somalia', 'Kenya']

    # 定义分辨率
    plt.figure(dpi=300, figsize=(8, 6))
    # 三分类则为3
    for i in range(0, 3):
        pts = X_pca[y == int(i), :]
        new_x, new_y = X_pca[y==i, 0], X_pca[y==i, 1]

        plt.plot(new_x, new_y, '.', color=colors[i], label=regions[i], markersize=14)

        plot_point_cov(pts, nstd=3, alpha=0.25, color=colors[i])

    # 添加坐标轴
    plt.xlim(-3.5, 4.5)
    plt.ylim(-1.5, 1.7)
    plt.xticks(size=16, family='Times New Roman')
    plt.yticks(size=16, family='Times New Roman')
    font = {'family': 'Times New Roman', 'size': 16}
    plt.xlabel('PC1 ({} %)'.format(round(pca.explained_variance_ratio_[0] * 100, 2)), font)
    plt.ylabel('PC2 ({} %)'.format(round(pca.explained_variance_ratio_[1] * 100, 2)), font)

    plt.legend(prop={"family": "Times New Roman", "size": 9},  loc='upper right')
    plt.show()

import pandas as pd
from sklearn.decomposition import PCA
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
labels = ['setosa', 'versicolor', 'virginica']
iris = load_iris()
X = iris.data
y = iris.target_names[iris.target]

print("y length--------", len(y))
y_category = pd.Categorical(y,ordered=True,categories=['setosa', 'versicolor', 'virginica'])

y = y_category.codes
print(y)
print(y.shape)
print(type(y[0]))
n_components = 2
pca = PCA(n_components=n_components)
X_pca = pca.fit_transform(X)
show_ellipse(X_pca, y, pca)

下面讲解实现过程。 

首先导入需要的库和数据集:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from matplotlib.patches import Ellipse

然后定义了一个函数 plot_point_cov(),用于计算样本点的协方差矩阵,并调用另一个函数 plot_cov_ellipse(),绘制置信椭圆。

代码中的cov变量是用于计算数据集协方差矩阵的。协方差矩阵用于描述多个变量之间的关系,其中对角线上的元素表示每个变量本身的方差,非对角线上的元素表示不同变量之间的协方差。

在函数plot_cov_ellipse()中使用协方差矩阵计算数据集的特征向量和特征值。特征向量和特征值用于确定椭圆的大小和方向,以便绘制置信椭圆。

因为在二维空间中,椭圆的方向和大小可以用特征向量和特征值来描述。例如对于一个2x2的协方差矩阵cov,它有两个特征向量和两个特征值,分别表示数据集在两个主要方向上的方差和偏移。特征向量的方向决定了椭圆的主轴方向,而特征值的大小则决定了椭圆沿每个主轴的长度。

在函数plot_cov_ellipse()中,先使用np.linalg.eigh()函数计算协方差矩阵cov的特征值和特征向量,然后按特征值从大到小的顺序排序,这样可以确保主轴方向是正确的。然后根据主轴方向的角度和特征值计算椭圆的宽度和高度,进而绘制置信椭圆。函数np.degrees()用于将弧度转换为角度,函数np.arctan2()用于计算角度。

np.degrees() 该函数使用的公式:角度=弧度*180/pi

np.degrees() 函数的参数是 np.arctan2(*vecs[:, 0][::-1]),它表示计算向量 vecs 中第一列(即下标为 0 的列)的极角(即与 x 轴的夹角)并将结果转换为角度制。

具体来说,vecs[:, 0] 表示选取 vecs 中所有行的第一列组成的向量,[::-1] 表示将该向量反转,从而得到与 arctan2 函数所需的参数格式一致的向量。

然后,np.arctan2() 函数接收两个参数,表示计算以这两个参数组成的向量为起点,与原点连接的向量的极角。这里第一个参数是反转后的向量,即 vecs[:, 0][::-1],第二个参数未给出,因此默认为 1。

最后,np.degrees() 函数将弧度制的极角值转换为角度制。因此,整个代码行的作用是计算向量 vecs 的第一列的极角,并将结果转换为角度制。

vals, vecs = eigsorted(cov)其目的是计算输入协方差矩阵的特征值和特征向量并返回排好序的结果。

特征值(eigenvalues)是协方差矩阵的一个重要属性,代表着每个特征向量的方差。在PCA中,特征值告诉我们每个主成分解释方差的大小。排序特征值后,我们可以选择最大的K个特征值来保留大部分数据的方差。

特征向量(eigenvectors)是PCA中另一个重要的概念,它们是协方差矩阵的正交基向量。每个特征向量对应着一个特征值。它们可以用来表示主成分的方向,PCA中的主成分就是按特征值大小排序后的特征向量。PCA的主要目的就是通过旋转坐标系来最大化每个主成分方差。

特征向量在这里被用来求出主成分的方向。在函数中,特征向量通过 vecs[:, order] 得到, [:, order] 表示选中所有行( : )和按照特定顺序排序的所有列( order )。这些特征向量就是主成分方向的坐标轴,可以用来画出置信区间椭圆的角度。

椭圆的角度可以通过主成分方向的坐标轴与水平轴的夹角得到。在给定的代码中, theta 被计算为 np.degrees(np.arctan2(*vecs[:, 0][::-1])),其中 arctan2() 计算向量的反正切值, [::-1] 表示按照相反的顺序取向量的元素。 np.degrees() 将弧度转换为角度。

def plot_point_cov(points, nstd=3, ax=None, **kwargs):
    # 求所有点的均值作为置信圆的圆心
    pos = points.mean(axis=0)
    # 求协方差矩阵
    cov = np.cov(points, rowvar=False)

    return plot_cov_ellipse(cov, pos, nstd, ax, **kwargs)

def plot_cov_ellipse(cov, pos, nstd=3, ax=None, **kwargs):
    def eigsorted(cov):
        cov = np.array(cov)
        vals, vecs = np.linalg.eigh(cov)
        order = vals.argsort()[::-1]
        return vals[order], vecs[:, order]

    if ax is None:
        ax = plt.gca()
    vals, vecs = eigsorted(cov)

    theta = np.degrees(np.arctan2(*vecs[:, 0][::-1]))
    width, height = 2 * nstd * np.sqrt(vals)
    ellip = Ellipse(xy=pos, width=width, height=height, angle=theta, **kwargs)
    ax.add_artist(ellip)
    return ellip

最后,定义了一个函数 show_ellipse(),用于绘制样本点和置信椭圆。

'''画置信圆'''
def show_ellipse(X_pca, y, pca, flag=1):
    # 定义颜色
    colors = ['tab:blue', 'tab:orange', 'seagreen']
    regions = ['Ethiopia', 'Somalia', 'Kenya']

    # 定义分辨率
    plt.figure(dpi=300, figsize=(8, 6))
    # 三分类则为3
    for i in range(0, 3):
        pts = X_pca[y == int(i), :]
        new_x, new_y = X_pca[y==i, 0], X_pca[y==i, 1]

        plt.plot(new_x, new_y, '.', color=colors[i], label=regions[i], markersize=14)

        plot_point_cov(pts, nstd=3, alpha=0.25, color=colors[i])

    # 添加坐标轴
    plt.xlim(-3.5, 4.5)
    plt.ylim(-1.5, 1.7)
    plt.xticks(size=16, family='Times New Roman')
    plt.yticks(size=16, family='Times New Roman')
    font = {'family': 'Times New Roman', 'size': 16}
    plt.xlabel('PC1 ({} %)'.format(round(pca.explained_variance_ratio_[0] * 100, 2)), font)
    plt.ylabel('PC2 ({} %)'.format(round(pca.explained_variance_ratio_[1] * 100, 2)), font)

    plt.legend(prop={"family": "Times New Roman", "size": 9},  loc='upper right')
    plt.show()

以数据集鸢尾花为例进行PCA降维,并使用上面代码画置信圆。

import pandas as pd
from sklearn.decomposition import PCA
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
labels = ['setosa', 'versicolor', 'virginica']
iris = load_iris()
X = iris.data
y = iris.target_names[iris.target]

print("y length--------", len(y))
y_category = pd.Categorical(y,ordered=True,categories=['setosa', 'versicolor', 'virginica'])

y = y_category.codes
print(y)
print(y.shape)
print(type(y[0]))
n_components = 2
pca = PCA(n_components=n_components)
X_pca = pca.fit_transform(X)
show_ellipse(X_pca, y, pca)

 上面解析均为学习使用,如有问题请指正。

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

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

相关文章

Windows环境搭建Android开发环境-Android Studio/Git/JDK

Windows环境搭建Android开发环境-Android Studio/Git/JDK 因为休假回来后公司的开发环境由Ubuntu变为了Windows,所以需要重新配置一下开发环境。 工作多年第一次使用Windows环境进行开发工作,作次记录下来。 一、 Git安装 1.1git 标题软件下载 网址&…

CISA 告诉机构优先考虑什么以满足网络安全日志要求

随着联邦机构努力满足 2021 年发布的网络安全记录要求,政府的主要网络安全部门发布了一般指南,以帮助机构领导者优先考虑可能是昂贵且资源密集型实施的部分内容。 管理和预算办公室于 2021 年 8 月发布了一份备忘录,要求各机构创建和维护某些…

linux下nm,objdump和ldd三大工具使用

linux下进行C/C开发时经常需要使用nm&#xff0c;objdump&#xff0c;ldd工具来分析定位问题&#xff0c;本篇文章就对其做个总结&#xff1a; 1.测试程序 TestSo.h #pragma once #include <iostream>extern "C" int CTypeAdd(int x, int y); extern "…

关于Git分支高级合并的一些笔记整理

写在前面 分享一些 Git 高级合并的笔记博文为《Pro Git》读书笔记整理感谢开源这本书的作者和把这本书翻译为中文的大佬们理解不足小伙伴帮忙指正&#xff0c;书很不错&#xff0c;感兴趣小伙伴可以去拜读下 傍晚时分&#xff0c;你坐在屋檐下&#xff0c;看着天慢慢地黑下去&a…

传统图像处理方法实现车辆计数

本文通过传统OpenCV图像处理方法实现单向行驶的车辆计数。用于车辆检测的视频是在https://www.bilibili.com/video/BV1uS4y1v7qN/?spm_id_from333.337.search-card.all.click里面下载的。 思路一&#xff1a;来自B站某教程。大致是在视频中选取一窄长条区域&#xff0c;统计每…

【软件测试面试题】项目经验?资深测试 (分析+回答) 我不信你还拿不到offer......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 在面试过程中&#…

Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作

场景 Sqlite数据库 SQLite是一个进程内的库&#xff0c;实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。 它是一个零配置的数据库&#xff0c;这意味着与其他数据库不一样&#xff0c;您不需要在系统中配置。 就像其他数据库&#xff0c;SQLite 引擎不…

day03

文章目录一、盒子模型1. 基础概念2. 外边距3. 边框1) 边框实现2) 单边框设置3) 网页三角标制作4) 圆角边框5) 轮廓线2. 内边距3. 盒阴影4. 盒模型概念5. 标签最终尺寸的计算5. 标签最终尺寸的计算一、盒子模型 1. 基础概念 ​ 盒子模型分别由外边距、边框、内边距和标签内容组…

【Datawhale图机器学习】图神经网络的表示能力

图神经网络的表示能力 GNN理论 GNN有多强大 已经提出了许多GNN模型&#xff08;例如&#xff0c;GCN、GAT、GraphSAGE、设计空间&#xff09;。这些GNN模型的表达能力什么&#xff1f; 表达、学习、区分、拟合如何设计一个最具表现力的GNN模型 一个GNN层 多个GNN层 GNN…

在小公司工作3年,从事软件测试6年了,才发现自己还是处于“初级“水平,是不是该放弃....

金三银四面试季&#xff0c;相信大家都想好好把握住这次机会拿到心仪的offer&#xff0c;今天就给大家分享我面试经历及总结&#xff0c;文章最后我还会分享一些自己的面试经验还有面试宝典&#xff0c;希望对程序媛们和程序猿们都能有所帮助~ 市场分析 现在的市场环境确实不大…

基本系统性质

系统的记忆特性 定义&#xff1a;对任意的输入信号&#xff0c;如果每一个时刻系统的输出信号值仅取决于该时刻的输入信号值&#xff0c;这个系统就是无记忆系统 接下来请看一看下面那些是记忆系统&#xff0c;哪些是无记忆系统。 非常简单&#xff0c;只有第一个和最后一个是…

LeetCode202 快乐数

题目&#xff1a; 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a;对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 如果这个过程 结果…

vue 3.0组件(下)

文章目录前言&#xff1a;一&#xff0c;透传属性和事件1. 如何“透传属性和事件”2.如何禁止“透传属性和事件”3.多根元素的“透传属性和事件”4. 访问“透传属性和事件”二&#xff0c;插槽1. 什么是插槽2. 具名插槽3. 作用域插槽三&#xff0c;单文件组件CSS功能1. 组件作用…

css实现音乐播放器页面 · 笔记

效果 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, …

k8s 系列之 CoreDNS 解读

k8s 系列之 CoreDNS CoreDNS工作原理 kuberntes 中的 pod 基于 service 域名解析后&#xff0c;再负载均衡分发到 service 后端的各个 pod 服务中&#xff0c;如果没有 DNS 解析&#xff0c;则无法查到各个服务对应的 service 服务 在 Kubernetes 中&#xff0c;服务发现有几…

都2023年还不知道Java8如何优雅简化代码就落后了

1、使用 Stream 简化集合操作 Java8 Stream流操作总结_出世&入世的博客-CSDN博客 2、使用 Optional 简化判空逻辑 空指针异常&#xff08;NullPointerExceptions&#xff09;是 Java 最常见的异常之一&#xff0c;一直以来都困扰着 Java 程序员。一方面&#xff0c;程序…

springboot集成canal 实现mysql增量同步mongodb

一、canal官网https://kgithub.com/alibaba/canal/二、下载地址https://kgithub.com/alibaba/canal/releases三、细节1.6版本有bug&#xff08;如果只是部署deployer&#xff0c;那没问题&#xff0c;如果你想部署admin模块来监控&#xff0c;那就会报错&#xff1a;java.nio.B…

运算方法和运算电路

文章目录运算方法和运算电路基本运算部件定点数的移位运算算术移位逻辑移位循环移位定点数的加减运算原码的加减法补码的加减法原码的乘法补码的乘法原码的除法补码的除法符号扩展大小端和内存对齐刷题小结最后运算方法和运算电路 基本运算部件 运算器一般包含这么几部分&…

7 线性回归及Python实现

1 统计指标 随机变量XXX的理论平均值称为期望: μE(X)\mu E(X)μE(X)但现实中通常不知道μ\muμ, 因此使用已知样本来获取均值 X‾1n∑i1nXi.\overline{X} \frac{1}{n} \sum_{i 1}^n X_i. Xn1​i1∑n​Xi​.方差variance定义为&#xff1a; σ2E(∣X−μ∣2).\sigma^2 E(|…

STM32单片机的FLASH和RAM

STM32内置有Flash和RAM&#xff08;而RAM分为SRAM和DRAM&#xff0c;STM32内为SRAM&#xff09;&#xff0c;硬件上他们是不同的设备存储器、属于两个器件&#xff0c;但这两个存储器的寄存器输入输出端口被组织在同一个虚拟线性地址空间内。 MDK预处理、编译、汇编、链接后编…