【问题标题】:How to optimize finding similarities?如何优化查找相似性?
【发布时间】:2014-05-31 16:49:53
【问题描述】:

我有一组由浮点向量表示的 30 000 个文档。所有向量都有 100 个元素。我可以通过在它们的向量之间使用余弦度量来比较它们来找到两个文档的相似性。问题是找到最相似的文档需要很长时间。有什么算法可以帮助我加快速度吗?

编辑

现在,我的代码只计算第一个向量和所有其他向量之间的余弦相似度。大约需要 3 秒。我想加快速度;)算法不一定要准确,但应该给出与完整搜索相似的结果。

每个向量的元素之和等于1。

start = time.time()

first = allVectors[0]
for vec in allVectors[1:]:
    cosine_measure(vec[1:], first[1:])

print str(time.time() - start)

【问题讨论】:

  • 也许你能告诉我们你做了什么?或者至少你采取了什么方法
  • 向量是否标准化为单位长度?
  • 元素之和等于 1。但如果有帮助,我可以将其标准化为 1 的长度。
  • 3 000 000 个值的 3 秒我认为相当不错。使用 map 和 numpy,你也许可以赢得半秒。使用 pypy 编译代码可能会让你再花半秒时间。
  • 我宁愿寻找一种算法不太准确但速度更快。 Python只是为了测试,我会用另一种语言来实现。

标签: algorithm optimization cosine-similarity


【解决方案1】:

locality sensitive hashing (LHS) 有帮助吗? 在 LHS 的情况下,散列函数以您选择的概率将相似的项目映射到彼此附近。据称它特别适合高维相似性搜索/最近邻搜索/近重复检测,在我看来,这正是您想要实现的目标。

另见How to understand Locality Sensitive Hashing?

【讨论】:

    【解决方案2】:

    如果你的向量被归一化,余弦与欧几里得距离有关:||a - b||² = (a - b)² = ||a||² + ||b||² - 2 ||a|| ||b|| cos(t) = 1 + 1 - 2 cos(t)。因此,您可以根据欧几里得最近邻重铸您的问题。

    kD 树是一种很好的方法,一种泛化二分搜索的空间数据结构 (http://en.wikipedia.org/wiki/K-d_tree)。无论如何,众所周知,kD 树在高维(您的情况)中效率低下,因此首选所谓的 best-bin-first-search (http://en.wikipedia.org/wiki/Best-bin-first_search)。

    【讨论】:

    • k-d 树不适合在高维空间中有效地找到最近邻。作为一般规则,如果维度为 k,则数据中的点数 N 应为 N >> 2k。引用自 Wikipedia,因此对于 30,000 个文档,k-d 树仅对 10 个维度有效。
    • @Daniel:完整阅读我的帖子。
    • 当答案仍然是“高效”时,我写了评论。
    • 是的,提到了 best-bin-first。
    【解决方案3】:

    有一篇论文How to Approximate the Inner-product: Fast Dynamic Algorithms for Euclidean Similarity 描述了如何快速逼近内积。如果这不够好或不够快,我建议建立一个包含所有文档的索引。类似于quadtree 但基于geodesic grid 的结构可能会非常有效,请参阅Indexing the Sphere with the Hierarchical Triangular Mesh

    更新:我完全忘记了您正在处理 100 个维度。索引高维数据是notoriously hard,我不确定索引一个球体将如何推广到 100 维。

    【讨论】:

      猜你喜欢
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      相关资源
      最近更新 更多