如何理解tensorflow 语义理解中的dimension

【前言】这篇文章将告诉你tensorflow的基本概念以及tensorflow的基本操作
TensorFlow的基本概念Tensor
TensorFlow的核心API
TensorFlow提供非常丰富的API,最底层的API—TensorFlow Core—提供了完整的编程控制接口。更高级别的API则是基于TensorFlow Core API之上,并且非常容易学习和使用,更高层次的API能够使一些重复的工作变得更加简单。比如tf.contrib.learn帮助你管理数据集等。
这篇博文将从TensorFlow Core开始。
Tensors(张量)
张量是所有深度学习框架中最核心的组件,TensorFlow中也是,在TensorFlow中,将数据表示为Tensor,一个Tensor是一个多维数组,例如,你可以将一批图像表示为一个四维数组[batch,height,width,channels],数组中的值均为浮点数。
在几何代数中定义的张量是基于向量和矩阵的推广,通俗理解,我们可以将标量视为零阶张量,那么矩阵就是二阶张量。
举例来说,我们可以将任意一张RGB彩色图片表示成一个三阶张量(三个维度分别是图片的高度、宽度和色彩数据)。
如图是一张普通水果图片按照RGB三原色拆分成的三张灰度图片,如果将这种表示方法用张量的形式写出来,就是下图的表格。
图中只显示了前5行、320列数据,每个方格代表一个像素点,其中的数据[1.0,1.0,1.0]即为颜色。假设用[1.0,0,0]表示红色,[0,1.0,0]代表绿色,[0,0,1.0]代表蓝色,那么如图所示,前面5行的数据则全部是白色。
将这一定义进行扩展,我们也可以用四阶张量表示一个包含多张图片的数据集,其中的四个维度分别是:图片在数据集中的编号,图片高度、宽度,以及色彩数据。
将各种各样的数据抽象成张量表示,然后再输入神经网络模型进行后续处理是一种非常必要且高效的策略。因为如果没有这一步骤,我们就需要根据各种不同类型的数据组织形式定义各种不同类型的数据操作,这会浪费大量的开发者精力。更关键的是,当数据处理完成后,我们还可以方便地将张量再转换回想要的格式。例如Python NumPy包中numpy.imread和numpy.imsave两个方法,分别用来将图片转换成张量对象(即代码中的Tensor对象),和将张量再转换成图片保存起来。
高维向量(Multidimensional Arrays)在matlab中的定义
An array having more than two dimensions is called a multidimensional array in the MATLAB(R) application. Multidimensional arrays in MATLAB are an extension of the normal two-dimensional matrix. Matrices have two dimensions: the row dimension and the column dimension.
You can access a two-dimensional matrix element with two subscripts: the first representing the row index, and the second representing the column index.
Multidimensional arrays use additional subscripts for indexing. A three-dimensional array, for example, uses three subscripts:
The first references array dimension 1, the row.
The second references dimension 2, the column.
The third references dimension 3. This illustration uses the concept of a page to represent dimensions 3 and higher.
To access the element in the second row, third column of page 2, for example, you use the subscripts (2,3,2).
As you add dimensions to an array, you also add subscripts. A four-dimensional array, for example, has four subscripts. The first two reference a row- the second two access the third and fourth dimensions of data.
Most of the operations that you can perform on matrices (i.e., two-dimensional arrays) can also be done on multidimensional arrays.
理解高维数组的建议
需要和高维数组(Tensor)打交道的话,思考时不要想着row, column, page这些术语, 要用dim_1, dim_2,... dim_M 来思考。好多地方说Matlab是先存column, 用我们的术语其实就是Matlab按照从左到右:dim_1, dim_2,... dim_M的顺序存储元素。例如想想下面 2 x 4 x 3 x 5 矩阵的存储顺序:
可视化高维数组
Rank本意是矩阵的秩,不过Tensor Rank和Matrix Rank的意义不太一样,这里就还叫Rank防止混淆了。Tensor Rank的意义看起来更像是维度,比如Rank = 1就是向量,Rank = 2就是矩阵了。(Rank = 0就是一个值了)
官网原话:A tensor's rank is its number of dimensions.
# a rank 0 this is a scalar with shape [][1. ,2., 3.] # a rank 1 this is a vector with shape [3][[1., 2., 3.], [4., 5., 6.]] # a rank 2 a matrix with shape [2, 3][[[1., 2., 3.]], [[7., 8., 9.]]] # a rank 3 tensor with shape [2, 1, 3]
Shape就是Tensor在各个维度上的长度组成的数组,譬如Rank = 0的Tensor Shape = [](因为没有维度嘛),Rank = 1的Tensor Shape = [ a ],Rank = 2的Tensor Shape = [ a, b ]这样。
本文已收录于以下专栏:
相关文章推荐
2、S型神经元
3、神经网络的架构
4、一个简单的分类手写数字的网络
5、使用梯度下降算法进行学习
6、实现我们的网络来分类数字
7、迈向深度学习
matplotlib实践
介绍TensorFlow中三大基本概念:Tensor,Operation,Graph
本文主要对tf的一些常用概念与方法进行描述。
TensorFlow 人工智能引擎 入门教程之一 基本概念以及理解
一、TensorFlow 简介1、TensorFlow 的定义
Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow代表着张量从图象的一端流动到另一端计...
摘要:本系列主要对tf的一些常用概念与方法进行描述。本文主要针对tensorflow的数据IO、图的运行等相关函数进行讲解。为‘Tensorflow一些常用基本概念与函数’系列之三。...
转载自:http://blog.csdn.net/lenbow/article/details/
摘要:本文主要对tf的一些常用概念与方法进行描述。1、tensorflow的基本运作为...
转载于:/p/
比喻说明:
结构:而计算图所建立的只是一个网络框架。在编程时,并不会有任何实际值出现在框架中。所...
他的最新文章
讲师:李江龙
讲师:司徒正美
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)基于TensorFlow理解三大降维技术:PCA、t-SNE 和自编码器4 months ago所以 fit 的目标是创建我们后面要用到的 Σ 和 U。
我们将从 tf.svd 行开始,这一行给了我们奇异值(就是图 1 中标记为 Σ 的对角值)和矩阵 U 和 V。
然后 tf.diag 是 TensorFlow 的将一个 1D 向量转换成一个对角矩阵的方法,在我们的例子中会得到 Σ。
在 fit 调用结束后,我们将得到奇异值、Σ 和 U。
现在让我们实现 reduce。def reduce(self, n_dimensions=None, keep_info=None):
if keep_info:
# Normalize singular values
normalized_singular_values = self.singular_values / sum(self.singular_values)
# Create the aggregated ladder of kept information per dimension
ladder = np.cumsum(normalized_singular_values)
# Get the first index which is above the given information threshold
index = next(idx for idx, value in enumerate(ladder) if value &= keep_info) + 1
n_dimensions = index
with self.graph.as_default():
# Cut out the relevant part from sigma
sigma = tf.slice(self.sigma, [0, 0], [self.data.shape[1], n_dimensions])
pca = tf.matmul(self.u, sigma)
with tf.Session(graph=self.graph) as session:
return session.run(pca, feed_dict={self.X: self.data})
如你所见,reduce 既有 keep_info,也有 n_dimensions(我没有实现输入检查看是否只提供了其中一个)。
如果我们提供 n_dimensions,它就会降维到那个数;但如果我们提供 keep_info(应该是 0 到 1 之间的一个浮点数),就说明了我们将从原来的数据中保存多少信息(假如是 0.9,就保存 90% 的数据)。
在第一个 if 中,我们规范化并检查了需要多少了奇异值,基本上能从 keep_info 得知 n_dimensions。
在这个图中,我们只需要从 Σ (sigma) 矩阵切下我们所需量的数据,然后执行矩阵乘法。
现在让我们在鸢尾花数据集上试一试,这是一个 (150, 4) 的数据集,包含了三种鸢尾花。from sklearn import datasets
import matplotlib.pyplot as plt
import seaborn as sns
tf_pca = TF_PCA(iris_dataset.data, iris_dataset.target)
tf_pca.fit()
pca = tf_pca.reduce(keep_info=0.9)
# Results in 2 dimensions
color_mapping = {0: sns.xkcd_rgb['bright purple'], 1: sns.xkcd_rgb['lime'], 2: sns.xkcd_rgb['ochre']}
colors = list(map(lambda x: color_mapping[x], tf_pca.target))
plt.scatter(pca[:, 0], pca[:, 1], c=colors)
图 2:鸢尾花数据集 PCA 二维绘图
还不错吧?
t-SNE 相对于 PCA,t-SNE 是一种相对较新的方法,起源于 2008 年的论文《Visualizing Data using t-SNE》:
它也比 PCA 更难理解,所以让我们一起坚持一下。
我们对 t-SNE 的符号定义为:X 是原来的数据;P 是一个矩阵,显示了高维(原来的)空间中 X 中的点之间的亲和度(affinities,约等于距离);Q 也是一个矩阵,显示了低维空间中数据点之间的亲和度。如果你有 n 个数据样本,那么 Q 和 P 都是 n×n 的矩阵(从任意点到任意点的距离包含自身)。
现在 t-SNE 有自己的「独特的」测量事物之间距离的方式(我们下面就会介绍)、一种测量高维空间中数据点之间的距离的方式、一种测量低维空间中数据点之间的距离的方式以及一种测量 P 和 Q 之间的距离的方式。
根据原始论文,一个数据点 x_j 与另一个点 x_i 之间的相似度是 p_j|i,其定义为:「x_i 选取 x_j 为其近邻点(neighbor),而近邻点的选取与以 x_i 为中心的高斯分布概率密度成正比。」
「这是什么意思!」不要担心,我前面说了,t-SNE 有自己测量距离的独特方式,所以让我们看看用于测量距离(亲和度)的公式,然后从中取出我们理解 t-SNE 的行为所需的见解。
从高层面来讲,这就是算法的工作方式(注意和 PCA 不一样,这是一个迭代式的算法)。
图 3:t-SNE 工作流程
让我们一步步地研究一下这个流程。
这个算法有两个输入,一个是数据本身,另一个被称为困惑度(Perp)。
简单来说,困惑度(perplexity)是指在优化过程中数据的局部(封闭点)和全局结构的焦点的平衡程度——本文建议将其保持在 5 到 50 之间。
更高的困惑度意味着一个数据点会把更多的数据点看作是其紧密的近邻点,更低的困惑度就更少。
困惑度会实际影响可视化的结果,而且你需要小心应对,因为它可能会在可视化低维数据时出现误导现象——我强烈推荐阅读这篇文章了解如何使用 t-SNE 困惑度:,其中介绍了不同困惑度的影响。
这种困惑度从何而来?它被用于求解式子 (1) 中的 σ_i,而且因为它们有单调的连接,所以可以通过二元搜索(binary search)找到。
所以使用我们提供给算法的困惑度,我们基本上会找到不同的 σ_i。
让我们看看公式为我们提供了哪些关于 t-SNE 的信息。
在我们探索公式 (1) 和 (2) 之前,需要知道 p_ii 和 q_ii 被设置为 0(即使我们将它们应用到两个相似的点上,公式的输出也不会是 0,这只是给定的值)。
所以看看公式 (1) 和 (2),我希望你注意到,当两个点很接近时(在高维表征中),分子的值大约为 1,而如果它们相距非常远,那么我们会接近无穷小——这将有助于我们后面理解成本函数。
现在我们可以了解关于 t-SNE 的一些事情了。
一是因为亲和度公式的构建方式,在 t-SNE 图中解读距离可能会出问题。
这意味着聚类之间的距离和聚类大小可能被误导,并且也会受到所选择的困惑度的影响(在上面我推荐的文章中,你可以看到这些现象的可视化)。
第二件要注意的事情是,怎么在等式 (1) 中我们基本上计算的是点之间的欧几里得距离?这方面 t-SNE 很强大,我们可以用任何我们喜欢的距离测量来取代它,比如余弦距离、Manhattan 距离,也可以使用任何你想用的测量方法(只要其保持空间度量(space metric),而且保持低维亲和度一样)——以欧几里得的方式会得到复杂的距离绘图。
比如说,如果你是一位 CTO,你有一些数据需要根据余弦相似度测量距离,而你的 CEO 想要你通过图表的形式呈现这些数据。我不确定你是否有时间向董事会解释什么是余弦相似度以及解读聚类的方式,你可以直接绘制余弦相似度聚类,因为欧几里得距离聚类使用 t-SNE——要我说,这确实很酷。
在代码中,你可以在 scikit-learn 中通过向 TSNE 方法提供一个距离矩阵来实现。
现在,我们知道当 x_i 和 x_j 更近时,p_ij/q_ij 的值更大;相反则该值更小。
让我们看看这会对我们的成本函数(被称为 KL 散度(Kullback–Leibler divergence))带来怎样的影响。让我们绘图,然后看看没有求和部分的公式 (3)。
图 4:没有求和部分的 t-SNE 成本函数
很难看明白这是啥?但我在上面给轴加了名字。
如你所见,这个成本函数是不对称的。
对于高维空间中临近的点,其得出了非常高的成本(p 轴),但这些点是低维空间中很远的点表示的;而在高维空间中远离的点则成本更低,它们则是用低维空间中临近的点表示的。
这说明在 t-SNE 图中,距离解释能力的问题甚至还更多。model = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=5)
tsne5 = model.fit_transform(iris_dataset.data)
model = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=30)
tsne30 = model.fit_transform(iris_dataset.data)
model = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=50)
tsne50 = model.fit_transform(iris_dataset.data)
plt.figure(1)
plt.subplot(311)
plt.scatter(tsne5[:, 0], tsne5[:, 1], c=colors)
plt.subplot(312)
plt.scatter(tsne30[:, 0], tsne30[:, 1], c=colors)
plt.subplot(313)
plt.scatter(tsne50[:, 0], tsne50[:, 1], c=colors)
plt.show()
图 5:在鸢尾花数据集上的 t-SNE,不同的困惑度
正如我们从数学中了解到的那样,你可以看到给定一个好的困惑度,数据会聚类,但要注意超参数的敏感性(如果不给梯度下降提供学习率,我无法找到聚类)。
在我们继续之前,我想说如果使用正确,t-SNE 会是一种非常强大的方法,而不会受到前面提及的负面影响,只是你要清楚如何使用它。
接下来是自编码器。
自编码器(Auto Encoders)
PCA 和 t-SNE 是方法,而自编码器则是一系列的方法。
自编码器是一种神经网络,其目标是通过使用比输入节点更少的隐藏节点(在编码器一端)预测输入(训练该网络使其输出尽可能与输入相似),为此该网络需要尽可能多地将信息编码到隐藏节点中。
图 6 给出了一个用于 4 维鸢尾花数据集的基本自编码器,其中输入层到隐藏层之间的连接线被称为编码器(encoder),而隐藏层到输出层之间的线被称为解码器(decoder)。
图 6:用于鸢尾花数据集的基本自编码器
所以为什么自编码器是一系列方法呢?因为我们仅有的约束条件是其输入层和输出层具有同样的维度,在两者之间,我们可以创建任何我们想要的可以最好地编码我们的高维数据的结构。
自编码器始于一些随机的低维表征(z)并会通过梯度下降改变其输入层和隐藏层以及隐藏层和输出层之间连接的权重,从而找到它们的解。
现在,我们对自编码器已经有了一定了解,因为我们可以控制该网络的内部,我们可以让编码器能挑选出特征之间的非常复杂的关系。
自编码器还有一个加分项。因为在训练结束时,我们有与隐藏层的连接权重,所以我们可以在特定的输入上训练,如果后面我们遇到了另一个数据点,那么我们无需重新训练就可以使用这些权重进行降维——但这种操作要小心,只有当新数据点与我们训练所用的数据点类似时这才有效。
在这种情况下,探索自编码器的数学可能很简单,但却没什么用处,因为对于每一种架构和我们选择的成本函数,其数学形式可能是不同的。
但如果我们想一想自编码器权重的优化方式,我们会理解我们定义的成本函数具有非常重要的作用。
因为自编码器会使用成本函数来确定其预测结果的质量,那么我们就可以使用这个功能来强化我们希望实现的东西。
不管我们想要的是欧几里得距离还是其它测量,我们都可以通过成本函数、使用不同的距离方法、使用不对称函数和其它方法而将其反映到编码的数据上。
而且因为自编码器本质上是神经网络,所以它还具有更大的力量,我们甚至可以在训练时给类和样本加权,从而为数据中的特定现象提供更大的重要性。
这能给我们压缩数据的方式提供很大的灵活性。
自编码器非常强大,而且在一些案例中能实现比其它方法更好的结果(谷歌搜一下「PCA vs Auto Encoders」,你就知道),所以它们肯定是一种有效的方法。
让我们用 TensorFlow 实现一个基于鸢尾花数据集的基本自编码器,并且绘图。
代码(自编码器) 同样,我们将其分成了 fit 和 reduce。def fit(self, n_dimensions):
graph = tf.Graph()
with graph.as_default():
# Input variable
X = tf.placeholder(self.dtype, shape=(None, self.features.shape[1]))
# Network variables
encoder_weights = tf.Variable(tf.random_normal(shape=(self.features.shape[1], n_dimensions)))
encoder_bias = tf.Variable(tf.zeros(shape=[n_dimensions]))
decoder_weights = tf.Variable(tf.random_normal(shape=(n_dimensions, self.features.shape[1])))
decoder_bias = tf.Variable(tf.zeros(shape=[self.features.shape[1]]))
# Encoder part
encoding = tf.nn.sigmoid(tf.add(tf.matmul(X, encoder_weights), encoder_bias))
# Decoder part
predicted_x = tf.nn.sigmoid(tf.add(tf.matmul(encoding, decoder_weights), decoder_bias))
# Define the cost function and optimizer to minimize squared error
cost = tf.reduce_mean(tf.pow(tf.subtract(predicted_x, X), 2))
optimizer = tf.train.AdamOptimizer().minimize(cost)
with tf.Session(graph=graph) as session:
# Initialize global variables
session.run(tf.global_variables_initializer())
for batch_x in batch_generator(self.features):
self.encoder['weights'], self.encoder['bias'], _ = session.run([encoder_weights, encoder_bias, optimizer],
feed_dict={X: batch_x})
这里没什么特别要说的,代码本身就已经给出了解释。我们可以看到在偏置中的编码器权重,然后我们可以在下面的 reduce 方法中给该数据降维。def reduce(self):
return np.add(np.matmul(self.features, self.encoder['weights']), self.encoder['bias'])
没错,就是这么简单 :)
让我们看看它的效果(批大小:50,1000 epoch)。
图 7:这个简单自编码器在鸢尾花数据集上的输出
我们可以继续调整批大小、epoch 数和不同的优化器,甚至无需改变架构我们就能得到不同的结果。
注意这里我给超参数随便选择了一些值,在真实场景中,我们需要通过交叉验证或测试数据来检验我们的结果,并借此找到最优的设置。
结语 这样的文章往往会通过某种形式的对比表格收尾,看看它们长处短处之类的。但那正好不是我想做的事情。
我的目标是深入到这些方法内部,让读者可以自己明白它们各自的优势和劣势。
我希望你喜欢这篇文章,并且能从中获益。现在回到文章开始处的问题,你知道它们的答案了吗?选自Medium
机器之心编译194收藏分享举报文章被以下专栏收录关注人工智能学术和技术实现推荐阅读{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&isPending&:false,&contributes&:[{&sourceColumn&:{&lastUpdated&:,&description&:&提供专业的前沿科技信息&,&permission&:&COLUMN_PUBLIC&,&memberId&:,&contributePermission&:&COLUMN_PUBLIC&,&translatedCommentPermission&:&all&,&canManage&:true,&intro&:&关注人工智能学术和技术实现&,&urlToken&:&jiqizhixin&,&id&:23235,&imagePath&:&v2-d50a7b9dbdd.jpg&,&slug&:&jiqizhixin&,&applyReason&:&0&,&name&:&机器之心&,&title&:&机器之心&,&url&:&https:\u002F\\u002Fjiqizhixin&,&commentPermission&:&COLUMN_ALL_CAN_COMMENT&,&canPost&:true,&created&:,&state&:&COLUMN_NORMAL&,&followers&:54314,&avatar&:{&id&:&v2-d50a7b9dbdd&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&activateAuthorRequested&:false,&following&:false,&imageUrl&:&https:\u002F\\u002Fv2-d50a7b9dbdd_l.jpg&,&articlesCount&:267},&state&:&accepted&,&targetPost&:{&titleImage&:&https:\u002F\\u002Fv2-dc136fd5cb6daed67f9241a_r.jpg&,&lastUpdated&:,&imagePath&:&v2-dc136fd5cb6daed67f9241a.jpg&,&permission&:&ARTICLE_PUBLIC&,&topics&:[4,155423],&summary&:&Pythonista 数据科学家 Elior Cohen 近日在 Medium 上发文解读了最常见的三大降维技术:PCA、t-SNE 和自编码器。为了帮助理解,他还为其中每种相关算法编写了代码(也发布在了 GitHub 上)。机器之心对本文进行了编译介绍。 代码地址:\u003Ca href=\&https:\\u002Feliorc\u002FMedium\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\&\u003Ehttps:\\u002Feliorc\u002FMedium\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\u003C\u002Fa\u003E…&,&copyPermission&:&ARTICLE_COPYABLE&,&translatedCommentPermission&:&all&,&likes&:0,&origAuthorId&:0,&publishedTime&:&T17:35:45+08:00&,&sourceUrl&:&&,&urlToken&:,&id&:3361460,&withContent&:false,&slug&:,&bigTitleImage&:true,&title&:&基于TensorFlow理解三大降维技术:PCA、t-SNE 和自编码器&,&url&:&\u002Fp\u002F&,&commentPermission&:&ARTICLE_ALL_CAN_COMMENT&,&snapshotUrl&:&&,&created&:,&comments&:0,&columnId&:0,&content&:&&,&parentId&:0,&state&:&ARTICLE_PUBLISHED&,&imageUrl&:&https:\u002F\\u002Fv2-dc136fd5cb6daed67f9241a_r.jpg&,&author&:{&bio&:&欢迎关注我们的微信公众号:机器之心(almosthuman2014)&,&isFollowing&:false,&hash&:&06a67981ced7a2e9f85c&,&uid&:493500,&isOrg&:true,&slug&:&ji-qi-zhi-xin-65&,&isFollowed&:false,&description&:&国内领先的前沿科技媒体和产业服务平台&,&name&:&机器之心&,&profileUrl&:&https:\u002F\\u002Forg\u002Fji-qi-zhi-xin-65&,&avatar&:{&id&:&v2-dd115d399e55c37e13890e&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:true,&isBanned&:false},&memberId&:,&excerptTitle&:&&,&voteType&:&ARTICLE_VOTE_CLEAR&},&id&:723688}],&title&:&基于TensorFlow理解三大降维技术:PCA、t-SNE 和自编码器&,&author&:&ji-qi-zhi-xin-65&,&content&:&\u003Cblockquote\u003EPythonista 数据科学家 Elior Cohen 近日在 Medium 上发文解读了最常见的三大降维技术:PCA、t-SNE 和自编码器。为了帮助理解,他还为其中每种相关算法编写了代码(也发布在了 GitHub 上)。机器之心对本文进行了编译介绍。\u003C\u002Fblockquote\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E代码地址:\u003Ca href=\&http:\u002F\\u002F?target=https%3A\\u002Feliorc\u002FMedium\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\& class=\& external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003E\u003Cspan class=\&invisible\&\u003Ehttps:\u002F\u002F\u003C\u002Fspan\u003E\u003Cspan class=\&visible\&\\u002Feliorc\u002FMediu\u003C\u002Fspan\u003E\u003Cspan class=\&invisible\&\u003Em\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\u003C\u002Fspan\u003E\u003Cspan class=\&ellipsis\&\u003E\u003C\u002Fspan\u003E\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E\n\u003C\u002Fp\u003E\u003Cp\u003E在这篇文章中,我将尽我所能揭秘三种降维技术:PCA、t-SNE 和自编码器。我做这件事的主要原因是基本上这些方法都被当作黑箱对待,因此有时候会被误用。理解它们将能让读者有办法决定在何时如何使用哪一种方法。\n\u003C\u002Fp\u003E\u003Cp\u003E为了实现这一目标,我将深入到每种方法的内部,并且将使用 TensorFlow 从零开始为每种方法编写代码(t-SNE 除外)。为什么选择 TensorFlow?因为其最常被用于深度学习领域,让我们能有点挑战。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E动机\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003E当处理真实问题和真实数据时,我们往往遇到维度高达数百万的高维数据。\n\u003C\u002Fp\u003E\u003Cp\u003E尽管在其原来的高维结构中,数据能够得到最好的表达,但有时候我们可能需要给数据降维。\n\u003C\u002Fp\u003E\u003Cp\u003E降维的需求往往与可视化有关(减少两三个维度,好让我们可以绘图),但这只是其中一个原因。\n\u003C\u002Fp\u003E\u003Cp\u003E有时候,我们认为性能比精度更重要,那么我们就可以将 1000 维的数据降至 10 维,从而让我们可以更快地对这些数据进行操作(比如计算距离)。\n\u003C\u002Fp\u003E\u003Cp\u003E有时候对降维的需求是真实存在的,而且有很多应用。\n\u003C\u002Fp\u003E\u003Cp\u003E在我们开始之前,先看一个问题:如果你要为以下案例选择一种降维技术,你会怎么选?\n\u003C\u002Fp\u003E\u003Cp\u003E1. 你的系统可以使用余弦相似度测量距离,但你需要将其可视化,以便不懂技术的董事会成员也能理解,这些人可能甚至从来没听说过余弦相似度;你会怎么做?\n\u003C\u002Fp\u003E\u003Cp\u003E2. 你有必要将数据的维度压缩到尽可能最低,你的限制是要保留大约 80% 的数据,你会怎么做?\n\u003C\u002Fp\u003E\u003Cp\u003E3. 你有一个数据库,其中的数据是耗费了大量时间收集的,而且还时不时有新的(相似类型的)数据加入。你需要降低你已有数据的维度,并且还要给到来的新数据降维,你会选择什么方法?\n\u003C\u002Fp\u003E\u003Cp\u003E这篇文章的目的是希望能帮助你更好地了解降维,以便你能轻松应对类似这样的问题。\n\u003C\u002Fp\u003E\u003Cp\u003E让我们从 PCA 开始吧。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003EPCA\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003EPCA,即主成分分析(Principal Component Analysis),可能是最古老的技巧了。\n\u003C\u002Fp\u003E\u003Cp\u003EPCA 已经得到了充分的研究,而且有很多方法可以实现这种解决方案,这里我们会谈到其中两种:Eigen 分解和奇异值分解(SVD),然后我们会在 TensorFlow 中实现其中的 SVD 方法。\n\u003C\u002Fp\u003E\u003Cp\u003E从现在起,假设我们的数据矩阵为 X,其 shape 为 (n, p),其中 n 是指样本的数量,而 p 是指维度。\n\u003C\u002Fp\u003E\u003Cp\u003E所以给定了 X 之后,这两种方法都要靠自己的方式找到一种操作并分解 X 的方法,以便接下来我们可以将分解后的结果相乘,从而以更少的维度表征最大化的信息。我知道,这听起来很唬人,但我们不会深入到数学证明中去,仅保留有助于我们理解这种方法的优缺点的部分。\n\u003C\u002Fp\u003E\u003Cp\u003E所以 Eigen 分解和 SVD 都是分解矩阵的方式,让我们看看它们可以在 PCA 中提供怎样的帮助,以及它们有怎样的联系。\n\u003C\u002Fp\u003E\u003Cp\u003E先看看下面的流程图,我会在后面解释。\n\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_b.png\& data-rawwidth=\&793\& data-rawheight=\&690\& class=\&origin_image zh-lightbox-thumb\& width=\&793\& data-original=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='793'%20height='690'&&\u002Fsvg&\& data-rawwidth=\&793\& data-rawheight=\&690\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&793\& data-original=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 1:PCA 工作流程\n\u003C\u002Fp\u003E\u003Cp\u003E所以,你为什么要关心这个?实际上,这两个流程中有一些非常基本的东西,能够给我们理解 PCA 提供很大帮助。\n\u003C\u002Fp\u003E\u003Cp\u003E你可以看到,这两种方法都是纯线性代数,这基本上就意味着:使用 PCA 就是在另一个角度看待真实数据——这是 PCA 独有的特性,因为其它方法都是始于低维数据的随机表征,然后使其表现得就像是高维数据。\n\u003C\u002Fp\u003E\u003Cp\u003E另外值得一提的是因为所有的运算都是线性的,所以 SVD 的速度非常快。\n\u003C\u002Fp\u003E\u003Cp\u003E另外,给定同样的数据,PCA 总是会给出同样的答案(而其它两种方法却不是这样)。\n\u003C\u002Fp\u003E\u003Cp\u003E注意我们在 SVD 中是怎样选择 r(r 是我们想要降低至的维度)的,以便将 Σ 中的大部分值保留到更低的维度上。\n\u003C\u002Fp\u003E\u003Cp\u003EΣ 则有一些特别之处。\n\u003C\u002Fp\u003E\u003Cp\u003EΣ 是一个对角矩阵(diagonal matrix),其中有 p(维度数)个对角值(被称为奇异值(singular value)),它们的大小表明了它们对保存信息的重要程度。\n\u003C\u002Fp\u003E\u003Cp\u003E所以我们可以选择降维到能保留给定比例的数据的维度数,后面我将通过代码说明。(比如让我们降维,但最多失去 15% 的数据。)\n\u003C\u002Fp\u003E\u003Cp\u003E你将看到,用 TensorFlow 写这个代码是很简单的,我们要编码的是一个带有 fit 方法和我们将提供维度的 reduce 方法的类。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E代码(PCA)\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003E设 self.X 包含数据且 self.dtype=tf.float32,那么 fit 方法看起来就是这样:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-python3\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Edef\u003C\u002Fspan\u003E \u003Cspan class=\&nf\&\u003Efit\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E):\u003C\u002Fspan\u003E\n
\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Egraph\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Etf\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EGraph\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E()\u003C\u002Fspan\u003E\n
\u003Cspan class=\&k\&\u003Ewith\u003C\u002Fspan\u003E \u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Egraph\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eas_default\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E():\u003C\u002Fspan\u003E\n
\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EX\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Etf\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eplaceholder\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Edtype\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Eshape\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eshape\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E\n\n
\u003Cspan class=\&c1\&\u003E# Perform SVD\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Esingular_values\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Eu\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003E_\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Etf\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Esvd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EX\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E\n\n
\u003Cspan class=\&c1\&\u003E# Create sigma matrix\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Esigma\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Etf\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Ediag\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Esingular_values\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E\n\n
\u003Cspan class=\&k\&\u003Ewith\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Etf\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003ESession\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Egraph\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Egraph\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E)\u003C\u002Fspan\u003E \u003Cspan class=\&k\&\u003Eas\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Esession\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eu\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Esingular_values\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Esigma\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Esession\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Erun\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E([\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eu\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Esingular_values\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Esigma\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E],\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Efeed_dict\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EX\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E:\u003C\u002Fspan\u003E \u003Cspan class=\&bp\&\u003Eself\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Edata\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E})\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E所以 fit 的目标是创建我们后面要用到的 Σ 和 U。\n\u003C\u002Fp\u003E\u003Cp\u003E我们将从 tf.svd 行开始,这一行给了我们奇异值(就是图 1 中标记为 Σ 的对角值)和矩阵 U 和 V。\n\u003C\u002Fp\u003E\u003Cp\u003E然后 tf.diag 是 TensorFlow 的将一个 1D 向量转换成一个对角矩阵的方法,在我们的例子中会得到 Σ。\n\u003C\u002Fp\u003E\u003Cp\u003E在 fit 调用结束后,我们将得到奇异值、Σ 和 U。\n\u003C\u002Fp\u003E\u003Cp\u003E现在让我们实现 reduce。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Edef reduce(self, n_dimensions=None, keep_info=None):\n
if keep_info:\n
# Normalize singular values\n
normalized_singular_values = self.singular_values \u002F sum(self.singular_values)\n\n
# Create the aggregated ladder of kept information per dimension\n
ladder = np.cumsum(normalized_singular_values)\n\n
# Get the first index which is above the given information threshold\n
index = next(idx for idx, value in enumerate(ladder) if value &= keep_info) + 1\n
n_dimensions = index\n\n
with self.graph.as_default():\n
# Cut out the relevant part from sigma\n
sigma = tf.slice(self.sigma, [0, 0], [self.data.shape[1], n_dimensions])\n\n
pca = tf.matmul(self.u, sigma)\n\n
with tf.Session(graph=self.graph) as session:\n
return session.run(pca, feed_dict={self.X: self.data})\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E如你所见,reduce 既有 keep_info,也有 n_dimensions(我没有实现输入检查看是否只提供了其中一个)。\n\u003C\u002Fp\u003E\u003Cp\u003E如果我们提供 n_dimensions,它就会降维到那个数;但如果我们提供 keep_info(应该是 0 到 1 之间的一个浮点数),就说明了我们将从原来的数据中保存多少信息(假如是 0.9,就保存 90% 的数据)。\n\u003C\u002Fp\u003E\u003Cp\u003E在第一个 if 中,我们规范化并检查了需要多少了奇异值,基本上能从 keep_info 得知 n_dimensions。\n\u003C\u002Fp\u003E\u003Cp\u003E在这个图中,我们只需要从 Σ (sigma) 矩阵切下我们所需量的数据,然后执行矩阵乘法。\n\u003C\u002Fp\u003E\u003Cp\u003E现在让我们在鸢尾花数据集上试一试,这是一个 (150, 4) 的数据集,包含了三种鸢尾花。\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Efrom sklearn import datasets\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\ntf_pca = TF_PCA(iris_dataset.data, iris_dataset.target)\ntf_pca.fit()\npca = tf_pca.reduce(keep_info=0.9)
# Results in 2 dimensions\n\ncolor_mapping = {0: sns.xkcd_rgb['bright purple'], 1: sns.xkcd_rgb['lime'], 2: sns.xkcd_rgb['ochre']}\ncolors = list(map(lambda x: color_mapping[x], tf_pca.target))\n\nplt.scatter(pca[:, 0], pca[:, 1], c=colors)\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-0c9b6139debce731fed6bf060aa260cf_b.png\& data-rawwidth=\&1075\& data-rawheight=\&613\& class=\&origin_image zh-lightbox-thumb\& width=\&1075\& data-original=\&https:\u002F\\u002Fv2-0c9b6139debce731fed6bf060aa260cf_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='1075'%20height='613'&&\u002Fsvg&\& data-rawwidth=\&1075\& data-rawheight=\&613\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&1075\& data-original=\&https:\u002F\\u002Fv2-0c9b6139debce731fed6bf060aa260cf_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-0c9b6139debce731fed6bf060aa260cf_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 2:鸢尾花数据集 PCA 二维绘图\n\u003C\u002Fp\u003E\u003Cp\u003E还不错吧?\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003Et-SNE\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E相对于 PCA,t-SNE 是一种相对较新的方法,起源于 2008 年的论文《Visualizing Data using t-SNE》:\u003Ca href=\&http:\u002F\\u002F?target=http%3A\u002F\u002Fwww.jmlr.org\u002Fpapers\u002Fvolume9\u002Fvandermaaten08a\u002Fvandermaaten08a.pdf\& class=\& external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003E\u003Cspan class=\&invisible\&\u003Ehttp:\u002F\u002Fwww.\u003C\u002Fspan\u003E\u003Cspan class=\&visible\&\u003Ejmlr.org\u002Fpapers\u002Fvolume9\u003C\u002Fspan\u003E\u003Cspan class=\&invisible\&\u003E\u002Fvandermaaten08a\u002Fvandermaaten08a.pdf\u003C\u002Fspan\u003E\u003Cspan class=\&ellipsis\&\u003E\u003C\u002Fspan\u003E\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E\n\u003C\u002Fp\u003E\u003Cp\u003E它也比 PCA 更难理解,所以让我们一起坚持一下。\n\u003C\u002Fp\u003E\u003Cp\u003E我们对 t-SNE 的符号定义为:X 是原来的数据;P 是一个矩阵,显示了高维(原来的)空间中 X 中的点之间的亲和度(affinities,约等于距离);Q 也是一个矩阵,显示了低维空间中数据点之间的亲和度。如果你有 n 个数据样本,那么 Q 和 P 都是 n×n 的矩阵(从任意点到任意点的距离包含自身)。\n\u003C\u002Fp\u003E\u003Cp\u003E现在 t-SNE 有自己的「独特的」测量事物之间距离的方式(我们下面就会介绍)、一种测量高维空间中数据点之间的距离的方式、一种测量低维空间中数据点之间的距离的方式以及一种测量 P 和 Q 之间的距离的方式。\n\u003C\u002Fp\u003E\u003Cp\u003E根据原始论文,一个数据点 x_j 与另一个点 x_i 之间的相似度是 p_j|i,其定义为:「x_i 选取 x_j 为其近邻点(neighbor),而近邻点的选取与以 x_i 为中心的高斯分布概率密度成正比。」\n\u003C\u002Fp\u003E\u003Cp\u003E「这是什么意思!」不要担心,我前面说了,t-SNE 有自己测量距离的独特方式,所以让我们看看用于测量距离(亲和度)的公式,然后从中取出我们理解 t-SNE 的行为所需的见解。\n\u003C\u002Fp\u003E\u003Cp\u003E从高层面来讲,这就是算法的工作方式(注意和 PCA 不一样,这是一个迭代式的算法)。\n\n\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-32b7b2d0a3f8d2e408055_b.png\& data-rawwidth=\&781\& data-rawheight=\&806\& class=\&origin_image zh-lightbox-thumb\& width=\&781\& data-original=\&https:\u002F\\u002Fv2-32b7b2d0a3f8d2e408055_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='781'%20height='806'&&\u002Fsvg&\& data-rawwidth=\&781\& data-rawheight=\&806\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&781\& data-original=\&https:\u002F\\u002Fv2-32b7b2d0a3f8d2e408055_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-32b7b2d0a3f8d2e408055_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 3:t-SNE 工作流程\n\u003C\u002Fp\u003E\u003Cp\u003E让我们一步步地研究一下这个流程。\n\u003C\u002Fp\u003E\u003Cp\u003E这个算法有两个输入,一个是数据本身,另一个被称为困惑度(Perp)。\n\u003C\u002Fp\u003E\u003Cp\u003E简单来说,困惑度(perplexity)是指在优化过程中数据的局部(封闭点)和全局结构的焦点的平衡程度——本文建议将其保持在 5 到 50 之间。\n\u003C\u002Fp\u003E\u003Cp\u003E更高的困惑度意味着一个数据点会把更多的数据点看作是其紧密的近邻点,更低的困惑度就更少。\n\u003C\u002Fp\u003E\u003Cp\u003E困惑度会实际影响可视化的结果,而且你需要小心应对,因为它可能会在可视化低维数据时出现误导现象——我强烈推荐阅读这篇文章了解如何使用 t-SNE 困惑度:\u003Ca href=\&http:\u002F\\u002F?target=http%3A\u002F\u002Fdistill.pub\u002FFmisread-tsne\& class=\& external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003E\u003Cspan class=\&invisible\&\u003Ehttp:\u002F\u002F\u003C\u002Fspan\u003E\u003Cspan class=\&visible\&\u003Edistill.pub\u002FFmisrea\u003C\u002Fspan\u003E\u003Cspan class=\&invisible\&\u003Ed-tsne\u003C\u002Fspan\u003E\u003Cspan class=\&ellipsis\&\u003E\u003C\u002Fspan\u003E\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E,其中介绍了不同困惑度的影响。\n\u003C\u002Fp\u003E\u003Cp\u003E这种困惑度从何而来?它被用于求解式子 (1) 中的 σ_i,而且因为它们有单调的连接,所以可以通过二元搜索(binary search)找到。\n\u003C\u002Fp\u003E\u003Cp\u003E所以使用我们提供给算法的困惑度,我们基本上会找到不同的 σ_i。\n\u003C\u002Fp\u003E\u003Cp\u003E让我们看看公式为我们提供了哪些关于 t-SNE 的信息。\n\u003C\u002Fp\u003E\u003Cp\u003E在我们探索公式 (1) 和 (2) 之前,需要知道 p_ii 和 q_ii 被设置为 0(即使我们将它们应用到两个相似的点上,公式的输出也不会是 0,这只是给定的值)。\n\u003C\u002Fp\u003E\u003Cp\u003E所以看看公式 (1) 和 (2),我希望你注意到,当两个点很接近时(在高维表征中),分子的值大约为 1,而如果它们相距非常远,那么我们会接近无穷小——这将有助于我们后面理解成本函数。\n\u003C\u002Fp\u003E\u003Cp\u003E现在我们可以了解关于 t-SNE 的一些事情了。\n\u003C\u002Fp\u003E\u003Cp\u003E一是因为亲和度公式的构建方式,在 t-SNE 图中解读距离可能会出问题。\n\u003C\u002Fp\u003E\u003Cp\u003E这意味着聚类之间的距离和聚类大小可能被误导,并且也会受到所选择的困惑度的影响(在上面我推荐的文章中,你可以看到这些现象的可视化)。\n\u003C\u002Fp\u003E\u003Cp\u003E第二件要注意的事情是,怎么在等式 (1) 中我们基本上计算的是点之间的欧几里得距离?这方面 t-SNE 很强大,我们可以用任何我们喜欢的距离测量来取代它,比如余弦距离、Manhattan 距离,也可以使用任何你想用的测量方法(只要其保持空间度量(space metric),而且保持低维亲和度一样)——以欧几里得的方式会得到复杂的距离绘图。\n\u003C\u002Fp\u003E\u003Cp\u003E比如说,如果你是一位 CTO,你有一些数据需要根据余弦相似度测量距离,而你的 CEO 想要你通过图表的形式呈现这些数据。我不确定你是否有时间向董事会解释什么是余弦相似度以及解读聚类的方式,你可以直接绘制余弦相似度聚类,因为欧几里得距离聚类使用 t-SNE——要我说,这确实很酷。\n\u003C\u002Fp\u003E\u003Cp\u003E在代码中,你可以在 scikit-learn 中通过向 TSNE 方法提供一个距离矩阵来实现。\n\u003C\u002Fp\u003E\u003Cp\u003E现在,我们知道当 x_i 和 x_j 更近时,p_ij\u002Fq_ij 的值更大;相反则该值更小。\n\u003C\u002Fp\u003E\u003Cp\u003E让我们看看这会对我们的成本函数(被称为 KL 散度(Kullback–Leibler divergence))带来怎样的影响。让我们绘图,然后看看没有求和部分的公式 (3)。\n\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-aed4fea994a81bf7aae9f53a_b.png\& data-rawwidth=\&1101\& data-rawheight=\&603\& class=\&origin_image zh-lightbox-thumb\& width=\&1101\& data-original=\&https:\u002F\\u002Fv2-aed4fea994a81bf7aae9f53a_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='1101'%20height='603'&&\u002Fsvg&\& data-rawwidth=\&1101\& data-rawheight=\&603\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&1101\& data-original=\&https:\u002F\\u002Fv2-aed4fea994a81bf7aae9f53a_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-aed4fea994a81bf7aae9f53a_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 4:没有求和部分的 t-SNE 成本函数\n\u003C\u002Fp\u003E\u003Cp\u003E很难看明白这是啥?但我在上面给轴加了名字。\n\u003C\u002Fp\u003E\u003Cp\u003E如你所见,这个成本函数是不对称的。\n\u003C\u002Fp\u003E\u003Cp\u003E对于高维空间中临近的点,其得出了非常高的成本(p 轴),但这些点是低维空间中很远的点表示的;而在高维空间中远离的点则成本更低,它们则是用低维空间中临近的点表示的。\n\u003C\u002Fp\u003E\u003Cp\u003E这说明在 t-SNE 图中,距离解释能力的问题甚至还更多。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Emodel = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=5)\ntsne5 = model.fit_transform(iris_dataset.data)\n\nmodel = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=30)\ntsne30 = model.fit_transform(iris_dataset.data)\n\nmodel = TSNE(learning_rate=100, n_components=2, random_state=0, perplexity=50)\ntsne50 = model.fit_transform(iris_dataset.data)\n\nplt.figure(1)\nplt.subplot(311)\nplt.scatter(tsne5[:, 0], tsne5[:, 1], c=colors)\n\nplt.subplot(312)\nplt.scatter(tsne30[:, 0], tsne30[:, 1], c=colors)\n\nplt.subplot(313)\nplt.scatter(tsne50[:, 0], tsne50[:, 1], c=colors)\n\nplt.show()\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-7d284b97d9ed262a2d22f_b.png\& data-rawwidth=\&995\& data-rawheight=\&757\& class=\&origin_image zh-lightbox-thumb\& width=\&995\& data-original=\&https:\u002F\\u002Fv2-7d284b97d9ed262a2d22f_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='995'%20height='757'&&\u002Fsvg&\& data-rawwidth=\&995\& data-rawheight=\&757\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&995\& data-original=\&https:\u002F\\u002Fv2-7d284b97d9ed262a2d22f_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-7d284b97d9ed262a2d22f_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 5:在鸢尾花数据集上的 t-SNE,不同的困惑度\n\u003C\u002Fp\u003E\u003Cp\u003E正如我们从数学中了解到的那样,你可以看到给定一个好的困惑度,数据会聚类,但要注意超参数的敏感性(如果不给梯度下降提供学习率,我无法找到聚类)。\n\u003C\u002Fp\u003E\u003Cp\u003E在我们继续之前,我想说如果使用正确,t-SNE 会是一种非常强大的方法,而不会受到前面提及的负面影响,只是你要清楚如何使用它。\n\u003C\u002Fp\u003E\u003Cp\u003E接下来是自编码器。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E自编码器(Auto Encoders)\n\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003EPCA 和 t-SNE 是方法,而自编码器则是一系列的方法。\n\u003C\u002Fp\u003E\u003Cp\u003E自编码器是一种神经网络,其目标是通过使用比输入节点更少的隐藏节点(在编码器一端)预测输入(训练该网络使其输出尽可能与输入相似),为此该网络需要尽可能多地将信息编码到隐藏节点中。\n\u003C\u002Fp\u003E\u003Cp\u003E图 6 给出了一个用于 4 维鸢尾花数据集的基本自编码器,其中输入层到隐藏层之间的连接线被称为编码器(encoder),而隐藏层到输出层之间的线被称为解码器(decoder)。\n\n\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-d80bb595afcc30f92ecdc_b.png\& data-rawwidth=\&589\& data-rawheight=\&565\& class=\&origin_image zh-lightbox-thumb\& width=\&589\& data-original=\&https:\u002F\\u002Fv2-d80bb595afcc30f92ecdc_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='589'%20height='565'&&\u002Fsvg&\& data-rawwidth=\&589\& data-rawheight=\&565\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&589\& data-original=\&https:\u002F\\u002Fv2-d80bb595afcc30f92ecdc_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-d80bb595afcc30f92ecdc_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 6:用于鸢尾花数据集的基本自编码器\n\u003C\u002Fp\u003E\u003Cp\u003E所以为什么自编码器是一系列方法呢?因为我们仅有的约束条件是其输入层和输出层具有同样的维度,在两者之间,我们可以创建任何我们想要的可以最好地编码我们的高维数据的结构。\n\u003C\u002Fp\u003E\u003Cp\u003E自编码器始于一些随机的低维表征(z)并会通过梯度下降改变其输入层和隐藏层以及隐藏层和输出层之间连接的权重,从而找到它们的解。\n\u003C\u002Fp\u003E\u003Cp\u003E现在,我们对自编码器已经有了一定了解,因为我们可以控制该网络的内部,我们可以让编码器能挑选出特征之间的非常复杂的关系。\n\u003C\u002Fp\u003E\u003Cp\u003E自编码器还有一个加分项。因为在训练结束时,我们有与隐藏层的连接权重,所以我们可以在特定的输入上训练,如果后面我们遇到了另一个数据点,那么我们无需重新训练就可以使用这些权重进行降维——但这种操作要小心,只有当新数据点与我们训练所用的数据点类似时这才有效。\n\u003C\u002Fp\u003E\u003Cp\u003E在这种情况下,探索自编码器的数学可能很简单,但却没什么用处,因为对于每一种架构和我们选择的成本函数,其数学形式可能是不同的。\n\u003C\u002Fp\u003E\u003Cp\u003E但如果我们想一想自编码器权重的优化方式,我们会理解我们定义的成本函数具有非常重要的作用。\n\u003C\u002Fp\u003E\u003Cp\u003E因为自编码器会使用成本函数来确定其预测结果的质量,那么我们就可以使用这个功能来强化我们希望实现的东西。\n\u003C\u002Fp\u003E\u003Cp\u003E不管我们想要的是欧几里得距离还是其它测量,我们都可以通过成本函数、使用不同的距离方法、使用不对称函数和其它方法而将其反映到编码的数据上。\n\u003C\u002Fp\u003E\u003Cp\u003E而且因为自编码器本质上是神经网络,所以它还具有更大的力量,我们甚至可以在训练时给类和样本加权,从而为数据中的特定现象提供更大的重要性。\n\u003C\u002Fp\u003E\u003Cp\u003E这能给我们压缩数据的方式提供很大的灵活性。\n\u003C\u002Fp\u003E\u003Cp\u003E自编码器非常强大,而且在一些案例中能实现比其它方法更好的结果(谷歌搜一下「PCA vs Auto Encoders」,你就知道),所以它们肯定是一种有效的方法。\n\u003C\u002Fp\u003E\u003Cp\u003E让我们用 TensorFlow 实现一个基于鸢尾花数据集的基本自编码器,并且绘图。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E代码(自编码器)\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003E同样,我们将其分成了 fit 和 reduce。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Edef fit(self, n_dimensions):\n
graph = tf.Graph()\n
with graph.as_default():\n\n
# Input variable\n
X = tf.placeholder(self.dtype, shape=(None, self.features.shape[1]))\n\n
# Network variables\n
encoder_weights = tf.Variable(tf.random_normal(shape=(self.features.shape[1], n_dimensions)))\n
encoder_bias = tf.Variable(tf.zeros(shape=[n_dimensions]))\n\n
decoder_weights = tf.Variable(tf.random_normal(shape=(n_dimensions, self.features.shape[1])))\n
decoder_bias = tf.Variable(tf.zeros(shape=[self.features.shape[1]]))\n\n
# Encoder part\n
encoding = tf.nn.sigmoid(tf.add(tf.matmul(X, encoder_weights), encoder_bias))\n\n
# Decoder part\n
predicted_x = tf.nn.sigmoid(tf.add(tf.matmul(encoding, decoder_weights), decoder_bias))\n\n
# Define the cost function and optimizer to minimize squared error\n
cost = tf.reduce_mean(tf.pow(tf.subtract(predicted_x, X), 2))\n
optimizer = tf.train.AdamOptimizer().minimize(cost)\n\n
with tf.Session(graph=graph) as session:\n
# Initialize global variables\n
session.run(tf.global_variables_initializer())\n\n
for batch_x in batch_generator(self.features):\n
self.encoder['weights'], self.encoder['bias'], _ = session.run([encoder_weights, encoder_bias, optimizer],\n
feed_dict={X: batch_x})\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E这里没什么特别要说的,代码本身就已经给出了解释。我们可以看到在偏置中的编码器权重,然后我们可以在下面的 reduce 方法中给该数据降维。\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Edef reduce(self):\n
return np.add(np.matmul(self.features, self.encoder['weights']), self.encoder['bias'])\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E没错,就是这么简单 :)\n\u003C\u002Fp\u003E\u003Cp\u003E让我们看看它的效果(批大小:50,1000 epoch)。\n\n\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-c7e3a5af745cb0332fd4_b.png\& data-rawwidth=\&1005\& data-rawheight=\&564\& class=\&origin_image zh-lightbox-thumb\& width=\&1005\& data-original=\&https:\u002F\\u002Fv2-c7e3a5af745cb0332fd4_r.png\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='1005'%20height='564'&&\u002Fsvg&\& data-rawwidth=\&1005\& data-rawheight=\&564\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&1005\& data-original=\&https:\u002F\\u002Fv2-c7e3a5af745cb0332fd4_r.png\& data-actualsrc=\&https:\u002F\\u002Fv2-c7e3a5af745cb0332fd4_b.png\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E图 7:这个简单自编码器在鸢尾花数据集上的输出\n\u003C\u002Fp\u003E\u003Cp\u003E我们可以继续调整批大小、epoch 数和不同的优化器,甚至无需改变架构我们就能得到不同的结果。\n\u003C\u002Fp\u003E\u003Cp\u003E注意这里我给超参数随便选择了一些值,在真实场景中,我们需要通过交叉验证或测试数据来检验我们的结果,并借此找到最优的设置。\n\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E结语\u003C\u002Fb\u003E \u003C\u002Fp\u003E\u003Cp\u003E这样的文章往往会通过某种形式的对比表格收尾,看看它们长处短处之类的。但那正好不是我想做的事情。\n\u003C\u002Fp\u003E\u003Cp\u003E我的目标是深入到这些方法内部,让读者可以自己明白它们各自的优势和劣势。\n\u003C\u002Fp\u003E\u003Cp\u003E我希望你喜欢这篇文章,并且能从中获益。现在回到文章开始处的问题,你知道它们的答案了吗?\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Ca href=\&http:\u002F\\u002F?target=https%3A\\u002Ftowards-data-science\u002Freducing-dimensionality-from-dimensionality-reduction-techniques-f658aec24dfe\& class=\& external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003E\u003Cspan class=\&invisible\&\u003Ehttps:\u002F\u002F\u003C\u002Fspan\u003E\u003Cspan class=\&visible\&\\u002Ftowards-data\u003C\u002Fspan\u003E\u003Cspan class=\&invisible\&\u003E-science\u002Freducing-dimensionality-from-dimensionality-reduction-techniques-f658aec24dfe\u003C\u002Fspan\u003E\u003Cspan class=\&ellipsis\&\u003E\u003C\u002Fspan\u003E\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E\u003C\u002Fp\u003E\u003Cp\u003E选自Medium
\u003Cb\u003E机器之心编译\u003C\u002Fb\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T09:35:45.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:7,&collapsedCount&:0,&likeCount&:194,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:true,&rating&:&none&,&titleImage&:&https:\u002F\\u002Fv2-dc136fd5cb6daed67f9241a_r.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&reviewers&:[],&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&TensorFlow&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&机器学习&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&数据降维&}],&adminClosedComment&:false,&titleImageSize&:{&width&:2000,&height&:720},&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&tipjarState&:&inactivated&,&annotationAction&:[],&sourceUrl&:&&,&pageCommentsCount&:7,&hasPublishingDraft&:false,&snapshotUrl&:&&,&publishedTime&:&T17:35:45+08:00&,&url&:&\u002Fp\u002F&,&lastestLikers&:[{&bio&:&&,&isFollowing&:false,&hash&:&85fb8e2cace4db2bb63566a1&,&uid&:24,&isOrg&:false,&slug&:&tian-shi-89&,&isFollowed&:false,&description&:&&,&name&:&天使&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Ftian-shi-89&,&avatar&:{&id&:&da8e974dc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&通信工程&,&isFollowing&:false,&hash&:&c64813efee9e36a2b236dce2c27b8a7b&,&uid&:32,&isOrg&:false,&slug&:&zhang-ying-78-47&,&isFollowed&:false,&description&:&言语从来没能将我的情感表达千万分之一。&,&name&:&张颖&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhang-ying-78-47&,&avatar&:{&id&:&eef110cd465adae92b1c7&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&怕什么真理无穷 进一寸有一寸的欢喜&,&isFollowing&:false,&hash&:&d109da5f8b64ef&,&uid&:013300,&isOrg&:false,&slug&:&zhou-zhi-ling-93-94&,&isFollowed&:false,&description&:&&,&name&:&机灵&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhou-zhi-ling-93-94&,&avatar&:{&id&:&v2-45b668a650cb30da7b9635&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&乐观向上,追求自由,勇于探索的青年。&,&isFollowing&:false,&hash&:&69bef87fa1911969aeae9&,&uid&:68,&isOrg&:false,&slug&:&huang-yun-99-93&,&isFollowed&:false,&description&:&爱好广泛,诸如阅读、运动、健身、摄影、旅游、骑行、电影等,对世界充满好奇。生命不息,探索不止!&,&name&:&黄云&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fhuang-yun-99-93&,&avatar&:{&id&:&v2-49eaea783ec3d0ae1bc707&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&&,&isFollowing&:false,&hash&:&dcd86a0aaea2&,&uid&:76,&isOrg&:false,&slug&:&liu-liu-32-71-71&,&isFollowed&:false,&description&:&&,&name&:&六六&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fliu-liu-32-71-71&,&avatar&:{&id&:&da8e974dc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}],&summary&:&\u003Cimg src=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_200x112.png\& data-rawwidth=\&793\& data-rawheight=\&690\& class=\&origin_image inline-img zh-lightbox-thumb\& data-original=\&https:\u002F\\u002Fv2-c6b4d43f0a375f9e990a_r.png\&\u003EPythonista 数据科学家 Elior Cohen 近日在 Medium 上发文解读了最常见的三大降维技术:PCA、t-SNE 和自编码器。为了帮助理解,他还为其中每种相关算法编写了代码(也发布在了 GitHub 上)。机器之心对本文进行了编译介绍。 代码地址:\u003Ca href=\&https:\\u002Feliorc\u002FMedium\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\&\u003Ehttps:\\u002Feliorc\u002FMedium\u002Fblob\u002Fmaster\u002FPCA-tSNE-AE.ipynb\u003C\u002Fa\u003E…&,&reviewingCommentsCount&:0,&meta&:{&previous&:null,&next&:null},&annotationDetail&:null,&commentsCount&:7,&likesCount&:194,&FULLINFO&:true}},&User&:{&ji-qi-zhi-xin-65&:{&isFollowed&:false,&name&:&机器之心&,&headline&:&国内领先的前沿科技媒体和产业服务平台&,&avatarUrl&:&https:\u002F\\u002F50\u002Fv2-dd115d399e55c37e13890e_s.jpg&,&isFollowing&:false,&type&:&org&,&slug&:&ji-qi-zhi-xin-65&,&bio&:&欢迎关注我们的微信公众号:机器之心(almosthuman2014)&,&hash&:&06a67981ced7a2e9f85c&,&uid&:493500,&isOrg&:true,&description&:&国内领先的前沿科技媒体和产业服务平台&,&badge&:{&identity&:null,&bestAnswerer&:null},&profileUrl&:&https:\u002F\\u002Forg\u002Fji-qi-zhi-xin-65&,&avatar&:{&id&:&v2-dd115d399e55c37e13890e&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:true,&isBanned&:false}},&Comment&:{},&favlists&:{}},&me&:{},&global&:{&experimentFeatures&:{&ge3&:&ge3_9&,&ge2&:&ge2_1&,&nwebStickySidebar&:&sticky&,&androidPassThroughPush&:&all&,&newMore&:&new&,&liveReviewBuyBar&:&live_review_buy_bar_2&,&liveStore&:&ls_a2_b2_c1_f2&,&qawebThumbnailAbtest&:&old&,&searchHybridTabs&:&without-tabs&,&iOSEnableFeedModuleWWANAritclePreRender&:&iOS_FeedModule_WWAN_PreRender_Enable&,&isOffice&:&false&,&liveDetailWechatBanner&:&Live_detail_wechat_banner_1&,&newLiveFeedMediacard&:&old&,&homeUi2&:&default&,&showVideoUploadAttention&:&false&,&recommendationAbtest&:&new&,&marketTab&:&market_tab_old&,&qrcodeLogin&:&qrcode&,&isShowUnicomFreeEntry&:&unicom_free_entry_off&,&newMobileColumnAppheader&:&new_header&,&androidDbRecommendAction&:&open&,&zcmLighting&:&zcm&,&favAct&:&default&,&appStoreRateDialog&:&close&,&mobileQaPageProxyHeifetz&:&m_qa_page_nweb&,&default&:&None&,&androidDbFeedRepinSelection&:&open&,&wechatShareModal&:&wechat_share_modal_show&,&qaStickySidebar&:&sticky_sidebar&,&androidProfilePanel&:&panel_b&,&nwebWriteAnswer&:&experiment&}},&columns&:{&next&:{}},&columnPosts&:{},&columnSettings&:{&colomnAuthor&:[],&uploadAvatarDetails&:&&,&contributeRequests&:[],&contributeRequestsTotalCount&:0,&inviteAuthor&:&&},&postComments&:{},&postReviewComments&:{&comments&:[],&newComments&:[],&hasMore&:true},&favlistsByUser&:{},&favlistRelations&:{},&promotions&:{},&switches&:{&couldSetPoster&:false},&draft&:{&titleImage&:&&,&titleImageSize&:{},&isTitleImageFullScreen&:false,&canTitleImageFullScreen&:false,&title&:&&,&titleImageUploading&:false,&error&:&&,&content&:&&,&draftLoading&:false,&globalLoading&:false,&pendingVideo&:{&resource&:null,&error&:null}},&drafts&:{&draftsList&:[],&next&:{}},&config&:{&userNotBindPhoneTipString&:{}},&recommendPosts&:{&articleRecommendations&:[],&columnRecommendations&:[]},&env&:{&edition&:{&baidu&:false,&yidianzixun&:false,&qqnews&:false},&isAppView&:false,&appViewConfig&:{&content_padding_top&:128,&content_padding_bottom&:56,&content_padding_left&:16,&content_padding_right&:16,&title_font_size&:22,&body_font_size&:16,&is_dark_theme&:false,&can_auto_load_image&:true,&app_info&:&OS=iOS&},&isApp&:false,&userAgent&:{&ua&:&Mozilla\u002F5.0 (compatible, MSIE 11, Windows NT 6.3; Trident\u002F7.0; rv:11.0) like Gecko&,&browser&:{&name&:&IE&,&version&:&11&,&major&:&11&},&engine&:{&version&:&7.0&,&name&:&Trident&},&os&:{&name&:&Windows&,&version&:&8.1&},&device&:{},&cpu&:{}}},&message&:{&newCount&:0},&pushNotification&:{&newCount&:0}}}

我要回帖

更多关于 eclipse中tensorflow 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信