关于python:在Numpy中向量化特征值计算

Vectorize eigenvalue calculation in Numpy

我想要一种向量化特征值计算的numpy-sh方式,这样我就可以为其输入矩阵矩阵,并且它将返回各个特征值的矩阵。

例如,在下面的代码中,B是由4个3x3矩阵A的副本组成的块6x6矩阵。
C是我希望看到的输出,即维度(2,2,3)的数组(因为A具有3个特征值)。

这当然是一个非常简化的示例,在一般情况下,矩阵A可以具有任何大小(尽管它们仍然是正方形),矩阵B不一定由A的副本形成,而是不同的A1,A2,等等(大小相同,但包含不同元素)。

1
2
3
4
5
6
7
import numpy as np
A = np.array([[0, 1, 0],
              [0, 2, 0],
              [0, 0, 3]])
B = np.bmat([[A, A], [A,A]])
C = np.array([[np.linalg.eigvals(B[0:3,0:3]),np.linalg.eigvals(B[0:3,3:6])],
              [np.linalg.eigvals(B[3:6,0:3]),np.linalg.eigvals(B[3:6,3:6])]])

编辑:如果您使用的是numpy> = 1.8.0版本,则np.linalg.eigvals在所处理的任何数组的最后两个维度上运行,因此,如果将输入重塑为(n_subarrays, nrows, ncols)数组,则只需调用一次eigvals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

A = np.array([[0, 1, 0],
              [0, 2, 0],
              [0, 0, 3]])

# the input needs to be an array, since matrices can only be 2D.
B = np.repeat(A[np.newaxis,...], 4, 0)

# for arbitrary input arrays you could do something like:
# B = np.vstack(a[np.newaxis,...] for a in input_arrays)
# but for this to work it will be necessary for each element in
# 'input_arrays' to have the same shape

# eigvals will operate over the last two dimensions of the array and return
# a (4, 3) array of eigenvalues
C = np.linalg.eigvals(B)

# reshape this output so that it matches your original example
C.shape = (2, 2, 3)

如果输入数组的维数都不相同,例如input_arrays[0].shape == (2, 2)input_arrays[1].shape == (3, 3)等。那么您只能跨尺寸匹配的子集对计算进行矢量化。

如果您使用的是numpy的旧版本,那么不幸的是,我认为没有任何方法可以向量化多个输入数组上特征值的计算-您只需要在Python中循环输入即可。<铅>


您可以做这样的事情

1
2
3
C = np.array([[np.linalg.eigvals(B[i:i+3, j:j+3])
              for i in xrange(0, B.shape[0], 3)]
                for j in xrange(0, B.shape[1], 3)])

也许更好的方法是使用https://stackoverflow.com/a/5078155/1352250中的block_view函数:

1
2
B_blocks = block_view(B)
C = np.array([[np.linalg.eigvals(m) for m in v] for v in B_blocks])

更新

ali_m指出,此方法是语法糖的一种形式,不会减少因多次调用eigvals而引起的开销。如果要应用的每个矩阵的开销都很大,那么此开销应该很小,但对于OP感兴趣的6x6矩阵,它并不是微不足道的(请参阅下面的注释;根据ali_m,可能是三分之一)我上面给出的版本与他发布的使用Numpy> = 1.8.0的版本之间的差异。