在处理高维数据集时,经常需要将其降维到低维空间,以便于分析和可视化。随机投影是一种有效的降维技术,它能够在控制成对距离失真的前提下,将高维数据随机投影到低维欧几里得空间。本文将介绍随机投影的理论基础、代码实现和实验验证。
随机投影的核心思想是利用约翰逊-林登斯特劳斯(Johnson-Lindenstrauss)引理,该引理指出,对于任意高维数据集,都存在一个低维空间,使得数据在该空间中的成对距离与原始空间中的成对距离之间的差异被控制在一定范围内。具体来说,对于任意两个数据点u和v,它们的成对距离在投影后满足以下不等式:
(1 - eps) \|u - v\|^2 < \|p(u) - p(v)\|^2 < (1 + eps) \|u - v\|^2
其中,p是一个随机高斯投影矩阵,eps是允许的最大失真比例。为了保证eps-嵌入,所需的最小投影维度n_components可以通过以下公式计算:
n_components >= 4 log(n_samples) / (eps^2 / 2 - eps^3 / 3)
这意味着,随着样本数量n_samples的增加,为了保证相同的失真比例eps,所需的最小投影维度n_components会以对数级别增长。
以下是使用Python实现随机投影的示例代码。首先,需要导入必要的库,包括NumPy、matplotlib和sklearn等。然后,可以使用sklearn中的SparseRandomProjection类来实现随机投影。
import sys
import time
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import fetch_20newsgroups_vectorized, load_digits
from sklearn.metrics.pairwise import euclidean_distances
from sklearn.random_projection import SparseRandomProjection, johnson_lindenstrauss_min_dim
接下来,可以根据约翰逊-林登斯特劳斯引理计算所需的最小投影维度,并绘制相应的图表。
eps_range = np.linspace(0.1, 0.99, 5)
colors = plt.cm.Blues(np.linspace(0.3, 1.0, len(eps_range)))
n_samples_range = np.logspace(1, 9, 9)
plt.figure()
for eps, color in zip(eps_range, colors):
min_n_components = johnson_lindenstrauss_min_dim(n_samples_range, eps=eps)
plt.loglog(n_samples_range, min_n_components, color=color)
plt.legend([f"eps={eps:0.1f}" for eps in eps_range], loc="lower right")
plt.xlabel("Number of observations to eps-embed")
plt.ylabel("Minimum number of dimensions")
plt.title("Johnson-Lindenstrauss bounds: n_samples vs n_components")
plt.show()
通过上述代码,可以直观地看到,随着样本数量的增加,为了保证相同的失真比例,所需的最小投影维度会以对数级别增长。
为了验证随机投影的有效性,在20个新闻组文本数据集和手写数字数据集上进行了实验。对于20个新闻组数据集,选择了300个文档,每个文档包含约10万个特征。通过使用稀疏随机矩阵,将这些文档投影到不同维度的欧几里得空间中。对于手写数字数据集,选择了300个8x8灰度像素的数字图片,并将其随机投影到不同维度的空间中。
实验结果表明,当投影维度较小时,成对距离的分布较宽,许多成对距离被扭曲,分布呈现偏态(由于距离总是非负的,因此存在硬性的零比率限制)。而当投影维度较大时,扭曲得到控制,成对距离通过随机投影得到了很好的保留。
根据约翰逊-林登斯特劳斯引理,即使在只有300个样本的情况下,也需要至少几千个维度来保证较小的失真,而与原始数据集的特征数量无关。因此,在只有64个特征的输入空间中的手写数字数据集上使用随机投影是没有意义的,因为它不允许在这种情况下进行降维。另一方面,20个新闻组的维度可以从56,436降低到10,000,同时合理地保留成对距离。