向量化 Python 代码

Jea*_*ean 3 python numpy vectorization

我编写了一个克里金算法,但我发现它很慢。特别是,您是否知道我如何在下面的 cons 函数中矢量化这段代码:

import time
import numpy as np

B = np.zeros((200, 6))
P = np.zeros((len(B), len(B)))

def cons():
  time1=time.time()
  for i in range(len(B)):
    for j in range(len(B)):
      P[i,j] = corr(B[i], B[j])
  time2=time.time()
  return time2-time1

def corr(x,x_i):
  return np.exp(-np.sum(np.abs(np.array(x) - np.array(x_i))))    

time_av = 0.
for i in range(30):
  time_av+=cons()
print "Average=", time_av/100.
Run Code Online (Sandbox Code Playgroud)

编辑:奖金问题

  1. 如果我想要corr(B[i], C[j])C 与 B 相同的维度,广播解决​​方案会发生什么
  2. 如果我的 p 范数订单是一个数组,scipy 解决方案会发生什么:

    p=np.array([1.,2.,1.,2.,1.,2.])
    def corr(x, x_i):
      return np.exp(-np.sum(np.abs(np.array(x) - np.array(x_i))**p))  
    
    Run Code Online (Sandbox Code Playgroud)

    对于 2.,我尝试过,P = np.exp(-cdist(B, C,'minkowski', p))但 scipy 期待一个标量。

And*_*eak 5

您的问题似乎很容易矢量化。对于B您要计算的每一对行

P[i,j] = np.exp(-np.sum(np.abs(B[i,:] - B[j,:])))
Run Code Online (Sandbox Code Playgroud)

您可以利用数组广播并引入第三维,沿最后一维求和:

P2 = np.exp(-np.sum(np.abs(B[:,None,:] - B),axis=-1))
Run Code Online (Sandbox Code Playgroud)

这个想法是重塑Bto shape的第一次出现,(N,1,M)而第二次B出现 shape (N,M)。使用数组广播,后者等价于(1,N,M),所以

B[:,None,:] - B
Run Code Online (Sandbox Code Playgroud)

是形状(N,N,M)。沿最后一个索引求和将产生(N,N)您正在寻找的-shape 相关数组。


请注意,如果你使用scipy,你就可以用这个做scipy.spatial.distance.cdist(或等价地,一个组合scipy.spatial.distance.pdistscipy.spatial.distance.squareform),而不必计算这个的Symmetrix矩阵的下三角一半。以这种方式在评论中使用@Divakar的建议以获得最简单的解决方案:

from scipy.spatial.distance import cdist
P3 = 1/np.exp(cdist(B, B, 'minkowski',1))
Run Code Online (Sandbox Code Playgroud)

cdist 将计算 1-范数的 Minkowski 距离,这正是坐标差的绝对值之和。