我想快速计算平方欧几里得,如下所述:
注意1:我只对距离感兴趣,而不是RBF 内核。
注意2:这里我忽略numexpr
了,只直接使用numpy。
简而言之,我计算:
|| x - y ||^2 = ||x||^2 + ||y||^2 - 2. * (x @ y.T)
~10
与此相比,我能够更快地计算距离矩阵scipy.pdist
。但是,我观察到数值问题,如果我取平方根来获得欧几里德距离,情况会变得更糟。我的值大约为1E-8 - 1E-7
,应该完全为零(即重复点或到自身点的距离)。
问题:
有没有办法或想法来克服这些数值问题(最好在不牺牲太多评估速度的情况下)?或者数字问题是为什么这条路径首先没有被采用(例如 by scipy.pdist
)的原因?
例子:
这是一个显示数值问题的小代码示例(不是加速,请查看上面链接的 SO 线程的答案)。
import numpy as np
M = np.random.rand(1000, 10)
M_norm = np.sum(M**2, axis=1)
res = M_norm[:, np.newaxis] + M_norm[np.newaxis, :] - 2. * M @ M.T
unique = np.unique(np.diag(res)) # analytically all diag values are exactly zero
sqrt_unique = np.sqrt(unique)
print(unique)
print(sqrt_unique)
示例输出:
[-2.66453526e-15 -1.77635684e-15 -8.88178420e-16 -4.44089210e-16
0.00000000e+00 4.44089210e-16 8.88178420e-16 1.77635684e-15
3.55271368e-15]
[ nan nan nan nan
0.00000000e+00 2.10734243e-08 2.98023224e-08 4.21468485e-08
5.96046448e-08]
正如您所看到的,一些值也是负数(这导致在nan
取 sqrt 之后)。当然这些很容易捕捉——但是对于欧几里得情况来说,小的积极因素有很大的错误(例如abs_error=5.96046448e-08
)