【小技巧】机器学习中可视化高维向量的两种方法PCA和t-SNE,以及其原理介绍和代码示例(附代码)

news2024/11/27 8:47:10

使用情景:比如说现在我有一批numpy的多维向量,比如说都是256维度的,X.shape(n, 256), 已知它们都是经过训练能够在256dim的超球面上实现分类或聚类的,现在我想把它们可视化出来看看各个簇在超球面上的分布是怎样的?
在这里插入图片描述

1. 可视化方法介绍(附代码)

为了可视化高维数据(比如你的256维向量)在低维空间(通常是2D或3D)的分布,常用的方法包括主成分分析(PCA)和t-SNE。这两种方法可以帮助我们理解数据在高维空间中的内在结构。

下面,我会展示如何使用Python的scikit-learn库和matplotlib来可视化这些向量。我将使用PCA和t-SNE两种方法来降维,并在3D平面上展示结果。如果你有标签数据,这将有助于我们看到不同簇的分布。

首先,确保你已经安装了必要的库:

pip install numpy matplotlib scikit-learn plotly

下面是一个示例脚本,展示如何将你的高维数据可视化:

# -*- coding: utf8 -*-
import os
import numpy as np
import matplotlib.pyplot as plt
plt.switch_backend('agg')
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import plotly.graph_objects as go


def visualize_data_3d_interactive_v0(X, save_path, labels=None):
    """
	X: shape(num, dim)
	"""
    save_path = os.path.splitext(save_path)[0]
    
    # 使用PCA将数据降到3维
    print('PCA is processing ...')
    pca = PCA(n_components=3)
    X_pca = pca.fit_transform(X)
    
    # 使用t-SNE将数据降到3维
    print('t-SNE is processing ...')
    tsne = TSNE(n_components=3, perplexity=30, learning_rate=200)
    X_tsne = tsne.fit_transform(X)
    
    # 为PCA结果创建一个3D散点图
    fig_pca = go.Figure(data=[go.Scatter3d(
        x=X_pca[:, 0], y=X_pca[:, 1], z=X_pca[:, 2],
        mode='markers',
        marker=dict(
            size=5,
            color=labels,                # 设置颜色为标签
            opacity=0.8
        )
    )])
    fig_pca.update_layout(title='PCA Results', scene=dict(
                    xaxis_title='Component 1',
                    yaxis_title='Component 2',
                    zaxis_title='Component 3'))
    fig_pca.write_html(save_path + '_pca.html')
    
    # 为t-SNE结果创建一个3D散点图
    fig_tsne = go.Figure(data=[go.Scatter3d(
        x=X_tsne[:, 0], y=X_tsne[:, 1], z=X_tsne[:, 2],
        mode='markers',
        marker=dict(
            size=5,
            color=labels,                # 设置颜色为标签
            opacity=0.8
        )
    )])
    fig_tsne.update_layout(title='t-SNE Results', scene=dict(
                    xaxis_title='Component 1',
                    yaxis_title='Component 2',
                    zaxis_title='Component 3'))
    fig_tsne.write_html(save_path + '_tsne.html')


