Scikit learn 可更新最近邻搜索

Scikit learn 可更新最近邻搜索,scikit-learn,nearest-neighbor,Scikit Learn,Nearest Neighbor,我正试图为最近邻搜索应用程序提出一个好的设计。这有点类似于这个问题: 在我的例子中,这将是在Python中,但主要的一点是,当新数据出现时,必须更新模型/索引。我现在正在和他玩,但我不认为这是一个很好的配合 应用程序的目标是: 用户输入一个查询,然后将显示现有数据集中的n个(可能固定为5个)最近邻。对于这一步,sklearn的这种搜索结构会有所帮助,但在添加新记录时必须重新生成。此外,这是第一次每次查询发生1次ste,因此与“立即”相比,可能会有点“慢”,如2-3秒 然后,用户可以单击其中一条

我正试图为最近邻搜索应用程序提出一个好的设计。这有点类似于这个问题:

在我的例子中,这将是在Python中,但主要的一点是,当新数据出现时,必须更新模型/索引。我现在正在和他玩,但我不认为这是一个很好的配合

应用程序的目标是:

用户输入一个查询,然后将显示现有数据集中的n个(可能固定为5个)最近邻。对于这一步,sklearn的这种搜索结构会有所帮助,但在添加新记录时必须重新生成。此外,这是第一次每次查询发生1次ste,因此与“立即”相比,可能会有点“慢”,如2-3秒

然后,用户可以单击其中一条记录并查看该记录的最近邻居,依此类推。这意味着我们现在在现有的数据集中,NNs可以预计算并存储在redis中(现在有20万条记录,但可以扩展到百万分之一或百万分之一)。这应该是非常快的浏览

但在这里,我将面临同样的问题,即如何更新预计算的数据,而不必对距离矩阵进行完整的重新计算,特别是因为新记录很少(比如每周100条)

是否存在用于可更新NN搜索的工具、方法或算法

4月3日编辑:

正如许多地方所指出的,KDTree或BallTree并不真正适合高维数据。我已经意识到,对于一个由200k条记录和512维数据组成的小数据集来说,蛮力的速度并不慢,大约550ms比750ms


然而,对于数百万以上的大型数据集,这个问题仍然没有解决。我看过datasketch LSH Forest,但在我的例子中,这似乎不够准确,或者我用错了。我们将就此提出一个单独的问题。

您应该了解FAISS及其IVFPQ方法 您可以为每次更新创建多个索引,并将它们与旧索引合并

支持添加新向量。Elasticsearch使用它作为他们的一部分,而且它是

一个警告:

HNSW算法允许增量添加点,但禁止删除和修改索引点

您还可以研究类似或的解决方案。

您可以尝试支持添加和近实时搜索向量的解决方案


以下是Milvus的示例。

关于您的最后一段:在构建有效的最近邻结构(如KD树)时,永远不会计算“完整”距离矩阵(在KD树的情况下,可以说甚至不是部分距离矩阵)。由于您的“新”数据是“基本”数据的一小部分,因此可以说是最简单的(对于可预见的未来,最有效的)方法是有两个最近邻数据结构,一个用于“基本”,一个用于“新”还有一个适配器,它隐藏了2个数据结构的复杂性。在适配器中,您可以同时查询这5个邻居,然后进行蛮力距离计算,以确定哪些是您的实际最近邻居。至少对于KD树,您遇到的基本问题是,尽管添加到现有树中很容易(也很快),随着时间的推移,这会导致不平衡的树,查找性能会下降。由于从头开始构建树相当快(类似于O(n logn)),流行的实现,如
scipy.spatial
中的KDtree不支持在初始构建后添加节点(在某种程度上,sklearn中的实现只是scipy中实现的包装,不确定是否仍然是这样)@Paul,是的,重新平衡在KD树中可能会成为一个问题,但只要新数据分布相当均匀或插入速度较慢,树就不会出现明显的不平衡。尽管如此,一种替代方法是每隔1000次左右插入重新创建树,有些实现甚至会进行“重新平衡”操作。另一种替代方法是我会使用另一棵树,比如R*树(R-star-tree)或简单的四叉树/八叉树/…(最快可达5或6维)。@TilmannZ我计划在sklearn.NearestNeights中使用BallTree作为算法,因为我有高维数据(512维,二进制)。但如果有更好的高维数据选项,这也是一个受欢迎的建议。我还没有看到如何在创建BallTree后更新它?IVFPQ支持增量索引,因此不需要多个索引。