【问题标题】:Vectorize the calculation for Euclidean distance between matrix and vector向量化矩阵和向量之间的欧几里得距离的计算
【发布时间】:2019-03-23 19:11:22
【问题描述】:

我想计算矩阵和标准向量之间的欧几里得距离。 我所有的矩阵都存储在一个列表中,比如说 A,所以

A = [[1,2,3],[2,3,4]...,[8,9,10]],

标准向量是[1,1,1],

我可以使用 for 循环来做到这一点,但这真的很耗时,因为 A 中通常有数百个矩阵。 如何向量化此计算以缩短运行时间?

【问题讨论】:

    标签: python multithreading vectorization euclidean-distance


    【解决方案1】:
    A = np.array([[1,2,3],
                  [2,3,4],
                  [3,4,5],
                  [4,5,6],
                  [5,6,7],
                  [6,7,8],
                  [7,8,9],
                  [8,9,10]])
    
    v = np.array([1,1,1])
    
    # Compute the length (norm) of the distance between the vectors
    distance = np.linalg.norm(A - v, axis = 1)
    print(distance)
    
    [ 2.23606798  3.74165739  5.38516481  7.07106781  8.77496439 10.48808848
     12.20655562 13.92838828]
    

    【讨论】:

    • 这是最快的方法吗?
    • Here 是比较不同方法速度的几个问题之一。特别是对于大型/众多矩阵,我强烈推荐np.linalg.norm()。
    【解决方案2】:

    方法#1

    使用np.einsum 进行距离计算。为了解决我们的问题,我们可以这样做 -

    def dist_matrix_vec(matrix, vec):    
        d = np.subtract(matrix,vec)
        return np.sqrt(np.einsum('ij,ij->i',d,d))
    

    示例运行 -

    In [251]: A = [[1,2,3],[2,3,4],[8,9,10]]
    
    In [252]: B = np.array([1,1,1])
    
    In [253]: dist_matrix_vec(A,B)
    Out[253]: array([ 2.23606798,  3.74165739, 13.92838828])
    

    方法#2

    在处理大数据时,如果预期的操作可以表示为算术操作,我们可以使用支持多核处理的numexpr module。为了解决我们的情况,我们可以这样表达 -

    import numexpr as ne
    
    def dist_matrix_vec_numexpr(matrix, vec): 
        matrix = np.asarray(matrix)
        vec = np.asarray(vec)
        return np.sqrt(ne.evaluate('sum((matrix-vec)**2,1)'))
    

    大型数组的计时 -

    In [295]: np.random.seed(0)
         ...: A = np.random.randint(0,9,(10000,3))
         ...: B = np.random.randint(0,9,(3,))
    
    In [296]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
         ...: %timeit dist_matrix_vec(A,B)
         ...: %timeit dist_matrix_vec_numexpr(A,B)
    1000 loops, best of 3: 244 µs per loop
    10000 loops, best of 3: 131 µs per loop
    10000 loops, best of 3: 96.5 µs per loop
    
    In [297]: np.random.seed(0)
         ...: A = np.random.randint(0,9,(100000,3))
         ...: B = np.random.randint(0,9,(3,))
    
    In [298]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
         ...: %timeit dist_matrix_vec(A,B)
         ...: %timeit dist_matrix_vec_numexpr(A,B)
    100 loops, best of 3: 5.31 ms per loop
    1000 loops, best of 3: 1.43 ms per loop
    1000 loops, best of 3: 918 µs per loop
    

    基于numexpr 的线程带有8 线程。因此,随着更多线程可用于计算,它应该会进一步改进。 Related post 了解如何控制多核功能。

    【讨论】:

      猜你喜欢
      • 2014-08-15
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 2014-03-07
      • 2021-02-11
      • 2017-05-03
      • 2021-09-14
      • 2020-03-13
      相关资源
      最近更新 更多