def visualize_data_3d_interactive_v1(data_dict, save_path):
    """
	版本不同:
	1.输入不同,data_dict是一个{cls: features};
	2.可视化功能差异,这个版本加入了对于不同cls显示不同颜色,并打上标签;
	"""

    save_path = os.path.splitext(save_path)[0]
    
    # 准备空列表来存储所有数据点和颜色
    all_data = []
    colors = []
    pid_index = 0  # 用于为每个pid分配不同的颜色
    texts = []  # 用于存储文本标签
    
    # 提取颜色映射
    color_palette = plt.cm.get_cmap('tab10', len(data_dict))
    
    # 将每个pid的数据点收集到一起,并为第一个特征添加标签
    for pid, features in data_dict.items():
        all_data.append(features)
        colors.extend([color_palette(pid_index)] * features.shape[0])
        # 初始化所有文本为空,除了第一个特征
        texts.extend([""] * features.shape[0])
        texts[len(texts) - features.shape[0]] = pid  # 为第一个特征设置pid标签
        pid_index += 1
    
    # 将所有数据合并成一个大矩阵
    all_data = np.vstack(all_data)
    
    # 使用PCA将数据降到3维
    print('PCA is processing ...')
    pca = PCA(n_components=3)
    X_pca = pca.fit_transform(all_data)
    
    # 使用t-SNE将数据降到3维
    print('t-SNE is processing ...')
    tsne = TSNE(n_components=3, perplexity=30, learning_rate=200)
    X_tsne = tsne.fit_transform(all_data)
    
    # 创建一个3D散点图显示PCA结果
    fig_pca = go.Figure(data=[go.Scatter3d(
        x=X_pca[:, 0], y=X_pca[:, 1], z=X_pca[:, 2],
        mode='markers+text',
        text=texts,
        marker=dict(
            size=5,
            color=['rgb({}, {}, {})'.format(c[0]*255, c[1]*255, c[2]*255) for c in colors],  # 将颜色转换为plotly格式
            opacity=0.8
        )
    )])
    fig_pca.update_layout(title='PCA Results', scene=dict(
        xaxis_title='Component 1',
        yaxis_title='Component 2',
        zaxis_title='Component 3'))
    fig_pca.write_html(save_path + '_pca.html')
    
    # 创建一个3D散点图显示t-SNE结果
    fig_tsne = go.Figure(data=[go.Scatter3d(
        x=X_tsne[:, 0], y=X_tsne[:, 1], z=X_tsne[:, 2],
        mode='markers+text',
        text=texts,
        marker=dict(
            size=5,
            color=['rgb({}, {}, {})'.format(c[0]*255, c[1]*255, c[2]*255) for c in colors],  # 将颜色转换为plotly格式
            opacity=0.8
        )
    )])
    fig_tsne.update_layout(title='t-SNE Results', scene=dict(
        xaxis_title='Component 1',
        yaxis_title='Component 2',
        zaxis_title='Component 3'))
    fig_tsne.write_html(save_path + '_tsne.html')



if __name__ == '__main__':
    # test v0
    data_np = np.random.rand(100, 256)
    visualize_data_3d_interactive_v0(data_np, 'outputs/vis_hdim_vector_interactive_v0.html')

    # test v1
    data_dict = {
        'class1': np.random.randn(100, 50),   # 100个50维的样本
        'class2': np.random.randn(100, 50),   # 另外100个50维的样本
        'class3': np.random.randn(100, 50),   # 另外100个50维的样本
        'class4': np.random.randn(100, 50),   # 另外100个50维的样本
        'class5': np.random.randn(100, 50),   # 另外100个50维的样本
        'class6': np.random.randn(100, 50),   # 另外100个50维的样本
        'class7': np.random.randn(100, 50),   # 另外100个50维的样本
        'class8': np.random.randn(100, 50),   # 另外100个50维的样本
        'class9': np.random.randn(100, 50),   # 另外100个50维的样本
        'class10': np.random.randn(100, 50)   # 另外100个50维的样本
    }

    visualize_data_3d_interactive_v1(data_dict, 'outputs/vis_hdim_vector_interactive_v1.html')

在这个脚本中,你需要替换X为你实际的数据。

PCA通常用于获取数据的主要方向,而t-SNE更擅长在保持局部结构的同时展示数据的簇状分布。视觉效果上,t-SNE可能更适合展示复杂的簇结构,但它的计算成本通常也更高。

2. t-SNE 原理

t-SNE(t-Distributed Stochastic Neighbor Embedding)是一种非常流行的机器学习算法,主要用于高维数据的可视化。它由Laurens van der Maaten和Geoffrey Hinton在2008年提出。t-SNE的核心优势在于它能够有效地在二维或三维空间中展示高维数据的局部结构,使得类似的数据点在低维空间中彼此靠近,而不相似的数据点则远离。这使t-SNE特别适用于高维数据的聚类分析和可视化。

