当前位置:   article > 正文

t-SNE非线性降维

t-sne

在这里插入图片描述

TSNE(t-Distributed Stochastic Neighbor Embedding )是对SNE的改进,SNE最早出现在2002年,改变了MDN和ISOMAP中基于距离不变的思想,将高维映射到低维的同时,尽量保证相互之间的分布概率不变,SNE将高维和低维中的样本分布都看作高斯分布,而TSNE将低维中的坐标当作T分布,这样的好处是为了让距离大的簇之间距离拉大,从而解决了拥挤问题。

将高维空间中的数据映射到低维空间中,并保留数据集的局部特性。当我们想对高维数据集进行分类,但又不清楚这个数据集有没有很好的可分性(同类之间间隔小、异类之间间隔大)时,可以通过t-SNE将数据投影到2维或3维空间中观察一下:如果在低维空间中具有可分性,则数据是可分的;如果在低维空间中不可分,则可能是因为数据集本身不可分,或者数据集中的数据不适合投影到低维空间。

t-SNE的特点

占用内存较多、运行时间长,t-SNE的计算复杂度很高,在数百万个样本数据集中可能需要几个小时,而PCA可以在几秒钟或几分钟内完成。

算法是随机的,具有不同种子的多次实验可以产生不同的结果。虽然选择loss最小的结果就行,但可能需要多次实验以选择超参数。

当数据维数过高时,这两个矩阵的计算量是很大的。所以一般来说,我们会先用 PCA 降维到 10 维左右,再使用 t-SNE 降维到 2 或 3 维空间进行可视化。

tSNE实际上只能嵌入到2维或3维中,是一种降维和可视化技术。另外t-SNE的输出可以作为其他分类算法的输入特征。

t-SNE 更加注重保留原始数据的局部特征。

降维步骤

t-SNE:将数据点之间的相似度转换为概率。原始空间中的相似度由高斯联合概率表示,嵌入空间的相似度由“t分布”表示。
第一步:计算数据集中每行与其他行的距离(默认为欧式距离),转换为概率向量;
第二步:对每一行重复操作,得到概率矩阵;
第三步:沿两条新轴用t分布对数据随机化;
第四步:逐渐迭代,通过最小化KL散度,使得二维空间的新概率矩阵尽可能接近原高维空间的。

Manifold learning sklearn官方文档

sklearn中文文档
流形学习降维:就是找到一个从流形到欧式空间的映射
局部线性嵌入(LLE)、等距离映射(Isomap)、多维标度法(MDS)
在这里插入图片描述

t-SNE实践(可视化两个图片数据集合的差异)

Pytorch+t-SNE

手写数据集降维案例

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.manifold import TSNE


# 加载数据
def get_data():
    """
    :return: 数据集、标签、样本数量、特征数量
    """
    digits = datasets.load_digits(n_class=10)
    data = digits.data  # 图片特征
    label = digits.target  # 图片标签
    n_samples, n_features = data.shape  # 数据集的形状
    return data, label, n_samples, n_features


# 对样本进行预处理并画图
def plot_embedding(data, label, title):
    """
    :param data:数据集
    :param label:样本标签
    :param title:图像标题
    :return:图像
    """
    x_min, x_max = np.min(data, 0), np.max(data, 0)
    data = (data - x_min) / (x_max - x_min)  # 对数据进行归一化处理
    fig = plt.figure()  # 创建图形实例
    ax = plt.subplot(111)  # 创建子图
    # 遍历所有样本
    for i in range(data.shape[0]):
        # 在图中为每个数据点画出标签
        plt.text(data[i, 0], data[i, 1], str(label[i]), color=plt.cm.Set1(label[i] / 10),
                 fontdict={'weight': 'bold', 'size': 7})
    plt.xticks()  # 指定坐标的刻度
    plt.yticks()
    plt.title(title, fontsize=14)
    # 返回值
    return fig


# 主函数,执行t-SNE降维
def main():
    data, label, n_samples, n_features = get_data()  # 调用函数,获取数据集信息
    print('Starting compute t-SNE Embedding...')
    ts = TSNE(n_components=2, init='pca', random_state=0)
    # t-SNE降维
    reslut = ts.fit_transform(data)
    # 调用函数,绘制图像
    fig = plot_embedding(reslut, label, 't-SNE Embedding of digits')
    # 显示图像
    plt.show()


# 主函数
if __name__ == '__main__':
    main()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

在这里插入图片描述

PCA vs t-SNE

那么既然有了 PCA,为什么我们还要去提出 t-SNE 呢?这就需要提到 PCA 的一个局限性。在降维的目的中,除了节约内存,还有一个最最重要的就是“对数据进行可视化”。我们希望将高维数据降维到 2 或 3 维,从而能够在图上直观地展现出来。

