【发布时间】:2014-06-28 23:07:27
【问题描述】:
我需要计算矩阵在其所有对角线上的轨迹。也就是说,对于一个 nxm 矩阵,该操作应该产生 n+m-1 个“轨迹”。这是一个示例程序:
import numpy as np
A=np.arange(12).reshape(3,4)
def function_1(A):
output=np.zeros(A.shape[0]+A.shape[1]-1)
for i in range(A.shape[0]+A.shape[1]-1):
output[i]=np.trace(A,A.shape[1]-1-i)
return output
A
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
function_1(A)
array([ 3., 9., 18., 15., 13., 8.])
我希望找到一种方法来替换程序中的循环,因为我需要在非常大的矩阵上多次执行此计算。一种看起来很有希望的途径是 使用 numpy.einsum,但我不知道该怎么做。或者,我已经研究过用 cython 中的循环完全重写问题:
%load_ext cythonmagic
%%cython
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
def function_2(long [:,:] A):
cdef int n=A.shape[0]
cdef int m=A.shape[1]
cdef long [::1] output = np.empty(n+m-1,dtype=np.int64)
cdef size_t l1
cdef int i,j, k1
cdef long out
it_list1=range(m)
it_list2=range(m,m+n-1)
for l1 in range(len(it_list1)):
k1=it_list1[l1]
i=0
j=m-1-k1
out=0
while (i<n)&(j<m):
out+=A[i,j]
i+=1
j+=1
output[k1]=out
for l1 in range(len(it_list2)):
k1=it_list2[l1]
i=k1-m+1
j=0
out=0
while (i<n)&(j<m):
out+=A[i,j]
i+=1
j+=1
output[k1]=out
return np.array(output)
cython 程序优于通过 np.trace 循环的程序:
%timeit function_1(A)
10000 loops, best of 3: 62.7 µs per loop
%timeit function_2(A)
100000 loops, best of 3: 9.66 µs per loop
所以,基本上我想获得关于是否有更有效的方式来使用 numpy/scipy 例程的反馈,或者我是否可能已经实现了 使用 cython 的最快方式。
【问题讨论】:
-
我想知道这将如何比较:
np.fromiter(map(A.trace, range(A.shape[1]-1, -A.shape[0], -1)), dtype=np.int64) -
对于大型矩阵,Cython 版本可以在内存访问方面进行改进。 IE。循环遍历行而不是对角线。
-
如果您希望跟踪而不是零填充,那么我认为在傅立叶空间中会有一个很好的方法。