【问题标题】:memory efficient euclidean distance measurement高效记忆欧几里得距离测量
【发布时间】:2018-09-09 08:11:55
【问题描述】:

我有 40,000 个点,我需要找出每对之间的欧几里得距离。上网后,我发现计算点对之间的欧式距离的有效方法是使用scipy.spatial distance.cdist。但是,既然没有。点数为 40,000,距离矩阵将占用大约 12 GB 的内存。

有没有办法在不影响计算速度的情况下减少存储距离矩阵所需的内存?距离矩阵的计算可以把数据类型改为float 32而不是float 64吗?

【问题讨论】:

  • 使用惰性求值?
  • 把你的点分成n个子数组,然后执行你的计算n^2次?类似于惰性评估,但您只需使用您提到的工具。
  • 我怀疑在幕后,cdist 在任何地方都使用 float64(C 双精度),所以这可能无关紧要。但这很容易通过较小的数组找到,同时使用两种输入数据类型,并比较内存使用情况。
  • 是的,您可以使用 float32。对这段代码稍加修改应该可以做你不想做的事情,而且比 cdist 更快。 stackoverflow.com/a/49490630/4045774
  • @Evert: cdist 使用float 64。当使用大点时,它会变成内存密集型

标签: python scipy


【解决方案1】:

类似cdist的方法

输出数据类型与输入相同。

import numpy as np
import numba as nb

@nb.njit(fastmath=True,parallel=True)
def calc_distance(vec_1,vec_2):
    res=np.empty((vec_1.shape[0],vec_2.shape[0]),dtype=vec_1.dtype)
    for i in nb.prange(vec_1.shape[0]):
        for j in range(vec_2.shape[0]):
            res[i,j]=np.sqrt((vec_1[i,0]-vec_2[j,0])**2+(vec_1[i,1]-vec_2[j,1])**2+(vec_1[i,2]-vec_2[j,2])**2)

    return res

没有重复的方法

@nb.njit(fastmath=True)
def calc_distance_pairs(vec):
  res=np.empty(((vec.shape[0]**2)//2-vec.shape[0]//2),dtype=vec.dtype)

  ii=0
  for i in range(vec.shape[0]):
    for j in range(i+1,vec.shape[0]):
      res[ii]=np.sqrt((vec[i,0]-vec[j,0])**2+(vec[i,1]-vec[j,1])**2+(vec[i,2]-vec[j,2])**2)
      ii+=1

  return res

这将内存量减少到不到 scipy cdist 方法的 1/4。

时间

calc_distance: ~2s
calc_distance_pairs: ~3s
cdist: ~11s

【讨论】:

  • 非常感谢
猜你喜欢
  • 2013-03-02
  • 2015-07-15
  • 2014-02-04
  • 1970-01-01
  • 2021-10-01
  • 2012-12-21
  • 1970-01-01
相关资源
最近更新 更多