PCA 固然能够满足可视化的要求,但是人们发现,如果用 PCA 降维进行可视化,会出现所谓的“拥挤现象”。对于橙、蓝两类数据,如果我们用 PCA 降维后呈现在二维平面上,那么两类数据的边界并不明显,仿佛蓝色的数据“嵌入”了橙色数据一般。而反观右图,蓝色与橙色两类数据明显没有了交集。并且从右图中我们还能看出,数据点仿佛是每 4 个凝聚成一个“小团体”,每 4 个“小团体”凝聚中一个“中团体”,这表明 t-SNE 更加注重保留原始数据的局部特征
在这里插入图片描述

PCA将手写数字降到2维难以区分

from sklearn.manifold import TSNE
from sklearn.datasets import load_iris,load_digits
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import os

digits = load_digits()
X_tsne = TSNE(n_components=2,random_state=33).fit_transform(digits.data)
X_pca = PCA(n_components=2).fit_transform(digits.data)

ckpt_dir="images"
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)

plt.figure(figsize=(10, 5))
plt.subplot(121)
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=digits.target,label="t-SNE")
plt.legend()
plt.subplot(122)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=digits.target,label="PCA")
plt.legend()
plt.savefig('images/digits_tsne-pca.png', dpi=120)
plt.show()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

参数解释

如何优化t-sne
在这里插入图片描述

sklearn.manifold.TSNE(n_components=2, perplexity=30.0, early_exaggeration=12.0, learning_rate=200.0, n_iter=1000, n_iter_without_progress=300, min_grad_norm=1e-07, metric=’euclidean’, init=’random’, verbose=0, random_state=None, method=’barnes_hut’, angle=0.5)
n_components:int,可选(默认值:2)嵌入式空间的维度。
perplexity:float,可选(默认:30)较大的数据集通常需要更大的perplexity。考虑选择一个介于5和50之间的值。由于t-SNE对这个参数非常不敏感,所以选择并不是非常重要。
early_exaggeration:float,可选(默认值:4.0)这个参数的选择不是非常重要。
learning_rate:float,可选(默认值:1000)学习率可以是一个关键参数。它应该在100到1000之间。如果在初始优化期间成本函数增加,则早期夸大因子或学习率可能太高。如果成本函数陷入局部最小的最小值,则学习速率有时会有所帮助。
n_iter:int,可选(默认值:1000)优化的最大迭代次数。至少应该200。
n_iter_without_progress:int,可选(默认值:300,必须是50倍数)在我们中止优化之前,没有进展的最大迭代次数。
0.17新版​​功能:参数n_iter_without_progress控制停止条件。
min_grad_norm:float,可选(默认值:1E-7)如果梯度范数低于此阈值,则优化将被中止。
metric:字符串或可迭代的,可选,计算特征数组中实例之间的距离时使用的度量。如果度量标准是字符串,则它必须是scipy.spatial.distance.pdist为其度量标准参数所允许的选项之一,或者是成对列出的度量标准.PAIRWISE_DISTANCE_FUNCTIONS。如果度量是“预先计算的”,则X被假定为距离矩阵。或者,如果度量标准是可调用函数,则会在每对实例(行)上调用它,并记录结果值。可调用应该从X中获取两个数组作为输入,并返回一个表示它们之间距离的值。默认值是“euclidean”,它被解释为欧氏距离的平方。
init:字符串,可选(默认值:“random”)嵌入的初始化。可能的选项是“随机”和“pca”。 PCA初始化不能用于预先计算的距离,并且通常比随机初始化更全局稳定。
random_state:int或RandomState实例或None(默认)
伪随机数发生器种子控制。如果没有,请使用numpy.random单例。请注意,不同的初始化可能会导致成本函数的不同局部最小值。
method:字符串(默认:‘barnes_hut’)
默认情况下,梯度计算算法使用在O(NlogN)时间内运行的Barnes-Hut近似值。 method ='exact’将运行在O(N ^ 2)时间内较慢但精确的算法上。当最近邻的误差需要好于3%时,应该使用精确的算法。但是,确切的方法无法扩展到数百万个示例。0.17新版​​功能:通过Barnes-Hut近似优化方法。
angle:float(默认值:0.5)
仅当method ='barnes_hut’时才使用这是Barnes-Hut T-SNE的速度和准确性之间的折衷。 ‘angle’是从一个点测量的远端节点的角度大小(在[3]中称为theta)。如果此大小低于’角度’,则将其用作其中包含的所有点的汇总节点。该方法对0.2-0.8范围内该参数的变化不太敏感。小于0.2的角度会迅速增加计算时间和角度,因此0.8会快速增加误差。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/343732
推荐阅读
相关标签
  

闽ICP备14008679号