t-SNE的工作原理

t-SNE的工作过程可以分为以下几个关键步骤:

  1. 计算高维空间中的相似性
    t-SNE首先在高维空间中计算每对数据点间的条件概率,这种概率反映了一个点选择另一个点作为其邻居的可能性。这个概率由高斯分布(正态分布)的相似性函数决定,其中中心点是数据点本身。

  2. 计算低维空间中的相似性
    对于映射到低维空间中的数据点,t-SNE使用了一个长尾分布——具体来说是t分布(自由度为1的学生t分布,形状类似柯西分布),来计算低维空间中点之间的相似性。使用长尾分布是为了解决所谓的“拥挤问题”(crowding problem),即在低维空间中很难准确地表示原高维空间中的距离关系。

  3. 最小化Kullback-Leibler散度
    t-SNE的目标是使得两个空间(高维和低维)中的概率分布尽可能相似。为此,它通过最小化高维空间与低维空间中定义的概率分布之间的Kullback-Leibler散度来调整低维空间中的点。Kullback-Leibler散度是一种衡量两个概率分布差异的方法。

  4. 梯度下降
    t-SNE使用梯度下降法来找到低维空间的最优配置,以最小化Kullback-Leibler散度。这一步通常需要多次迭代,且对初始值和超参数(如学习率和困惑度)比较敏感。

t-SNE的使用注意事项

  • 困惑度(Perplexity)
    困惑度是t-SNE中的一个重要参数,反映了考虑的邻居的数量,并且对结果有显著影响。一般需要通过试验来选择最合适的困惑度值。

  • 随机性
    由于梯度下降的初始点是随机选择的,t-SNE的结果可能每次都略有不同。为了得到可重复的结果,需要固定随机种子。

  • 计算成本
    t-SNE的计算成本随着数据量的增加而显著增加,特别是对于非常大的数据集,可能需要较长的计算时间。

t-SNE是一个非常强大的工具,特别是在探索性数据分析和数据可视化方面。然而,正确地使用t-SNE需要对其参数和数据特性有一定的理解。

3. PCA 原理

主成分分析(PCA,Principal Component Analysis)是一种广泛使用的统计技术,用于数据降维和探索性数据分析。通过PCA,可以从多维数据集中提取出关键信息,并且以维数更少的数据集形式呈现,这种转换是通过保留数据的最大方差来实现的。

PCA的工作原理

  1. 标准化数据
    首先,通常需要将数据进行标准化处理,即对每个特征维度进行中心化(减去均值)和缩放(除以标准差),以使各特征具有相同的重要性。

  2. 计算协方差矩阵
    然后,计算数据的协方差矩阵。协方差矩阵描述了数据中各个变量之间的相关性;在这个矩阵中,每个元素是对应两个变量的协方差,它反映了两个变量变化时是如何相互影响的。

  3. 求解特征值和特征向量
    对协方差矩阵进行特征值分解,求得的特征值和对应的特征向量指示了数据的主要变化方向。特征值越大,对应的特征向量在数据集中的重要性就越高,这个特征向量定义了一个主成分。

  4. 选择主成分
    选择最大的几个特征值及其对应的特征向量。通常,这些特征向量被称为“主成分”,它们是新的、较少的、互相正交的坐标轴,这些坐标轴是按照它们能够捕捉的数据方差的重要性排序的。

  5. 构造新的特征空间
    将原始数据投影到这些选定的主成分上,得到的就是降维后的数据。这一步通常涉及到一个矩阵乘法运算,原始数据矩阵乘以选定的主成分矩阵。

PCA的应用

  • 数据压缩:通过减少数据集的维数,PCA有助于减少存储空间和提高算法效率。
  • 去噪:PCA可以帮助识别并去除数据中的噪声,特别是当噪声较小且数据的主要结构在高方差的方向时。
  • 可视化:在多维数据集中,通过PCA可以将数据降到两维或三维,使得数据可通过图形化方式展示。

