初探t-sne(附python代码)

九月下旬啦!
封校不能出门 只能乖乖在校科研了
(厦门加油~同安稳住鸭!)
今天做一个简单的知识记录/代码记录

T-sne

t-SNE(t-distributed stochastic neighbor embedding)是用于降维的一种机器学习算法,可以将高维数据内部的特征放大,使得相似的数据在低维中能更加接近,不相似的数据在低维中距离更远
降维,简而言之,就是将高维空间的数据在低维空间进行展示。
与之前写过的PCA(https://www.jianshu.com/p/7cc617ee0f0c)相比,t-sne属于非线性降维,PCA为线性降维。线性降维算法主要问题是它们集中将不相似的数据点放置在较低维度区域时,数据点相距甚远。但是为了在低维、非线性流型上表示高维数据,也需要把相似的数据点靠近在一起展示,这并不是线性降维算法所能做的,且线性降维不能解释特征直接复杂的多项式关系,具有一定的局限性。t-SNE是基于在邻域图上随机游走的概率分布,可以在数据中找到其结构关系,故,t-sne在降维上比PCA更胜一筹。

算法

t-sne是在sne的基础上提出来的,这边对sne就不展开过多的介绍
具体可见(https://blog.csdn.net/scott198510/article/details/76099700

t-sne搬运(https://zhuanlan.zhihu.com/p/148170862
步骤1:先测量一个点相对于其他点的距离。
(不是直接处理这些距离,而是将它们映射到一个概率分布。)在分布中,相对于当前点距离最小的点有很高的可能性,而远离当前点的点有很低的可能性。


步骤2:除以概率总和
(请注意蓝色的点团比绿色的点团更分散。我们需要解决比例上的差异)
因此,尽管两点之间的绝对距离不同,但它们被认为是相似的。
数学概念:正态分布

把指数前面的所有东西都放下,用另一个点代替均值,得到了方程:

步骤3:如何使用缩小的特征空间
首先,我们创建一个n_samples x n_components矩阵(在本例中为9x1),并用随机值(即位置)填充它

如果采用与上面相似的方法(测量点之间的距离并将它们映射到一个概率分布),得到以下等式:

如果能使简化特征空间中的点的概率分布近似于原始特征空间中的点,就能得到定义良好的聚类。为了做到这一点,我们使用了一种叫做KL散度的东西。KL散度是衡量一个概率分布与另一个概率分布的差异。(KL散度值越低,两个分布越接近。KL散度为0意味着这两个分布是相同的。)
在t-SNE中,我们使用梯度下降最小化所有数据点上的Kullback-Leiber差异的总和。

最后,对成本函数对每一点求偏导数,以便得到每次更新的方向。

一点总结:

1.非线性降维算法t-SNE通过基于具有多个特征的数据点的相似性识别观察到的模式来找到数据中的规律。
2.它不是一个聚类算法,而是一个降维算法,可以较好地通过视觉可视化来验证算法的性能。
t3.-SNE的核心思想是保证在低维上数据的分布与原始特征空间的分布相似性高。相似性度量是依赖于KL散度以及计算欧式距离并概率化。换句话说,它依然受到维度灾难的影响,如果在低维空间上本身不存在区分度或者高维空间中欧式距离差别很小的话,效果也不好。

代码

1.经典手写数字数据集的降维与可视化

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()
原文链接:https://blog.csdn.net/tszupup/article/details/84997804

2.t-SNE可视化两个图片数据集合的差异

import os
import numpy as np
import cv2
from time import time
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets #手写数据集要用到
from sklearn.manifold import TSNE
#该函数是关键,需要根据自己的数据加以修改,将图片存到一个np.array里面,并且制作标签
#因为是两类数据,所以我分别用0,1来表示
def get_data(Input_path): #Input_path为你自己原始数据存储路径,我的路径就是上面的'./Images'
    Image_names=os.listdir(Input_path) #获取目录下所有图片名称列表
    data=np.zeros((len(Image_names),40000)) #初始化一个np.array数组用于存数据
    label=np.zeros((len(Image_names),)) #初始化一个np.array数组用于存数据
    #为前500个分配标签1,后500分配0
    for k in range(500):
        label[k]=1
    #读取并存储图片数据,原图为rgb三通道,而且大小不一,先灰度化,再resize成200x200固定大小
    for i in range(len(Image_names)):
        image_path=os.path.join(Input_path,Image_names[i])
        img=cv2.imread(image_path)
        img_gray=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
        img=cv2.resize(img_gray,(200,200))
        img=img.reshape(1,40000)
        data[i]=img
        n_samples, n_features = data.shape
    return data, label, n_samples, n_features

‘’‘下面的两个函数,
一个定义了二维数据,一个定义了3维数据的可视化
不作详解,也无需再修改感兴趣可以了解matplotlib的常见用法
’‘’
def plot_embedding_2D(data, label, title):
    x_min, x_max = np.min(data, 0), np.max(data, 0)
    data = (data - x_min) / (x_max - x_min)
    fig = plt.figure()
    for i in range(data.shape[0]):
        plt.text(data[i, 0], data[i, 1], str(label[i]),
                 color=plt.cm.Set1(label[i]),
                 fontdict={'weight': 'bold', 'size': 9})
    plt.xticks([])
    plt.yticks([])
    plt.title(title)
    return fig
def plot_embedding_3D(data,label,title): 
    x_min, x_max = np.min(data,axis=0), np.max(data,axis=0) 
    data = (data- x_min) / (x_max - x_min) 
    ax = plt.figure().add_subplot(111,projection='3d') 
    for i in range(data.shape[0]): 
        ax.text(data[i, 0], data[i, 1], data[i,2],str(label[i]), color=plt.cm.Set1(label[i]),fontdict={'weight': 'bold', 'size': 9}) 
    return fig

#主函数
def main():
    data, label, n_samples, n_features = get_data('./Images') #根据自己的路径合理更改
    print('Begining......') #时间会较长,所有处理完毕后给出finished提示
    tsne_2D = TSNE(n_components=2, init='pca', random_state=0) #调用TSNE
    result_2D = tsne_2D.fit_transform(data)
    tsne_3D = TSNE(n_components=3, init='pca', random_state=0)
    result_3D = tsne_3D.fit_transform(data)
    print('Finished......')
    #调用上面的两个函数进行可视化
    fig1 = plot_embedding_2D(result_2D, label,'t-SNE')
    plt.show(fig1)
    fig2 = plot_embedding_3D(result_3D, label,'t-SNE')
    plt.show(fig2)
if __name__ == '__main__':
    main()
参考:https://zhuanlan.zhihu.com/p/67491123

ENDing~冲冲冲!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341