7.6. 随机投影#
sklearn.random_projection
模块实现了一种简单且计算高效的方法,通过牺牲一定的精度(作为额外的方差)来换取更快的处理时间和更小的模型尺寸,从而降低数据维度。此模块实现了两种类型的非结构化随机矩阵:高斯随机矩阵 和 稀疏随机矩阵。
随机投影矩阵的维度和分布受到控制,以保留数据集中任意两个样本之间的成对距离。因此,随机投影是一种适用于基于距离的方法的近似技术。
参考文献
Sanjoy Dasgupta. 2000. 随机投影实验。 刊于:第十六届人工智能不确定性会议论文集(UAI’00),Craig Boutilier 和 Moisés Goldszmidt(编)。Morgan Kaufmann Publishers Inc.,美国加利福尼亚州旧金山,143-151。
Ella Bingham 和 Heikki Mannila. 2001. 降维中的随机投影:图像和文本数据应用。 刊于:第七届 ACM SIGKDD 国际知识发现与数据挖掘会议论文集(KDD ‘01)。ACM,美国纽约州纽约市,245-250。
7.6.1. 约翰逊-林登施特劳斯引理#
随机投影效率背后的主要理论结果是约翰逊-林登施特劳斯引理(引自维基百科)
在数学中,约翰逊-林登施特劳斯引理是一个关于将高维空间中的点低失真嵌入到低维欧几里得空间的结果。该引理指出,高维空间中的一小组点可以嵌入到维度低得多的空间中,并且点之间的距离几乎得以保留。用于嵌入的映射至少是 Lipschitz 连续的,甚至可以是正交投影。
仅知道样本数量,sklearn.random_projection.johnson_lindenstrauss_min_dim
可以保守地估计随机子空间的最小尺寸,以保证由随机投影引入的失真在有界范围内。
>>> from sklearn.random_projection import johnson_lindenstrauss_min_dim
>>> johnson_lindenstrauss_min_dim(n_samples=1e6, eps=0.5)
np.int64(663)
>>> johnson_lindenstrauss_min_dim(n_samples=1e6, eps=[0.5, 0.1, 0.01])
array([ 663, 11841, 1112658])
>>> johnson_lindenstrauss_min_dim(n_samples=[1e4, 1e5, 1e6], eps=0.1)
array([ 7894, 9868, 11841])


示例
请参阅使用随机投影进行嵌入的约翰逊-林登施特劳斯界限,了解约翰逊-林登施特劳斯引理的理论解释以及使用稀疏随机矩阵进行的经验验证。
参考文献
Sanjoy Dasgupta 和 Anupam Gupta, 1999. 约翰逊-林登施特劳斯引理的一个基本证明。
7.6.2. 高斯随机投影#
GaussianRandomProjection
通过将原始输入空间投影到一个随机生成的矩阵上,从而降低维度,该矩阵的分量从以下分布 \(N(0, \frac{1}{n_{components}})\) 中抽取。
下面是一个小片段,展示如何使用高斯随机投影变换器
>>> import numpy as np
>>> from sklearn import random_projection
>>> X = np.random.rand(100, 10000)
>>> transformer = random_projection.GaussianRandomProjection()
>>> X_new = transformer.fit_transform(X)
>>> X_new.shape
(100, 3947)
7.6.3. 稀疏随机投影#
SparseRandomProjection
通过使用稀疏随机矩阵投影原始输入空间来降低维度。
稀疏随机矩阵是密集高斯随机投影矩阵的替代方案,它能保证相似的嵌入质量,同时更节省内存并允许更快地计算投影数据。
如果我们定义 s = 1 / density
,则随机矩阵的元素从以下分布中抽取:
其中 \(n_{\text{components}}\) 是投影子空间的大小。默认情况下,非零元素的密度设置为 Ping Li 等人推荐的最小密度:\(1 / \sqrt{n_{\text{features}}}\)。
下面是一个小片段,展示如何使用稀疏随机投影变换器
>>> import numpy as np
>>> from sklearn import random_projection
>>> X = np.random.rand(100, 10000)
>>> transformer = random_projection.SparseRandomProjection()
>>> X_new = transformer.fit_transform(X)
>>> X_new.shape
(100, 3947)
参考文献
D. Achlioptas. 2003. 数据库友好的随机投影:带有二元硬币的约翰逊-林登施特劳斯。 Journal of Computer and System Sciences 66 (2003) 671-687.
Ping Li, Trevor J. Hastie, and Kenneth W. Church. 2006. 非常稀疏的随机投影。 刊于:第12届 ACM SIGKDD 国际知识发现与数据挖掘会议论文集(KDD ‘06)。ACM,美国纽约州纽约市,287-296。
7.6.4. 逆变换#
随机投影变换器具有 compute_inverse_components
参数。当设置为 True 时,在拟合期间创建随机 components_
矩阵后,变换器会计算此矩阵的伪逆并将其存储为 inverse_components_
。inverse_components_
矩阵的形状为 \(n_{features} \times n_{components}\),并且它始终是密集矩阵,无论 components 矩阵是稀疏还是密集。因此,根据特征和分量的数量,它可能会占用大量内存。
当调用 inverse_transform
方法时,它会计算输入 X
与逆分量转置的乘积。如果逆分量在拟合期间已计算,则在每次调用 inverse_transform
时都会重用它们。否则,它们每次都会重新计算,这可能代价高昂。即使 X
是稀疏的,结果也始终是密集的。
下面是一个小代码示例,展示如何使用逆变换功能
>>> import numpy as np
>>> from sklearn.random_projection import SparseRandomProjection
>>> X = np.random.rand(100, 10000)
>>> transformer = SparseRandomProjection(
... compute_inverse_components=True
... )
...
>>> X_new = transformer.fit_transform(X)
>>> X_new.shape
(100, 3947)
>>> X_new_inversed = transformer.inverse_transform(X_new)
>>> X_new_inversed.shape
(100, 10000)
>>> X_new_again = transformer.transform(X_new_inversed)
>>> np.allclose(X_new, X_new_again)
True