t-SNE可视化-Python实现

本文介绍了t-Distributed Stochastic Neighbor Embedding (t-SNE)这一无监督的非线性降维技术,用于高维数据的可视化。t-SNE与PCA的主要区别在于其能更好地保留局部相似性,适合处理非线性结构。通过Python的sklearn库展示了t-SNE的实现,并给出了手写数字数据集的可视化示例。文章还探讨了t-SNE的原理,包括高维和低维空间中相似性的计算以及Kullback-Leibler散度的成本函数。此外,提供了两种不同风格的可视化结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

t-SNE

本文主要是对An Introduction to t-SNE with Python Example博客的翻译记录,和一些入门的Python代码,可以的话推荐阅读原文。

主要参考

介绍:
An Introduction to t-SNE with Python Example
GitHub:
sas-python-work/tSneExampleBlogPost.ipynb
t-SNE-tutorial
tSNE
tsne-pytorch
PintheMemory/tsnelib.py
加速包:
Multicore-TSNE
tsne-cuda

t-SNE介绍

t-Distributed Stochastic Neighbor Embedding (t-SNE) 是一种无监督的非线性技术,主要用于数据探索和高维数据的可视化。 简单来说,t-SNE 让您对数据在高维空间中的排列方式有一种感觉或直觉。 它由 Laurens van der Maatens 和 Geoffrey Hinton 于 2008 年开发。

简单来说就是高维数据可视化,目的是观察高维数据的之间的分布情况

t-SNE与PCA的区别

首先要注意的是,PCA 是在 1933 年开发的,而 t-SNE 是在 2008 年开发的。自 1933 年以来,数据科学领域发生了很大变化,主要是在计算和数据大小方面。 其次,PCA 是一种线性降维技术,旨在最大化方差并保持较大的成对距离。 换句话说,不同的事物最终会相距甚远。 这会导致可视化效果不佳,尤其是在处理非线性流形结构时。 将流形结构视为任何几何形状,例如:圆柱体、球体、曲线等。
t-SNE 与 PCA 的不同之处在于仅保留小的成对距离或局部相似性,而 PCA 关注的是保留大的成对距离以最大化方差。 Laurens 使用图 1 [1] 中的 Swiss Roll 数据集很好地说明了 PCA 和 t-SNE 方法。 您可以看到,由于这个玩具数据集(流形)的非线性和保留较大的距离,PCA 会错误地保留数据的结构。

PCA的可视化我也写了一个单独的博客,可以参考:网络特征之PCA可视化-Python实现

t-SNE原理

t-SNE 算法计算高维空间和低维空间中实例对之间的相似性度量。 然后,它尝试使用成本函数优化这两个相似性度量。 让我们将其分解为 3 个基本步骤:

  1. 第一步,测量高维空间中点之间的相似度。 想想散布在二维空间上的一堆数据点(图 2)。 对于每个数据点 (xi),我们将在该点上以高斯分布为中心。 然后我们测量该高斯分布下所有点 (xj) 的密度。 然后对所有点重新归一化。 这为我们提供了所有点的一组概率 (Pij)。 这些概率与相似性成正比。 这意味着,如果数据点 x1 和 x2 在这个高斯圆下具有相等的值,那么它们的比例和相似性是相等的,因此它们在这个高维空间的结构中具有局部相似性。 高斯分布或圆可以使用所谓的 perplexity 来操纵,它会影响分布的方差(圆的大小)以及最近邻的数量。 perplexity 的正常范围在 5 到 50 之间 [2]。
  2. 第 2 步与第 1 步类似,但不是使用高斯分布,而是使用具有一个自由度的学生 t 分布,也称为柯西分布(图 3)。 这为我们提供了低维空间中的第二组概率(Qij)。 如图所示,学生 t 分布的尾部比正态分布更重。 厚重的尾巴可以更好地模拟远距离。
  3. 最后一步是我们希望这些来自低维空间 (Qij) 的概率集尽可能地反映高维空间 (Pij) 的概率。 我们希望这两个地图结构相似。 我们使用 Kullback-Liebler 散度 (KL) 测量二维空间的概率分布之间的差异。最后,我们使用梯度下降来最小化我们的 KL 成本函数。

t-SNE的Python实现

入门例子

import numpy as np

from sklearn.manifold import TSNE
# For the UCI ML handwritten digits dataset
from sklearn.datasets import load_digits

# Import matplotlib for plotting graphs ans seaborn for attractive graphics.
import matplotlib.pyplot as plt
import matplotlib.patheffects as pe
import seaborn as sns