注意事项

虽然PCA是一个强大的工具,但它也有局限性。由于PCA是基于线性假设的,它可能无法有效识别基于非线性结构的复杂模式。此外,如果所有变量的方差都差不多,PCA的效果可能就不明显。在这些情况下,可能需要考虑使用其他的降维技术,如t-SNE、LDA(线性判别分析)或者基于核的PCA方法。

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

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

相关文章

C++的stack和queue类(三):适配所有容器的反向迭代器

目录 前言 list的反向迭代器 list.h文件 ReverseIterator.h文件 test.cpp文件 前言 迭代器按性质分类: 单向:forward_list双向:list随机:vector / deque 迭代器按功能分类: 正向反向const list的反向迭代器…

抽象工厂模式:深入探索面向对象设计的多样性

在软件开发中,正确地应用设计模式对于构建可扩展、可维护和高效的系统至关重要。抽象工厂模式作为创建型设计模式之一,提供了一个高层接口,用于创建一系列相关或依赖对象,而无需指定它们具体的类。本文将详细介绍抽象工厂模式的概…

【虚幻引擎】DTProjectSettings 蓝图获取基本项目配置插件使用说明 获取项目命名,项目版本,公司名,公司识别名,主页,联系方式

本插件可以使用蓝图获取到项目的一些基本配置,如获取:公司名、公司识别名、版权声明、描述、主页、许可条款、隐私政策、项目ID、项目命名、项目版本、支持联系方式、项目显示标题、项目调试标题信息、应保留窗口宽高比、使用无边框窗口、以VR启动、允许…

ASP.NET MVC企业级程序设计 (EF+MVP实现显示数据)

效果图 实现过程 1创建数据库 2创建项目文件 3创建控制器,右键添加,控制器 注意这里要写Home 创建成功 数据模型创建过程之前作品有具体过程 4创建视图,右键添加视图 5HomeController.cs代码 using System; using System.Collections.Gene…

JVM修炼之路【11】- 解决内存溢出、内存泄漏 以及相关案例

前面的10篇 都是基础的知识,包括类加载的过程 类加载的细节,jvm内存模型 垃圾回收 等等, 这一篇我们开始实战了解一下 各种疑难杂症:怎么监控 怎么发现 怎么解决 内存溢出 内存泄漏 这两个概念在垃圾回收器里面已经讲过了&#…

视频秒播优化实践

本文字数:2259字 预计阅读时间:10分钟 视频起播时间,即首帧时间,是视频类应用的一个重要核心指标,也是影响用户观看体验的核心因素之一。如果视频要加载很久才能开始播放,用户放弃播放甚至离开 App 的概率都…

React + three.js 实现人脸动捕与3D模型表情同步

系列文章目录 React 使用 three.js 加载 gltf 3D模型 | three.js 入门React three.js 3D模型骨骼绑定React three.js 3D模型面部表情控制React three.js 实现人脸动捕与3D模型表情同步 示例项目(github):https://github.com/couchette/simple-react-three-facia…

【Godot4自学手册】第三十六节圆形移动或扇形移动的铁球

在第三十四节我实现了来回无限滚动的伤害铁刺球,这一节我准备实现一个圆形移动或扇形移动,并带有链条的铁球。效果如下: 一、实现原理 绕一点做圆周运动,简单的说就是: 每一帧根据旋转的角度计算出下一个位置的坐标…

R语言绘图:绘制横向柱状图

代码主要实现&#xff1a; 对数据进行排序&#xff0c;并且相同分组的数据会有相同的颜色。最后&#xff0c;绘制横向柱状图。 # 加载ggplot2包 library(ggplot2)# 示例数据&#xff0c;假设有三列&#xff1a;Group, Variable, Value data <- data.frame(Group factor(c(…

植被参数光学遥感反演方法(Python)及遥感与生态模型数据同化算法

