余弦相似度搜索的最大优化

时间:2018-10-28 10:56:57

标签: python search indexing time-complexity cosine-similarity

我已经完成了一个包含512维向量的预制数据库,并希望对它们实施高效的搜索算法。


研究

余弦相似度

在这种情况下,最佳算法将由cosine similarity度量组成,该度量基本上是归一化的点积,即:

def cossim(a, b): numpy.inner(a, b)/(numpy.linalg.norm(a)*numpy.linalg.norm(b))

在Python中。

线性搜索:

对于这种情况,最明显和最简单的搜索将是linear search O(n),它会遍历整个数据库并最终选择最相似的结果:

def linear_search(query_text, db):  # where db is set of 512D vectors
    most_similar = ("", 0)  # placeholder
    for query in db:
        current_sim = cossim(query_text, query)  # cossim function defined above
        if current_sim > most_similar[1]:
            most_similar = (query, current_sim)
    return most_similar[0] 

如您所见,应该对整个数据库进行扫描,如果数据库包含成千上万个向量,这可能效率很低。

准线性搜索:(部分解析)

余弦相似度和Euclidean distanceexplained very well in this answer)之间存在基本关系-我们可以从以下方程式得出欧几里得距离:

|a - b|² = 2(1 - cossim(a,b))

如答案中所述,随着两个向量之间的余弦变大,欧几里得距离将变小,因此我们可以将其转化为closest pairs of points问题,可以在quasilinear {{1}中解决}使用递归divide and conquer algorithm

因此,我必须实现自己的分治算法,才能找到最接近的512维向量对。

但是,不幸的是,由于向量的维数高,无法直接解决此问题。经典的分治法仅适用于二维。

为二进制搜索建立索引(未解决):

根据我的知识,从速度上优化余弦相似度搜索的最佳方法是建立索引,然后执行二进制搜索。

这里的主要问题是索引512维向量非常困难,除locality sensitive hashing之外,我还没有意识到可能对数据库索引有用或可能不有用的东西(主要问题是维数)降低,这可能会导致精度随之降低)。

有一种新的Angular Multi-index Hashing方法,不幸的是,如果向量是稀疏的,则仅适用于基于二进制的向量和维数independent similarity computation,而实际上不是。

最后,还有An Optimal Algorithm for Approximate Nearest Neighbor Searching in Fixed Dimensions,乍一看也许是最好的解决方案,但是在文档中指出:

  

不幸的是,查询时间中的指数因素确实暗示着我们   该算法不适用于较大的d值。但是,我们的   第6节中的经验证据表明,恒定因素是   比许多定理1中给出的界限小得多   我们测试过的发行版。我们的算法可以提供   与蛮力搜索相比,在高维度上有重大改进   为20,平均误差相对较小。

我们正在尝试对O(n log n)维向量进行查询,这将使上述算法效率极低。

有一个类似的question包含类似的问题,但不幸的是,尚未找到索引的解决方案。


问题

除了准线性搜索,是否有其他方法可以优化此类矢量的余弦相似性搜索?也许还有其他索引高维向量的方法吗?我相信以前已经做过这样的事情。

最近的解决方案

我相信我已经找到了可能是解决方案的解决方案,它包括用于索引几百维矢量数据库的随机分区树,我相信这正是我真正需要的。 (see here

谢谢!

0 个答案:

没有答案