Tensorflow_06_Tensorboard 的数据可视化与 Data Embedding

Brief 概述

Tensorboard 提供了一个非常亲切且容易执行的环境给使用者更好的找出计算流图当中的问题,并根据问题发生的要点予以更正,不过这个工具是 Google 团队在经历长达一年的时间开发出来的产物,实际上的功能肯定不是简单的一篇文章能够涵盖,这里要介绍另一个数据处理中非常实用的投影办法,Tensorboard 提供了内置的降维非监督学习算法,让我们只要简单的导入数据后,即可通过鼠标点击和拉动的方式调整聚类所需要的一切超参数。

 

Plus - Embedding Visualizer

上节的内容其实对于一般的使用和工作辅助已经非常够用了,不过 Tensorboard 数据可视化的绝招可以让我们直接在多个维度中分布出大数据的位置,并根据构建好的模型与初始化的参数,全程观看大数据在模型迭代中归类的移动过程,同时可以手动调整多维度数据分布的观察角度,已经可以算上是一个可视化神器的级别,因此特别推荐大家对 Projector 有一定程度的理解。

谈到这个功能主要有两个步骤需要拆分,分别如下:

  1. Embedding
  2. Projecting

1. Embedding Data

指的是把不论是什么类型的数据(图片,声音,文字...等)对应到一组向量中的动作,这些向量可以是随机的,也可以是经过不同的数据提取出来的特征值,目的是为了让数据能够更能有效的被计算机处理,因此做了一个转换动作。

--- Here are some examples below ---

DoReMi = [0.23, 1.59, 3.82, ..., 1.02]

words = [5.33, 0.29, 3.09, ..., 8.91]

image = [3.44, 8.22, 4.92, ..., 6.21]

2. Projecting Embedding Data

一个被 Embedded 过后的数据现在(可能)是由多个维度的向量组成的,一旦数据用向量表示后,我们就可以更好的使用数学工具处理和计算,同时可以根据这些向量值把数据投射到一个 2D 或是 3D 的空间中更好的达到数据可视化的效果。其中 Tensorboard 提供了两个数据投射的方法分别如下:

  1. PCA: Principle Component Analysis 主成分分析
  2. t-SNE: T-distributed Stochastic Neighbor Embedding 

Explanation

不同复杂程度的数据对应到不一样多的维度,但是实际上我们在描绘数据分布的时候,大于三维的数据是没办法落实在人们能够构建的坐标中的,因此下面两个方法都是先让数据降维,再根据降维的结果描绘数据点到新的坐标轴上。

2-1. PCA

此方法根据数据在不同维度上的离散情况定义出一个又一个新的坐标,再根据每个新坐标方差(variance)的大小找到最大的前三个坐标,用此三个坐标构建一个新的立体空间,并把数据依照投影的规则描绘到其中。能够这么操作的理由是方差越大的新坐标上,从数学的角度看越多的保留了数据的特征,越没有特征的数据分布也正是我们越不想理会的东西,越大的特征才能够越好的分辨数据,做好简化的同时不失归类的目的,如下图:

图中黑色虚线位二维数据线性回归算出来的一维方程式,灰色虚线表示二维数据投影到新坐标的的对应点,并且新的坐标会沿着方差最大的回归线方向建立。

这也就好比我们看电影的时候,3D 的电影其实我们是可以舍去深度的维度,使其成为 2D 电影来观看的,用数学的描述就是因为其第三维数据之间的方差小到足以让我们视觉上忽略,因此可以把 3D 电影 PCA 成为 2D。

2-2. t-SNE

与 PCA 使用数据相关性的大小来重新划定坐标轴的方式不同,此方法使用每个个别数据点与其他所有数据的距离来权衡彼此之间的相关性,旦凡坐落在 t-distributionn 分布范围内的数据点,我们就更倾向于把他们归到同一类别中,t-distribution 的分布方式和 normal distribution 不同之处在于它中间没有那么突出,而两边相对更为平滑,是一种比较不陡峭的下滑分布,t-SNE 也因此得其名。

而 t-SNE 方法投射数据的方式也较为简单,它不用根据数学模型选择坐标轴,而是直接投射到我们预计维度数量的坐标系中,并根据新的坐标系中数据之间的彼此距离和原数据维度上的距离做对比,此一距离又称作欧式距离,谁与谁应该离得比较近,那么谁就往应该的方向移动一步,因此此方法投射的方式并非一步到位,而是像下棋一般一步一步的逐渐趋近原本维度上数据分布的模样,如下图:

