我已经完成了一个包含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 distance(explained 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)
谢谢!