非常大的数据集中的成对距离

Posted

技术标签:

【中文标题】非常大的数据集中的成对距离【英文标题】:Pairwise distance in very large datasets 【发布时间】:2021-07-18 17:41:15 【问题描述】:

我有一个大约 [5000000 x 6] 的数组,我只需要选择彼此相距一定距离的点(行)。

想法应该是:

从数据数组的第一行开始new_array

将 new_array 与数据数组中的第二行进行比较

如果它们之间的 pdist > tol,则将行追加到 new_array

将 new_array 与数据数组中的第三行进行比较

等等……

一个问题是 RAM 大小。即使在 pdist 中,我也无法一次比较所有行。

所以我一直在考虑将数据集拆分为较小的数据集,但后来我不知道如何检索数据集中行的索引信息。

我试过 scipy cdist、scipy euclidean、sklearn euclidean_distances、sklearnpaired_distances,下面的代码是我能得到的最快的。一开始它很快,但是在 40k 循环之后它变得非常慢。

xyTotal=np.random.random([5000000,6])
tol=0.5
for i,z in enumerate(xyTotal):
    if (pdist(np.vstack([np.array(ng),z]))>tol).all():
        ng.append(z)

对这个问题有什么建议吗?

编辑

ktree = BallTree(xyTotal, leaf_size=40,metric='euclidean')
btsem=[]
for i,j in enumerate(xyTotal):
    ktree.query_radius(j.reshape(1,-1),r=tol, return_distance=True)
    if (ktree.query_radius(j.reshape(1,-1),r=tol, count_only=True))==1:
        btsem.append(j)

这很快,但我只挑选异常值。当我到达靠近另一个点(即在一个小集群中)时,我不知道只选择一个点并留下其他点,因为我将获得集群中所有点的相同指标(它们都有距离相同)

【问题讨论】:

【参考方案1】:

计算速度很慢,因为算法的复杂性是二次的O(k * n * n) 其中 n 是 len(xyTotal)k 是条件为真的概率。因此,假设k=0.1n=5000000,运行时间将会很长(可能需要数小时的计算)。

希望您可以编写一个在O(n * log(n)) 时间运行的更好的实现。然而,这很难实现。您需要将ng 点添加到kd 树 中,然后您可以搜索最近邻 并检查与当前点的距离是否大于tol

请注意,您可以找到实现 k-d 树的 Python 模块,并且 SciPy 文档提供了用纯 Python 编写的 an example of implementation(因此可能效率不高)。

【讨论】:

你好,杰罗姆。我已经尝试过使用 sklearn NearestNeighbors 进行类似的操作。 outroneigh = NearestNeighbors(n_neighbors=2) filtered=[xyTotal[0]] for i,j in enumerate(xyTotal): outroneigh.fit(np.vstack([filtered,j])) if outroneigh.kneighbors(j.reshape(1,-1),return_distance=True)[0][0,1]>tol: print(i) filtered.append(j) 问题是为了获得与其他方法相同的答案,我需要继续拟合附加数组。这种拟合比 pdist 慢得多。 这不是append 的问题,而是np.vstack 从所有过去的值重建一个全新的数组。你不需要那个。实际上,append 也不需要。如果你想使用 Numpy 数组,你可以预先分配一个大数组,分配单元格并分割好的部分。请注意,在 CPython 列表中,我认为 append 应该以摊销的 O(1) 运行。您应该首先关注复杂性,然后再关注优化/矢量化。 我明白你的意思并同意。但我无法弄清楚如何不使用追加或重建数组,因为我必须测试一个数组中的点与另一个数组中的点并连接 if 条件. pdist 也仅适用于 ndarrays,因此我需要构建一个数组以传递给 pdist。但是,如果您告诉我用 KDTree 对整个数据数组进行一次拟合,我用 NearestNeighbors 尝试过一次。我试图获取每个点到所有点的距离,但结果不一样。我可以确定这样做关于离群点,我想要,但是当我有接近点时它会变得混乱,我可能想要。

以上是关于非常大的数据集中的成对距离的主要内容,如果未能解决你的问题,请参考以下文章

数据框列中的字符串列表行之间的成对距离

R中非常大的矩阵计算有效

在 scipy 中计算成对距离时出现内存错误

在R中聚类非常大的数据集

计算大量 GPS 坐标之间的成对路由距离

python中最快的成对距离度量