跟 PCA 方法最大的不同地方在于 t-SNE 是非线性聚类的方法,虽然说精确度比前者要高出很多,但是计算资源的消耗也是呈现指数级的上升。


Import data 导入数据

了解了两个方法的简单绘制原理后,接下来是把数据导入 Tensorboard 的环节,而要呈现出一个三维数据分布的效果需要根据两个文件,其名称与文件内容分别如下:

  • Sprite image - data format: .jpeg or .png
  • Labels file - data format: tsv (Tab Separated Values)

如上圖所示,Sprite image 就是一张大大的图,是用一部分数据集拼凑出来的结果,我们可以自定义数据集里面有多少张图片将要被包含到此大图中。利用这张大图和对应大图的标签 tsv 数据,我们就可以使用上述的两种方法其中一种,把结果投射到可视化的坐标轴中观察。

然而,如此设计导入数据的方法理由无从得知,把数据集放到同一张大图中的结果只能是自己手写代码完成,下面是生成大图与 .tsv 标签文件的方法:

def sprite_and_tsv(images, labels, save_dir=None):
    # if the argument is the python list, turn it into numpy array
    if isinstance(images, list):
        images = np.array(images)
        
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    
    # get the dimension of single image from the 4D array
    img_h = images.shape[1]
    img_w = images.shape[2]
    
    # get the size of produced sprite image
    size = int(np.ceil(np.sqrt(images.shape[0])))
    
    # create a blank image array, depending on image dimension
    # in this case, the input images is 2D without color channels
    sprite_img = np.ones([img_h*size, img_w*size])
    
    # dive into the partial blank image to fill the area
    # with the selected new image
    for i in range(size):
        for j in range(size):
            iteration = i * size + j
            if images.shape[0] > iteration:
                # only numpy array can be indexed this way
                sprite_img[
                    i*img_h:(i+1)*img_h, 
                    j*img_w:(j+1)*img_w
                ] = images[iteration] * (-1) + 1
                # * -1 + 1 is used to make white background and black num
    
    # save the combined image into the appointed directory
    img_dir = os.path.join(save_dir, 'sprite_img.png')
    plt.imsave(img_dir, sprite_img, cmap='gray')
    
    # save the label .tsv metadata into the appointed directory
    meta_dir = os.path.join(save_dir, 'labels.tsv')
    with open(meta_dir, 'w') as meta:
        meta.write('Index\tLabel\n')
        for index, label in enumerate(labels):
            meta.write('{}\t{}\n'.format(index, label))

 

Steps of Importing data 导入数据的步骤

经过上面的步骤的理解加上代码执行后,现在电脑里面多了一个文件夹和两个文件,这两个文件是在 Tensorboard 展开三维数据的两个不可或缺的核心,不过核心周边的事前准备和数据导引过程对构建可视化模型而言同样重要,有了最重要的两个文件之后,接下来是构建模型让 Tensorflow 读取文件的环节,步骤如下:

  1. 创建两个最重要的图像数据和对应标签文档,并储存此二文件到指定文件夹中
  2. 根据文件夹路径,引入此二文件到专为 embedding data 设置的 tf 节点中
  3. 使用 projector 方法把 embedding 对象的内容投射到 Tensorboard 上面
  4. 创建绘话 session 并把节点的变量使用 Saver 方法储存起来

Tensorflow 中的 projector 方法导入方式需要特别留意,完整代码和注释如下:

Step 1. Create the key files

首先引入必須使用的模塊包,加上此系列 Tensorflow 前面章节的设定函数后,呼叫上面设定好的函数并指定储存路径,生成两个必要的文件。

import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import os

from tensorflow.contrib.tensorboard.plugins import projector
from Code_Session.TF_04 import mnist


# define how many images would be embedded into one big graph
emb_num = 1598
data_dir = '/Users/kcl/MNIST_data'
save_dir = '/Users/kcl/tb_projector'

# create an instance to load mnist dataset from a local computer
M = mnist.MNIST(val_ratio=0.0, data_dir=data_dir)

# format the images and randomly pick up the amount of images
format_images = M.img_train.reshape([-1, 28, 28])
rand = np.random.randint(0, len(M.lab_train), size=emb_num, dtype=np.int)

# put the picked data into the defined func to generate both key files
sprite_and_tsv(format_images[rand], M.lab_train[rand], save_dir=save_dir)

