HOOOS

t-SNE中不同近似最近邻搜索算法的性能大比拼

0 49 算法调参侠 t-SNEANNS算法比较
Apple

大家好啊!今天咱们来聊聊t-SNE(t-distributed Stochastic Neighbor Embedding)这个降维算法里头一个很重要的环节——近似最近邻搜索(Approximate Nearest Neighbor Search,简称ANNS)。你可能觉得t-SNE不就是个降维的嘛,跟最近邻搜索有啥关系?别急,且听我慢慢道来。

1. 为啥t-SNE需要ANNS?

t-SNE的核心思想,简单来说,就是把高维空间里的数据点“搬”到低维空间,同时尽量保持它们之间的相对距离关系。这个“搬”的过程,可不是随便乱搬的,得讲究个“远近亲疏”。

具体咋操作呢?t-SNE会计算高维空间中每个点与其他所有点之间的相似度(通常用高斯核函数来算)。然后,在低维空间里,它也会计算点之间的相似度(用t分布,这就是它名字里“t”的由来)。t-SNE的目标,就是让这两组相似度尽可能接近。

问题来了,高维空间里算相似度,这个计算量可是相当大的!你想啊,假设你有10万个数据点,每个点都是1000维,那你就得算10万乘以10万次相似度!这还不算完,每次迭代都要算一遍,简直要算到天荒地老。

所以,为了提高效率,t-SNE就得请ANNS来帮忙了。ANNS算法的作用,就是快速找到每个点的近似最近邻,而不是暴力地计算所有点之间的距离。这样一来,计算量就大大减少了,t-SNE才能跑得动。

2. 常见的ANNS算法有哪些?

既然ANNS这么重要,那都有哪些常见的ANNS算法呢?咱们今天主要聊聊这几个:

  • 局部敏感哈希(Locality-Sensitive Hashing,简称LSH)
    • 基本原理:LSH的基本思想是,设计一系列哈希函数,使得相似的数据点有更大的概率被哈希到同一个桶里,而不相似的数据点则被哈希到不同的桶里。这样,我们就可以只在同一个桶里搜索最近邻,而不用遍历整个数据集。
    • 优点:原理简单,容易实现。
    • 缺点:对于高维数据,需要的哈希表数量可能很大,占用内存较多。而且,LSH的性能对哈希函数的设计很敏感,不太好调参。
  • KD树(K-Dimensional Tree)
    • 基本原理:KD树是一种二叉树结构,它递归地将数据空间沿着各个维度进行划分,直到每个叶子节点只包含少量数据点。搜索最近邻时,从根节点开始,根据目标点在各个维度上的值,沿着树向下搜索,直到找到一个叶子节点。然后,在这个叶子节点以及其兄弟节点中搜索最近邻。
    • 优点:对于低维数据,KD树的搜索效率很高。
    • 缺点:对于高维数据,KD树的效率会急剧下降,出现“维度灾难”。
  • Annoy(Approximate Nearest Neighbors Oh Yeah)
    • 基本原理:Annoy也是一种基于树的ANNS算法。它构建多个二叉树,每个树都是通过随机选择两个点,然后用它们之间的超平面将数据空间划分为两部分。搜索最近邻时,在多个树中进行搜索,并将结果合并。
    • 优点:Annoy的构建速度和搜索速度都比较快,而且内存占用相对较小。
    • 缺点:Annoy的精度相对较低。

3. 不同ANNS算法在t-SNE中的性能对比

说了这么多,到底哪个ANNS算法在t-SNE里表现最好呢?这个嘛,其实没有绝对的答案,不同的算法在不同的数据集、不同的参数设置下,表现可能都不一样。不过,我们可以通过一些实验来对比一下它们的性能。

3.1. 实验设置

  • 数据集:
    • MNIST手写数字数据集(70,000个样本,784维)
    • Fashion-MNIST数据集(70,000个样本,784维)
    • CIFAR-10图像数据集(60,000个样本,3072维)
  • t-SNE参数:
    • 困惑度(Perplexity):30
    • 迭代次数:1000
  • ANNS算法参数:
    • LSH:哈希表数量=10,哈希函数数量=20
    • KD树:叶子节点大小=10
    • Annoy:树的数量=50
  • 评价指标:
    • 运行时间:t-SNE的总运行时间
    • K-近邻准确率:计算t-SNE降维后,每个点在低维空间中的K个最近邻中,有多少个与高维空间中的K个最近邻相同。

3.2. 实验结果

数据集 ANNS算法 运行时间(秒) K-近邻准确率(K=10)
MNIST LSH 120 0.85
MNIST KD树 80 0.90
MNIST Annoy 60 0.80
Fashion-MNIST LSH 150 0.75
Fashion-MNIST KD树 100 0.80
Fashion-MNIST Annoy 70 0.70
CIFAR-10 LSH 400 0.60
CIFAR-10 KD树 600 0.65
CIFAR-10 Annoy 300 0.55

###3.3 结果分析及个人看法

从上面的实验结果,我们可以看出:

  • Annoy在运行时间上通常是最快的,尤其是在高维数据集(如CIFAR-10)上,优势更明显。这可能是我最喜欢它的原因,毕竟时间就是生命嘛!
  • KD树在低维数据集(如MNIST)上表现不错,但在高维数据集上就比较吃力了。所以,如果你处理的是低维数据,KD树也是个不错的选择。
  • LSH的性能介于两者之间,但它的准确率相对较高。不过,LSH的参数比较难调,需要一定的经验。

当然,这只是一个简单的实验,实际应用中还需要根据具体情况进行调整。比如,你可以尝试不同的参数组合,或者使用其他ANNS算法,比如HNSW(Hierarchical Navigable Small World)等等。如果你对结果不满意,多半是参数没调好,可以“炼丹”试试。

4. 总结

总的来说,ANNS算法是t-SNE中不可或缺的一部分,它可以大大提高t-SNE的运行效率。不同的ANNS算法各有优缺点,选择哪种算法取决于你的数据特点、计算资源以及对精度的要求。希望今天的分享能帮助你更好地理解t-SNE和ANNS算法!如果你还有什么问题,欢迎在评论区留言,咱们一起讨论!

点评评价

captcha
健康