def plot(x, colors):
    # Choosing color palette
    # https://seaborn.pydata.org/generated/seaborn.color_palette.html
    palette = np.array(sns.color_palette("pastel", 10))
    # pastel, husl, and so on

    # Create a scatter plot.
    f = plt.figure(figsize=(8, 8))
    ax = plt.subplot(aspect='equal')
    sc = ax.scatter(x[:,0], x[:,1], lw=0, s=40, c=palette[colors.astype(np.int8)])
    # Add the labels for each digit.
    txts = []
    for i in range(10):
        # Position of each label.
        xtext, ytext = np.median(x[colors == i, :], axis=0)
        txt = ax.text(xtext, ytext, str(i), fontsize=24)
        txt.set_path_effects([pe.Stroke(linewidth=5, foreground="w"), pe.Normal()])
        txts.append(txt)
    plt.savefig('./digits_tsne-pastel.png', dpi=120)
    return f, ax, txts


digits = load_digits()
print(digits.data.shape)
# There are 10 classes (0 to 9) with alomst 180 images in each class 
# The images are 8x8 and hence 64 pixels(dimensions)

# Place the arrays of data of each digit on top of each other and store in X
X = np.vstack([digits.data[digits.target==i] for i in range(10)])
# Place the arrays of data of each target digit by the side of each other continuosly and store in Y
Y = np.hstack([digits.target[digits.target==i] for i in range(10)])

# Implementing the TSNE Function - ah Scikit learn makes it so easy!
digits_final = TSNE(perplexity=30).fit_transform(X) 
# Play around with varying the parameters like perplexity, random_state to get different plots

plot(digits_final, Y)

生成的图片(分别是husl风格和pastel风格,每次运行结果不一样):
在这里插入图片描述
在这里插入图片描述
在前面的基础上换一种可视化风格:

def plot2(data, x='x', y='y'):
    sns.set_context("notebook", font_scale=1.1)
    sns.set_style("ticks")

    sns.lmplot(x=x,
            y=y,
            data=data,
            fit_reg=False,
            legend=True,
            height=9,
            hue='Label',
            scatter_kws={"s":200, "alpha":0.3})

    plt.title('t-SNE Results: Digits', weight='bold').set_fontsize('14')
    plt.xlabel(x, weight='bold').set_fontsize('10')
    plt.ylabel(y, weight='bold').set_fontsize('10')
    plt.savefig('./digits_tsne-plot2.png', dpi=120)

import pandas as pd
data = {'x': digits_final[:, 0],
        'y': digits_final[:, 1],
        'Label': Y}
data = pd.DataFrame(data)
plot2(data)

生成的图片:
在这里插入图片描述

高级例子

由于篇幅的原因,分割网络模型的t-SNE可视化放在了新的博客上:
用于语义分割模型的t-SNE可视化
欢迎大家留言讨论,谢谢

### T-SNE 可视化用于跨模态行人重识别 T-Distributed Stochastic Neighbor Embedding (t-SNE) 是一种广泛应用于高维数据可视化的技术,能够有效地将多维度的数据映射到二维或三维空间中以便于观察和理解。对于跨模态行人重识别而言,t-SNE 能够帮助研究人员直观地分析不同特征表示方法的效果以及模型学习到的嵌入空间特性。 #### 数据准备与预处理 为了实现有效的 t-SNE 可视化,在应用此算法之前通常需要先提取图像中的深层特征向量作为输入。这些特征可以来自于卷积神经网络的最后一层全连接层或其他专门设计的人体描述符。此外,还需要确保来自不同传感器(如可见光摄像头和红外线摄像头)采集到的数据经过标准化处理以消除差异[^1]。 #### 实现过程 下面是一个简单的 Python 代码片段展示如何利用 scikit-learn 库来执行基于 t-SNE 的降维并绘制散点图: ```python import numpy as np from sklearn.manifold import TSNE import matplotlib.pyplot as plt def visualize_tsne(features, labels): tsne = TSNE(n_components=2).fit_transform(features) fig = plt.figure(figsize=(8, 8)) unique_labels = set(labels) colors = plt.cm.rainbow(np.linspace(0, 1, len(unique_labels))) for i, label in enumerate(unique_labels): mask = [l == label for l in labels] plt.scatter(tsne[mask][:, 0], tsne[mask][:, 1], c=[colors[i]], label=f'ID {label}') plt.legend() plt.show() # 假设 features 和 labels 已经准备好 visualize_tsne(features, labels) ``` 通过上述代码,可以看到每个样本被投影到了二维平面上,并按照其所属的身份类别进行了着色标记。这有助于评估所使用的特征表达能力及其区分度。 #### 结果解释 当查看由 t-SNE 产生的图表时,如果同一身份的不同视角下的图片聚集在一起,则说明该特征具有良好的不变性和辨别力;反之则可能意味着当前的方法未能充分捕捉个体之间的细微差别或者存在其他问题待解决。
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深山里的小白羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值