tf 如何进行svd_基于TensorFlow理解三大降维技术:PCA、t

本文深入探讨了PCA、t-SNE和自编码器三种常见的降维技术,并提供了使用TensorFlow从零开始实现PCA(重点使用SVD方法)的代码示例。文章旨在帮助读者理解这些方法的内部运作,以便在实际问题中选择合适的技术。PCA通过Eigen分解和SVD实现,t-SNE是一种迭代算法,侧重于数据的局部和全局结构。此外,文章还讨论了降维在可视化、性能提升等方面的应用场景。
摘要由CSDN通过智能技术生成

选自medium

机器之心编译

参与:Panda

Pythonista 数据科学家 Elior Cohen 近日在 Medium 上发文解读了最常见的三大降维技术:PCA、t-SNE 和自编码器。为了帮助理解,他还为其中每种相关算法编写了代码(也发布在了 GitHub 上)。机器之心对本文进行了编译介绍。

代码地址:https://github.com/eliorc/Medium/blob/master/PCA-tSNE-AE.ipynb

在这篇文章中,我将尽我所能揭秘三种降维技术:PCA、t-SNE 和自编码器。我做这件事的主要原因是基本上这些方法都被当作黑箱对待,因此有时候会被误用。理解它们将能让读者有办法决定在何时如何使用哪一种方法。

为了实现这一目标,我将深入到每种方法的内部,并且将使用 TensorFlow 从零开始为每种方法编写代码(t-SNE 除外)。为什么选择 TensorFlow?因为其最常被用于深度学习领域,让我们能有点挑战。

动机

当处理真实问题和真实数据时,我们往往遇到维度高达数百万的高维数据。

尽管在其原来的高维结构中,数据能够得到最好的表达,但有时候我们可能需要给数据降维。

降维的需求往往与可视化有关(减少两三个维度,好让我们可以绘图),但这只是其中一个原因。

有时候,我们认为性能比精度更重要,那么我们就可以将 1000 维的数据降至 10 维,从而让我们可以更快地对这些数据进行操作(比如计算距离)。

有时候对降维的需求是真实存在的,而且有很多应用。

在我们开始之前,先看一个问题:如果你要为以下案例选择一种降维技术,你会怎么选?

1. 你的系统可以使用余弦相似度测量距离,但你需要将其可视化,以便不懂技术的董事会成员也能理解,这些人可能甚至从来没听说过余弦相似度;你会怎么做?

2. 你有必要将数据的维度压缩到尽可能最低,你的限制是要保留大约 80% 的数据,你会怎么做?

3. 你有一个数据库,其中的数据是耗费了大量时间收集的,而且还时不时有新的(相似类型的)数据加入。你需要降低你已有数据的维度,并且还要给到来的新数据降维,你会选择什么方法?

这篇文章的目的是希望能帮助你更好地了解降维,以便你能轻松应对类似这样的问题。

让我们从 PCA 开始吧。

PCA

PCA,即主成分分析(Principal Component Analysis),可能是最古老的技巧了。

PCA 已经得到了充分的研究,而且有很多方法可以实现这种解决方案,这里我们会谈到其中两种:Eigen 分解和奇异值分解(SVD),然后我们会在 TensorFlow 中实现其中的 SVD 方法。

从现在起,假设我们的数据矩阵为 X,其 shape 为 (n, p),其中 n 是指样本的数量,而 p 是指维度。

所以给定了 X 之后,这两种方法都要靠自己的方式找到一种操作并分解 X 的方法,以便接下来我们可以将分解后的结果相乘,从而以更少的维度表征最大化的信息。我知道,这听起来很唬人,但我们不会深入到数学证明中去,仅保留有助于我们理解这种方法的优缺点的部分。

所以 Eigen 分解和 SVD 都是分解矩阵的方式,让我们看看它们可以在 PCA 中提供怎样的帮助,以及它们有怎样的联系。

先看看下面的流程图,我会在后面解释。

图 1:PCA 工作流程

所以,你为什么要关心这个?实际上,这两个流程中有一些非常基本的东西,能够给我们理解 PCA 提供很大帮助。

你可以看到,这两种方法都是纯线性代数,这基本上就意味着:使用 PCA 就是在另一个角度看待真实数据--这是 PCA 独有的特性,因为其它方法都是始于低维数据的随机表征,然后使其表现得就像是高维数据。

另外值得一提的是因为所有的运算都是线性的,所以 SVD 的速度非常快。

另外,给定同样的数据,PCA 总是会给出同样的答案(而其它两种方法却不是这样)。

注意我们在 SVD 中是怎样选择 r(r 是我们想要降低至的维度)的,以便将 Σ 中的大部分值保留到更低的维度上。

Σ 则有一些特别之处。

Σ 是一个对角矩阵(diagonal matrix),其中有 p(维度数)个对角值(被称为奇异值(singular value)),它们的大小表明了它们对保存信息的重要程度。

所以我们可以选择降维到能保留给定比例的数据的维度数,后面我将通过代码说明。(比如让我们降维,但最多失去 15% 的数据。)

你将看到,用 TensorFlow 写这个代码是很简单的,我们要编码的是一个带有 fit 方法和我们将提供维度的 reduce 方法的类。

代码(PCA)

设 self.X 包含数据且 self.dtype=tf.float32,那么 fit 方法看起来就是这样:def fit(self):self.graph = tf.Graph()with self.graph.as_default():self.X = tf.placeholder(self.dtype, shape=self.data.shape)#Perform SVDsingular_values, u, _ = tf.svd(self.X)#Create sigma matrixsigma = tf.diag(singular_values)with tf.Session(graph=self.graph)as session:self.u, self.singular_values, self.sigma = session.run([u, singular_values, sigma],feed_dict={self.X: self.data})

所以 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 valuesnormalized_singular_values = self.singular_values / sum(self.singular_values)#Create the aggregated ladder of kept information per dimensionladder = np.cumsum(normalized_singular_values)#Get the first index which is above the given information thresholdindex = next(idx for idx, value in enumerate(ladder)if value >= keep_info) + 1n_dimensions = indexwith self.graph.as_default():#Cut out the relevant part from sigmasigma = tf.slice(self.sigma, [0, 0], [self.data.shape[1], n_dimensions])#PCApca = 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 datasetsimport matplotlib.pyplot as pltimport seaborn as snstf_pca = TF_PCA(iris_dataset.data, iris_dataset.target)tf_pca.fit()pca = tf_pca.reduce(keep_info=0.9) # Results in 2 dimensionscolor_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》:http://www.jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf

它也比 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 之间。

更高的困惑度意味着一个数据点会把更多的数据点看作是其紧密的近邻点,更低的困惑度就更少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值