传统的地面实测方法能够得到比较准确的植被参数&#xff08;如叶面积指数、覆盖度、生物量、叶绿素、干物质、叶片含水量、FPAR等&#xff09;&#xff0c;但其获取信息有限&#xff0c;难以满足大范围提取植被参数的需求&#xff0c;尤其在异质地表区域。遥感技术的发展为植被…

【PythonCode】力扣Leetcode11~15题Python版

【PythonCode】力扣Leetcode11~15题Python版 前言 力扣Leetcode是一个集学习、刷题、竞赛等功能于一体的编程学习平台&#xff0c;很多计算机相关专业的学生、编程自学者、IT从业者在上面学习和刷题。 在Leetcode上刷题&#xff0c;可以选择各种主流的编程语言&#xff0c;如C…

316_C++_xml文件解析成map,可以放到表格上 + xml、xlsx文件互相解析

xml文件例如&#xff1a; <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <TrTable> <tr id"0" label"TR_PB_CH" text"CH%2"/> <tr id"4" label"TR_PB_CHN"…

[BT]BUUCTF刷题第16天(4.12)

第16天 Web [MRCTF2020]Ezpop 打开网站就是一段泄露的源代码&#xff1a; <?php //flag is in flag.php //WTF IS THIS? //Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95 //And Crack…

Ollama、FastGPT大模型RAG结合使用案例

参考: https://ollama.com/download/linux https://doc.fastai.site/docs/intro/ https://blog.csdn.net/m0_71142057/article/details/136738997 https://doc.fastgpt.run/docs/development/custom-models/m3e/ Ollama作为后端大模型加载运行 FastGPT作为前端页面聊天集成RA…

Linux函数学习 select

1、Linux select 函数 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); nfds 最大文件fd 1 readfds 监听可读文件集合fd writefds 监听可写文件集合fd exceptfd 监听异常文件集…

[蓝桥杯] 岛屿个数(C语言)

提示&#xff1a; 橙色字体为需要注意部分&#xff0c;红色字体为难点部分&#xff0c;会在文章“重难点解答”部分精讲。 题目链接 蓝桥杯2023年第十四届省赛真题-岛屿个数 - C语言网 题目理解 这道题让我们求岛屿个数&#xff0c;那么我们就应该先弄懂&#xff0c;对于一…

R: 支持向量机(Support Vector Machine,简称SVM)

在数据科学和机器学习领域中&#xff0c;支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是一种强大的监督学习算法&#xff0c;常用于分类和回归分析。它的优点之一是可以适用于复杂的数据集&#xff0c;并且在高维空间中表现良好。在本文中&am…

SpringBoot3 + Vue3 + Uniapp + uView + Elenment 实现动态二级分类以及二级分类的管理

SpringBoot3 Vue3 Uniapp uView Elenment 实现动态二级分类以及二级分类的管理 1. 效果展示1.1 前端显示效果1.2 后台管理一级分类1.3 后台管理二级分类 2. 后端代码2.1 GoodsCategoryController.java2.2.1 GoodsCategoryMapper.java2.2.2 GoodsCategorySonMapper.java2.3.…

蓝桥杯备赛(C/C++组)

README&#xff1a; 本笔记是自己的备考笔记&#xff0c;按照官网提纲进行复习&#xff01;适合有基础&#xff0c;复习用。 一、总考点 试题考查选手解决实际问题的能力&#xff0c;对于结果填空题&#xff0c;选手可以使用手算、软件、编程等方法解决&#xff0c;对于编程大…

Laravel 11入门:使用ServBay打造高效开发环境

Laravel 11发布&#xff0c;改进了不少功能。 它引入了更加流畅的应用结构、每秒限速、健康路由等特性。 此外&#xff0c;Laravel还推出了第一方可扩展的WebSocket服务器Laravel Reverb&#xff0c;为你的应用提供强大的实时功能。 在今天的指南中&#xff0c;我将设置一个…