在数据科学领域,降维是一个重要的步骤,它可以帮助减少数据的复杂性,提高模型的训练效率。随机投影是一种有效的降维方法,它通过引入一定程度的误差来换取更快的处理时间和更小的模型尺寸。本文将介绍两种类型的随机矩阵:高斯随机矩阵和稀疏随机矩阵,它们都用于控制数据的维度和分布,以保持数据集中任意两个样本之间的成对距离。因此,随机投影是一种适合于基于距离的方法的近似技术。
随机投影的效率背后的主要理论结果是约翰逊-林登斯特劳斯引理。这个引理表明,高维空间中的一组点可以嵌入到低维空间中,使得点之间的距离几乎被保留。用于嵌入的映射至少是Lipschitz连续的,甚至可以是正交投影。约翰逊-林登斯特劳斯引理提供了一个估计随机子空间最小尺寸的方法,以保证由随机投影引入的有界失真。
from sklearn.random_projection import johnson_lindenstrauss_min_dim
johnson_lindenstrauss_min_dim(n_samples=1e6, eps=0.5)
上述代码展示了如何使用约翰逊-林登斯特劳斯引理来估计所需的最小随机子空间尺寸。通过调整参数,可以得到不同精度要求下的子空间尺寸。
高斯随机投影通过将原始输入空间投影到一个随机生成的矩阵上来降低维度,该矩阵的分量是从正态分布 \(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)
print(X_new.shape)
这段代码首先生成了一个100x10000的随机矩阵,然后使用高斯随机投影变换器对其进行变换,最终得到的新矩阵的维度为100x3947。
稀疏随机投影通过使用稀疏随机矩阵来降低维度,这种矩阵是高斯随机投影矩阵的一个替代方案,它在保证相似嵌入质量的同时,更加内存高效,并且允许更快地计算投影数据。如果定义 \(s = 1 / density\),那么随机矩阵的元素是从以下分布中抽取的:
[
-sqrt(s/n_components) with probability 1/(2s),
0 with probability 1 - 1/s,
+sqrt(s/n_components) with probability 1/(2s)
]
其中 \(n_{components}\) 是投影子空间的大小。默认情况下,非零元素的密度设置为Ping Li等人推荐的最小密度 \(1 / sqrt(n_{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)
print(X_new.shape)
这段代码同样生成了一个100x10000的随机矩阵,然后使用稀疏随机投影变换器对其进行变换,最终得到的新矩阵的维度也是100x3947。
随机投影变换器具有一个可选参数 compute_inverse_components,当设置为True时,在拟合过程中创建随机组件矩阵后,变换器会计算这个矩阵的伪逆,并将其存储为 inverse_components。这个矩阵的形状为 \(n_{features} \times n_{components}\),并且始终是一个密集矩阵,无论组件矩阵是稀疏还是密集。因此,根据特征和组件的数量,它可能会使用大量的内存。
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)
print(X_new.shape)
X_new_inversed = transformer.inverse_transform(X_new)
print(X_new_inversed.shape)
X_new_again = transformer.transform(X_new_inversed)
np.allclose(X_new, X_new_again)
这段代码展示了如何使用逆变换功能。首先,它使用稀疏随机投影变换器对数据进行变换,然后使用逆变换方法将变换后的数据恢复到原始空间。最后,它验证了逆变换后的数据与原始变换前的数据是否接近。