`expm` 矩阵的 Python `(N,M,M)`

标签 python numpy scipy linear-algebra numpy-einsum

A 是一个 (N,M,M) 矩阵(N 非常大),我想计算 scipy.linalg.expm(A[n,:,:]) 用于范围 (N) 中的每个 n。我当然可以只使用 for 循环,但我想知道是否有一些技巧可以更好地做到这一点(比如 np.einsum)。

我对其他操作也有同样的问题,比如求逆矩阵(求逆在评论中解决)。

最佳答案

根据矩阵的大小和结构,您可以做得比循环更好。

假设您的矩阵可以对角化为 A = V D V^(-1)(其中 D 在其对角线上具有特征值,而 V包含相应的特征向量作为列),您可以将矩阵指数计算为

exp(A) = V exp(D) V^(-1)

其中 exp(D) 仅包含其对角线中每个特征值 lambdaexp(lambda)。如果我们使用指数函数的幂级数定义,这真的很容易证明。如果矩阵 A 进一步正规,则矩阵 V 是酉矩阵,因此可以通过简单地取它的伴随来计算它的逆。

好消息是 numpy.linalg.eignumpy.linalg.inv 都可以很好地处理堆叠矩阵:

import numpy as np
import scipy.linalg

A = np.random.rand(1000,10,10)

def loopy_expm(A):
    expmA = np.zeros_like(A)
    for n in range(A.shape[0]):
        expmA[n,...] = scipy.linalg.expm(A[n,...])
    return expmA

def eigy_expm(A):
    vals,vects = np.linalg.eig(A)
    return np.einsum('...ik, ...k, ...kj -> ...ij',
                     vects,np.exp(vals),np.linalg.inv(vects))

请注意,在调用 einsum 时指定操作顺序可能有一些优化空间,但我没有对此进行调查。

测试上面的随机数组:

In [59]: np.allclose(loopy_expm(A),eigy_expm(A))
Out[59]: True

In [60]: %timeit loopy_expm(A)
824 ms ± 55.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [61]: %timeit eigy_expm(A)
138 ms ± 992 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

这已经很好了。如果你足够幸运,你的矩阵都是正态的(比如,因为它们是实对称的):

A = np.random.rand(1000,10,10)
A = (A + A.transpose(0,2,1))/2

def eigy_expm_normal(A):
    vals,vects = np.linalg.eig(A)
    return np.einsum('...ik, ...k, ...jk -> ...ij',
                     vects,np.exp(vals),vects.conj())

注意输入矩阵的对称定义和 einsum 模式内的转置。结果:

In [80]: np.allclose(loopy_expm(A),eigy_expm_normal(A))
Out[80]: True

In [79]: %timeit loopy_expm(A)
878 ms ± 89.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [80]: %timeit eigy_expm_normal(A)
55.8 ms ± 868 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

对于上述示例形状,这是 15 倍的加速。


应该注意的是,scipy.linalg.eigm 根据文档使用 Padé 近似。这可能意味着如果您的矩阵是病态的,则特征值分解可能会产生与 scipy.linalg.eigm 不同的结果。我不熟悉此功能的工作原理,但我希望它对病理输入更安全。

关于 `expm` 矩阵的 Python `(N,M,M)`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49530410/

相关文章:

python - 数据增强完成后会发生什么?

python - 从 x,y 坐标查找最近的 x,y,z 点

python - 如何求连续减少(增加)的次数

python - 使用 [ :, :] crashes python? 填充 numpy 数组

python - 在将数据传递给插值例程之前存储数据

python - 获取对 Python dict 键的引用

python - 在ID3决策树中选择具有属性数值的最佳节点

python - 不添加不必要的极值的插值方法

python - 有使用 h5py 在 Python 中对大数据进行分析工作的经验吗?

python - 寻找巨大稀疏矩阵的最大特征值