文件的储存结果如下图:

Step 2. Create embedding tf node

使用 tf.Variable() 创建变量,重点在于变量节点的名字,之后呼叫此节点的方式都是借由现在定义的名字来呼叫,并把储存路径下的文件 summarize 到一个新的对象中。

# construct the embedding tf node for the input data
emb_node = tf.Variable(M.img_train[rand], name='Embed_data')
# summarize the 2 key files along with "save_dir" directory
summary_writer = tf.summary.FileWriter(save_dir)

emb_node 的数据形状只能是二维的张量,第一维表示数据的个数,第二维表示数据的特征数,就图片而言,即便数据是由长宽和颜色通道组合而成,但是在给 Tensorboard 指令的时候,需要把全部数据拉直成为一条没有多余维度的数据,不然可视化的过程将会持续的卡顿并无法显示。

Step 3. Project the embedding data onto Tensorboard

分别把两个重要文件的完整路径赋值给不同的对象,用來後面方便呼叫指定的文件。使用 projector 方法创建 embedding 对象后,开始往此对象中添加节点名称,指定标签文件,指定大图。最后决定那一张大图需要被切分的尺寸后,把设定好的 projector 方法对象名 "config" 整个投影到 summary 对象中去。

# get the complete directory of individual generated files
os.chdir(save_dir)
sprite_img_dir = os.path.abspath('sprite_img.png')
tsv_lab_dir = os.path.abspath('labels.tsv')

# create an embedding object by using projector method called config
config = projector.ProjectorConfig()
embedding = config.embeddings.add()

# embed the node by calling its node name
embedding.tensor_name = emb_node.name
# embed the sprite image by calling its full path
embedding.sprite.image_path = sprite_img_dir
# embed the tsv file by calling its full path
embedding.metadata_path = tsv_lab_dir

# cut the whole sprite image into specific size
embedding.sprite.single_image_dim.extend([28, 28])

# finally projecting embedding things onto the summary writer object
projector.visualize_embeddings(summary_writer, config)

小小总结,代码一共分三部分:

  1. 告知文件信息
  2. 根据这些文件信息,下达一系列必须执行的动作指令
  3. 把指令做完的结果连同原文件信息可视化

跟着这个逻辑走,思路就会变得清晰。做到这边基本上就已经完成了所有的代码功能部署,接着下一步的执行环节后,在不启动 Saver 的方法创建 .ckpt 检查点文件情况下,同样可以顺利开启可视化的坐标观察数据的分布。此阶段还会创建一个新的文件,用以让 Tensorboard 解析数据分布的情况,如下图:

Step 4. Session and Save

把可视化的结果和设定参数的一切保存起来,方便后面呼叫查看。执行所有代码后,就可以回到命令提示字元窗口键入启动 Tensorboard 的代码,观察最后面呈现出来的结果。

sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
saver.save(sess, os.path.join(save_dir, 'mnist.ckpt'))
'/Users/kcl/tb_projector/mnist.ckpt'

虽然储存文件和数据可视化的 "展示" 没有任何关系,没有 .ckpt 文件也能够执行起来,但是如果我们想在 Tensorboard 上面执行非监督学习的聚类操作,那么在使用指令开启 Tensorboard 之前,就必须让 .ckpt 文件也在同样即将被引入的文件夹中才行,这么一来调整 learning rate 和一些超参数计算出来的结果才会是去向准确的,否则的话,Tensorboard 就只是随意的移动数据,看似在聚类但其实怎么聚都还是乱的结果。

p.s. 储存的 .ckpt 文件不需要是训练过的模型才储存,可以直接是如上代码,什么都不做就储存一个检查点,在导入 Tensorboard 的时候就可以有聚类收敛的效果了。

 

Result on Tensorboard

进入到储存重要档案的文件夹后,开启终端键入上面内容提到过的 tensorboard 指令,等一会电脑运行即可出现一个二维或三维的可视化数据坐标轴,坐标中随机散落了所有数据的分布,如下图片效果:

借由 tensorflow 的 plugin 里面的方法 projector,我们顺利的打开了 Tensorboard 的此项功能,左边栏位控制列表中明显可以看出 T-SNE 方法聚类效果是 PCA 完全无法比拟的,而其聚类的过程,完全是在 Tensorboard 投影上调整参数,不需要我们额外添加任何的代码指令即可开始聚类的非监督学习迭代。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值