24/11/8 算法笔记 t-SNE降维算法

t-SNE算法的核心实现涉及几个关键步骤,主要包括概率分布的构建、梯度计算和优化。以下是这些步骤的简要说明:

1. **概率分布的构建**:
   - 在高维空间中,t-SNE使用高斯分布(Gaussian distribution)来构建概率分布,表示样本点之间的相似度。在低维空间中,使用学生t分布(Student's t-distribution)。
   - 通过计算高维空间中所有点对之间的欧氏距离,然后使用这些距离来计算高斯概率分布,即联合概率矩阵P。

2. **KL散度(Kullback-Leibler divergence)**:
   - t-SNE的目标是最小化高维空间和低维空间概率分布之间的KL散度,以此来保持高维空间中的局部结构。
   - KL散度是衡量两个概率分布差异的指标,t-SNE通过最小化这个值来优化低维空间中点的布局。

3. **梯度计算**:
   - 为了最小化KL散度,t-SNE需要计算梯度(gradient),这是通过反向传播算法完成的。
   - 梯度计算涉及到对高维和低维概率分布的微分,以及对嵌入空间坐标的微分。

4. **优化(梯度下降)**:
   - 使用梯度下降算法来更新低维空间中点的位置,以最小化KL散度。
   - t-SNE有两种优化阶段:一种是带有早期夸张(early exaggeration)的优化,以鼓励簇之间的更大分离;另一种是标准的梯度下降,用于细化结果。

5. **动量和学习率调整**:
   - 在优化过程中,t-SNE使用动量(momentum)来帮助逃离局部最小值,并调整学习率以控制优化步长。

6. **早期夸张和学习率衰减**:
   - 在早期夸张阶段,学习率会逐渐减小,以允许在优化的后期阶段进行更细致的调整。
 

高斯分布就是正态分布,这里我就不讲了。

我们来看一下学生分布:

学生t分布(Student's t-distribution)的原理基于以下统计学概念和假设:

  1. 正态分布样本的样本均值: 当从一个正态分布的总体中随机抽取样本时,样本均值的分布也是正态分布的。这是中心极限定理的一个特例。

  2. 样本标准差: 样本的标准差(S)是总体标准差(σ)的一个估计。当总体标准差未知时,我们使用样本标准差来估计它。

  3. 自由度: 在统计学中,自由度(df)是指在估计统计量时,数据中可以自由变动的值的数量。对于样本方差,自由度通常是样本大小减一(n-1),因为样本均值的计算限制了数据的一个自由度。

  4. t统计量: t统计量是通过将样本均值与总体均值的差除以样本标准差(除以样本大小的平方根)来计算的。数学上,如果X1, X2, ..., Xn是从均值为μ、方差为σ^2的正态分布中抽取的样本,则t统计量定义为: t=​ 其中,Xˉ是样本均值,μ是总体均值,S是样本标准差,n是样本大小。

  5. t分布的形成: 当总体标准差σ未知且用样本标准差S代替时,t统计量的分布就是学生t分布。这个分布的形状取决于自由度(n-1),随着自由度的增加,t分布越来越接近标准正态分布。

  6. t分布的特性

    • t分布是对称的,并且以0为中心。
    • 与标准正态分布相比,t分布的尾部更重,这意味着它更有可能产生极端值。
    • 当自由度增加时,t分布的形状越来越接近标准正态分布。

接下来我们来解析一下简化后的t-SNE源代码

import numpy as np
from scipy.spatial.distance import pdist, squareform
from sklearn.decomposition import PCA
from sklearn.utils import check_random_state
from sklearn.neighbors import NearestNeighbors

def _joint_probabilities(distances, desired_perplexity, verbose):
    distances = distances.astype(np.float32)
    conditional_P = np.exp(-distances ** 2 / (2 * desired_perplexity ** 2))
    sum_P = np.sum(conditional_P)
    P = conditional_P / sum_P
    return P

def _kl_divergence(P, X_embedded, degrees_of_freedom):
    dist = pdist(X_embedded, "sqeuclidean")
    Q = np.maximum(1 + dist, 1e-15) ** (-1 * dist)
    kl_divergence = np.sum(P * np.log(P / Q))
    return kl_divergence

def _gradient_descent(kl_divergence_grad, X_embedded, learning_rate, momentum):
    update = momentum * update - learning_rate * kl_divergence_grad
    X_embedded += update
    return X_embedded

class TSNE:
    def __init__(self, n_components=2, perplexity=30.0, learning_rate=200.0):
        self.n_components = n_components
        self.perplexity = perplexity
        self.learning_rate = learning_rate

    def fit_transform(self, X):
        n_samples = X.shape[0]
        distances = pdist(X, "euclidean")
        P = _joint_probabilities(distances, self.perplexity, 0)

        pca = PCA(n_components=self.n_components)
        X_embedded = pca.fit_transform(X)

        degrees_of_freedom = self.n_components - 1
        kl_divergence_grad = None  # Initialize gradient

        for _ in range(1000):  # Max iterations
            dist = pdist(X_embedded, "sqeuclidean")
            Q = np.maximum(1 + dist, 1e-15) ** (-1 * dist)
            kl_divergence_grad = 4 * (P - Q) * (1 + dist) ** (-1)
            kl_divergence_grad = kl_divergence_grad[:, np.newaxis] * (X_embedded[:, np.newaxis] - X_embedded[np.newaxis, :])
            kl_divergence_grad = kl_divergence_grad.ravel()

            X_embedded = _gradient_descent(kl_divergence_grad, X_embedded, self.learning_rate, 0.8)
            kl_divergence = _kl_divergence(P, X_embedded, degrees_of_freedom)

        return X_embedded

# Example usage
X = np.array([[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]])
tsne = TSNE(n_components=2, perplexity=3)
X_embedded = tsne.fit_transform(X)
print(X_embedded.shape)

1.导入依赖

import numpy as np
from scipy.spatial.distance import pdist, squareform
from sklearn.decomposition import PCA
from sklearn.utils import check_random_state
from sklearn.neighbors import NearestNeighbors

可以看见这边导入了PCA,主成分分析,我们先来了解一下24/11/7 算法笔记 PCA主成分分析-CSDN博客

2.定义计算联合函数

def _joint_probabilities(distances, desired_perplexity, verbose):
    distances = distances.astype(np.float32)
    conditional_P = np.exp(-distances ** 2 / (2 * desired_perplexity ** 2))
    sum_P = np.sum(conditional_P)
    P = conditional_P / sum_P
    return P

3.定义计算KL散度的函数_kl_divergence

def _kl_divergence(P, X_embedded, degrees_of_freedom):
    dist = pdist(X_embedded, "sqeuclidean")
    Q = np.maximum(1 + dist, 1e-15) ** (-1 * dist)
    kl_divergence = np.sum(P * np.log(P / Q))
    return kl_divergence

这行代码使用了scipy.spatial.distance.pdist函数来计算X_embedded数组中所有点之间的平方欧几里得距离。对于两个点 x 和 y,它们的平方欧几里得距离 d计算公式为:

其中 n 是点的维度数,xi 和 yi​ 分别是点 x 和 y 在第 i 维的坐标。

在t-SNE算法中,这个距离度量用于计算低维空间中点之间的相似度,进而构建概率分布Q,这是优化过程的一部分,目的是使得低维空间中的概率分布 Q 尽可能地接近高维空间中的概率分布 P。通过最小化 P 和 Q 之间的KL散度来实现这一目标。

4.定义梯度下降的函数_gradient_descent

def _gradient_descent(kl_divergence_grad,X_embedded, learning_rate, momentum):
     
    update = momentum * update - learning_rate * kl_divergence_grad
    
    X_embedded += update
    
    return X_embedded 

5.定义t-SNE类的TSNE

class TSNE:
    def __init__(self, n_components=2, perplexity=30.0, learning_rate=200.0):
        self.n_components = n_components
        self.perplexity = perplexity
        self.learning_rate = learning_rate

这个类初始化t-SNE算法的参数,包括降维后的成分数、困惑度(perplexity)和学习率。

6.  定义fit_transform方法:

def fit_transform(self, X):
    n_samples = X.shape[0]
    distances = pdist(X, "euclidean")
    P = _joint_probabilities(distances, self.perplexity, 0)

    pca = PCA(n_components=self.n_components)
    X_embedded = pca.fit_transform(X)

    degrees_of_freedom = self.n_components - 1
    kl_divergence_grad = None  # Initialize gradient

    for _ in range(1000):  # Max iterations
        dist = pdist(X_embedded, "sqeuclidean")
        Q = np.maximum(1 + dist, 1e-15) ** (-1 * dist)
        #计算KL散度的梯度,并将其展平为一维数组,以便用于梯度下降。
        kl_divergence_grad = 4 * (P - Q) * (1 + dist) ** (-1)
        kl_divergence_grad = kl_divergence_grad[:, np.newaxis] * (X_embedded[:, np.newaxis] - X_embedded[np.newaxis, :])
        kl_divergence_grad = kl_divergence_grad.ravel()
        #执行梯度下降
        X_embedded = _gradient_descent(kl_divergence_grad, X_embedded, self.learning_rate, 0.8)
        #计算KL散度:
        kl_divergence = _kl_divergence(P, X_embedded, degrees_of_freedom)

    return X_embedded

这个方法执行t-SNE算法的主要步骤:计算高维空间中的联合概率、执行PCA降维、初始化梯度、执行梯度下降优化,并返回最终的低维嵌入结果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业微信-消息推送之微信客服-接收消息和事件

一:企微实现和企业间的微信客服消息接收和事件原理 新版企微主要通过2个阶段实,第一个:消息推送 概述 - 文档 - 企业微信开发者中心 ,第二个:微信客服 接收消息和事件 - 文档 - 企业微信开发者中心 二:代码…

Ascend Extension for PyTorch是个what?

1 Ascend Extension for PyTorch Ascend Extension for PyTorch 插件是基于昇腾的深度学习适配框架,使昇腾NPU可以支持PyTorch框架,为PyTorch框架的使用者提供昇腾AI处理器的超强算力。 项目源码地址请参见Ascend/Pytorch。 昇腾为基于昇腾处理器和软…

【React】React 生命周期完全指南

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 React 生命周期完全指南一、生命周期概述二、生命周期的三个阶段2.1 挂载阶段&a…

开源模型应用落地-glm模型小试-glm-4-9b-chat-压力测试(六)

一、前言 GLM-4是智谱AI团队于2024年1月16日发布的基座大模型,旨在自动理解和规划用户的复杂指令,并能调用网页浏览器。其功能包括数据分析、图表创建、PPT生成等,支持128K的上下文窗口,使其在长文本处理和精度召回方面表现优异&a…

程序开发时单数复数及前缀的命名规范(目录名、文件名、函数名、变量名、数据库字段等)

在程序开发中,我总是被单复数搞得头疼,以前采用了最舒服的方法,一刀切:全部单数,因为理由也很简单,单数都可以作为定语解释,比如/util,可以认为真正的名称是/util files或者/util di…

Spring Boot原理全解析:如何让开发更轻松高效(二)-起步依赖、自动装配

通过这篇博客,读者将能够掌握 Spring Boot 中的配置优先级和 Bean 管理的核心原理,为开发更加高效、可维护的 Spring Boot 应用打下坚实的基础。 目录 前言 起步依赖 自动配置 概述 常见方案 概述 方案一 方案二 总结 前言 通过这篇博客&#xf…

力扣动态规划基础版(矩阵型)

62.不同路径(唯一路径问题) 62. 不同路径https://leetcode.cn/problems/unique-paths/ 方法一:动态规划 找状态转移方程,也就是说它从左上角走到右下角,只能往右或者往下走,那么设置一个位置为&#xff…

Ubuntu 22 安装 Apache Doris 3.0.3 笔记

Ubuntu 22 安装 Apache Doris 3.0.3 笔记 1. 环境准备 Doris 需要 Java 17 作为运行环境,所以首先需要安装 Java 17。 sudo apt-get install openjdk-17-jdk -y sudo update-alternatives --config java在安装 Java 17 后,可以通过 sudo update-alter…

141/142题环形链表

本题返回环入口的位置。使用快慢指针,快指针每次移动两个,慢指针每次移动一个。设前一段距离是a,进入环内到slow和fast相遇的地点距离是b,环内剩下的距离是c,如图所示。 环的长度是bc 慢指针移动距离是ab 快指针移动距离是abk(bc…

leetcode25:k个一组链表反转

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

《今日制造与升级》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问:《今日制造与升级》是不是核心期刊? 答:不是,是知网收录的正规学术期刊。 问:《今日制造与升级》级别? 答:国家级。主管单位:中国机械工业联合会 …

【Linux第八课-进程间通信】管道、共享内存、消息队列、信号量、信号、可重入函数、volatile

目录 进程间通信为什么?是什么?怎么办?一般规律具体做法 匿名管道原理代码 命名管道原理代码 system V共享内存消息队列信号量信号量的接口 信号概念为什么?怎么办?准备信号的产生信号的保存概念三张表匹配的操作和系统…

C++builder中的人工智能(18):神经网络中的SoftMax函数

在这篇文章中,我们将探讨SoftMax函数在神经网络中的作用,如何在人工神经网络(ANN)中使用SoftMax函数,以及在AI技术中SoftMax的应用场景。让我们来详细解释这些概念。 SoftMax函数是什么? SoftMax函数是逻辑…

证件照尺寸168宽240高,如何手机自拍更换蓝底

在提供学籍照片及一些社会化考试报名时,会要求我们提供尺寸为168*240像素的电子版证件照,本文将介绍如何使用“报名电子照助手”,借助手机拍照功能完成证件照的拍摄和背景更换,特别是如何将照片尺寸调整为168像素宽和240像素高&am…

pytest+request+allure接口自动化框架搭建分享

介绍分享一个接口自动化框架搭建方法 (pytestrequestallure),这个方案是由 xpcs 同学在TesterHome社区网站的分享。 写在前面 去年11月被裁,到现在还没上岸,gap 半年了。上岸无望,专业技能不能落下,花了两三天时间&…

大数据新视界 -- 大数据大厂之 Impala 性能优化:融合机器学习的未来之路(上 (2-2))(11/30)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Unity 实现数字垂直滚动效果

Unity 实现数字垂直滚动效果 前言项目场景布置Shader代码编写材质球设置代码编写数字图片 前言 遇到一个需要数字垂直滚动模拟老虎机的效果,记录一下。 项目 场景布置 3个Image换上带有RollNumberShader的材质 在RollNumberScript脚本中引用即可 Shader代码编…

[linux]docker基础

常见命令 Docker最常见的命令就是操作镜像、容器的命令,详见官方文档: Docker Docs 案例: 查看DockerHub,拉取Nginx镜像,创建并运行Nginx容器 在DockerHub中搜索Nginx镜像 拉取Nginx镜像 查看本地镜像列表 把镜像保持到本地 查看保持命令的…

纯C++信号槽使用Demo (sigslot 库使用)

sigslot 库与QT的信号槽一样,通过发送信号,触发槽函数,信号槽不是QT的专利,早在2002年国外的一小哥用C写了sigslot 库,简单易用; 该库的官网(喜欢阅读的小伙伴可以仔细研究)&#xf…

(Go语言)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法

0. 序言 从这章开始,在Go基础语法里难度就开始上来了 在学习函数与方法前,先弄明白指针是很重要的。 1. 指针 在没学指针前,相信很多人就已经大概知道指针是个什么东西了。因为它太有名了,当然是与 C和C 的出名有关。 1.1 指针…