Optimization 在numpy中对linalg.eig()进行矢量化

Optimization 在numpy中对linalg.eig()进行矢量化,optimization,numpy,linear-algebra,Optimization,Numpy,Linear Algebra,我有一个m*m*n numpy数组(称之为A),我想找到这个数组中每个子矩阵A[:,:,n]的特征值。我可以相对轻松地在循环中使用linalg.eig(),但确实应该有一种方法将其矢量化。类似于ufunc,但可以处理子向量而不是单个元素。这是可能的吗?特征值和特征向量的计算不能矢量化,因为通常无法为不同的矩阵共享工作np.linalg.eig(对于实际输入)只是的一个包装器,根据文档,它每次调用只接受一个矩阵,并且计算相当昂贵,因此对于不小的矩阵,python循环的开销可以忽略不计 不过,如果你

我有一个m*m*n numpy数组(称之为A),我想找到这个数组中每个子矩阵
A[:,:,n]
的特征值。我可以相对轻松地在循环中使用
linalg.eig()
,但确实应该有一种方法将其矢量化。类似于
ufunc
,但可以处理子向量而不是单个元素。这是可能的吗?

特征值和特征向量的计算不能矢量化,因为通常无法为不同的矩阵共享工作
np.linalg.eig
(对于实际输入)只是的一个包装器,根据文档,它每次调用只接受一个矩阵,并且计算相当昂贵,因此对于不小的矩阵,python循环的开销可以忽略不计

不过,如果你对许多非常小的矩阵进行此操作,它可能会变得太慢。与此相关的问题有很多,解决方案通常以编译扩展结束。正如神秘物理学家在一篇评论中所说,用与UFUNC相同的方式处理子向量和子矩阵的想法通常是有用的。这些被称为广义的UFUNC,并且已经在numpy中。我发现对于形状为
(1000,3,3)
的矩阵,速度大约快8倍:


另一方面,如果您碰巧处理的是对称矩阵,则可以使用
np.linalg.eigh
,这要快得多(同样,对于特定但常见的对称输入情况,例如协方差矩阵)。当然,这并不能解决你的矢量化问题(@jorgeca是正确的,没有直接矢量化的方法,只有当
m
非常小而
n
非常大时,它才会明显更快)。假设
m
很小而
n
不是,并且假设你在多核机器上运行它,一种可能的加速方法是使用
多处理
模块:只需为每个进程分配几个矩阵。嗯,碰巧m非常小。(只有4)否则我就不会问这个问题了。相信我,哈哈。我正在考虑更直接地使用C语言的特征值求解器。我已经有了一些代码,我想我可以让它以我想要的速度工作。但是,如果UFUNC真的存在,而且它们确实存在,那么即使是以同样的方式处理子向量和子矩阵的想法也会在总体上是有用的。@Enigmatic物理学家你想要的行为(广义的
UFUNC
处理子阵列)已经在numpy中了,如果你愿意构建和使用它的话。嘿,那太酷了,Jorge!如果我有时间的话,我肯定需要看一看。@EnigmaticPhysicast我刚刚更新了答案,加入了时间安排(来自一个普通的ATLAS构建)。
In [2]: np.__version__
Out[2]: '1.8.0.dev-dcf7cac'

In [3]: A = np.random.rand(1000, 3, 3)

In [4]: timeit np.linalg.eig(A)
P100 loops, best of 3: 9.65 ms per loop

In [5]: timeit [np.linalg.eig(Ai) for Ai in A]
10 loops, best of 3: 74.6 ms per loop

In [6]: a1 = np.linalg.eig(A)

In [7]: a2 = [np.linalg.eig(Ai) for Ai in A]

In [8]: all(np.allclose(a1[i][j], a2[j][i]) for j in xrange(1000) for i in xrange(2))
Out[8]: True