Python 如何优化多维numpy阵列计算?
给定一个5D阵列,目标是计算提取的两个阵列之间的差异。为简单起见,假设在第二个位置测量差异,可以表示为Python 如何优化多维numpy阵列计算?,python,performance,numpy,coding-efficiency,Python,Performance,Numpy,Coding Efficiency,给定一个5D阵列,目标是计算提取的两个阵列之间的差异。为简单起见,假设在第二个位置测量差异,可以表示为bt和lf。这两个数组中的值可以提取如下: arr[ep, bt, mt, bd, :] - arr[ep, lf, mt, bd, :] 注意,在上面,第一(ep)、第三(mt)和第四(bd)轴的索引对于这两个阵列是相同的,只有第二轴的位置索引不同(bt和lf) 基于此要求,提出了以下代码,并将其打包在函数嵌套的\u for_循环下: import numpy as np from jobl
bt
和lf
。这两个数组中的值可以提取如下:
arr[ep, bt, mt, bd, :] - arr[ep, lf, mt, bd, :]
注意,在上面,第一(ep
)、第三(mt
)和第四(bd
)轴的索引对于这两个阵列是相同的,只有第二轴的位置索引不同(bt
和lf
)
基于此要求,提出了以下代码,并将其打包在函数嵌套的\u for_循环
下:
import numpy as np
from joblib import Parallel, delayed
np.random.seed(0)
ub_lb_pair = np.tril_indices (5, -1)
arr = np.random.randn(3, 5, 4, 3, 2)
my_shape = arr.shape
def nested_for_loop():
store_cval = np.full([my_shape[0], 10, my_shape[2], my_shape[3], my_shape[4]],
np.nan) # preallocate
for ep in range(0, my_shape[0]):
for mt in range(0, my_shape[2]):
for bd in range(0, my_shape[3]):
for idx,(bt, lf) in enumerate(zip(ub_lb_pair[0], ub_lb_pair[1])):
store_cval[ep, idx, mt, bd, :] = arr[ep, bt, mt, bd, :] - \
arr[ep, lf, mt, bd, :]
return store_cval
store_cval = nested_for_loop()
但是,如果可能的话,我想使代码更加紧凑和高效
我能想到的一种方法是利用joblibparallel
模块,它可以实现如下所示的功能multi_prop
def multi_prop(my_arr, ep):
temp_ = np.full([10, my_shape[2], my_shape[3], my_shape[4]],
np.nan)
for mt in range(0, my_shape[2]):
for bd in range(0, my_shape[3]):
for idx, (bt, lf) in enumerate(zip(ub_lb_pair[0], ub_lb_pair[1])):
temp_[idx, mt, bd, :] = my_arr[ep, bt, mt, bd, :] - my_arr[ep, lf, mt, bd, :]
x = 1
return temp_
dist_abs = Parallel(n_jobs=-1)(delayed(multi_prop)(arr, ep) for ep in range(0, my_shape[0]))
dist_abs = np.array(dist_abs)
bb = np.array_equal(store_cval, dist_abs)
但是,我想知道,这是否是实现同样目标的一种更具numpythonic的方法。您根本不需要任何循环。想象一下这对奇特的指数:
bt, lf = np.tril_indices (5, -1)
你在找什么
store_cval = arr[:, bt] - arr[:, lf]
请记住,store_cval[ep,idx,mt,bd,:]=arr[ep,bt,mt,bd,:]-arr[ep,lf,mt,bd,:]
是上一个索引上的隐式循环。它们都是环,你不需要在引擎盖上有任何环
一个更普遍的解决方案:
def diffs(arr, axis):
a, b = np.tril_indices(arr.shape[axis], -1)
ind1 = [slice(None) for _ in range(arr.ndim)]
ind2 = ind1.copy()
ind1[axis] = a
ind2[axis] = b
return arr[tuple(ind1)] - arr[tuple(ind2)]
为什么只为最后一个维度创建一个切片
arr[:,bt,:,:,:,:,:]和arr[:,lf,:,:]
或者甚至arr[:,bt,…]和arr[:,lf,…]
?假设最后一个维度的形状为2和,并且每个维度都具有值[3,4]
和[1,1]
。因此,它们之间的区别是[2,3]
。这对你有意义吗@hpaulj?嗨@Mad,谢谢你的详细解释。由于某种原因,我无法重现上述结果。例如,轴的值是多少。此外,我的编译器在ind1=[slice(None)for uu.in range arr.ndim]
行上提供了预期的警告End-of-statement
。最后,你是说tril
成为np.tril\u索引
?@balandongiv。对不起,我打错了。现在修好了。在本例中,您希望沿第二个轴使用组合,因此axis=1