【发布时间】:2021-03-30 02:22:06
【问题描述】:
给定两个大型 numpy 数组 A 和 B,它们的行数不同 (len(B) > len(A)) 但列数相同 (A.shape[1] = B.shape[1] = 3)。我想知道从B 获得一个子集C 的最快方法,该子集具有最小total 距离(所有成对距离的总和)到A 没有重复(每一对都必须是唯一的)。这意味着C 应该与A 具有相同的形状。
下面是我的代码,但有两个主要问题:
- 我不知道这是否给出了最小 total 距离
- 实际上我有一个比
np.linalg.norm更昂贵的距离计算函数(需要注意周期性边界条件)。我认为这绝对不是最快的方法,因为下面的代码每次调用一对距离计算函数。当我调用更昂贵的距离计算函数并且它将永远运行时,会有很大的开销。有什么建议吗?
import numpy as np
from operator import itemgetter
import random
import time
A = 100.*np.random.rand(1000, 3)
B = A.copy()
for (i,j), _ in np.ndenumerate(B):
B[i,j] += np.random.rand()
B = np.vstack([B, 100.*np.random.rand(500, 3)])
def calc_dist(x, y):
return np.linalg.norm(x - y)
t0 = time.time()
taken = []
for rowi in A:
res = min(((k, calc_dist(rowi, rowj)) for k, rowj in enumerate(B)
if k not in taken), key=itemgetter(1))
taken.append(res[0])
C = B[taken]
print(A.shape, B.shape, C.shape)
>>> (1000, 3) (1500, 3) (1000, 3)
print(time.time() - t0)
>>> 12.406389951705933
编辑:对于那些对昂贵的距离计算功能感兴趣的人,它使用ase 包(可以通过pip install ase 安装)
from ase.geometry import find_mic
def calc_mic_dist(x, y):
return find_mic(np.array([x]) - np.array([y]),
cell=np.array([[50., 0.0, 0.0],
[25., 45., 0.0],
[0.0, 0.0, 100.]]))[1][0]
【问题讨论】:
-
也许你可以向量化函数的计算,你能描述一下吗?
-
我添加了昂贵的距离计算功能。
-
只是想一想,如何对
A和B数组进行排序,并开始考虑B中的元素,从nth 元素中最接近的B中的子集C到A中的第一个元素? (附加细节:如果n的值大于len(B) - len(A),那么n可以向后移动作为一种折衷方案)我认为这种方式会产生最好的对并确保最小的距离。这有意义吗? -
是的,我确实同意 A 和 B 应该首先以某种方式排序,以便每一对始终是“完美”对,但我不太了解向后移动的部分。如果能写一些伪代码就更好理解了。
标签: python arrays performance numpy distance