scipy中逆矩阵乘积的跟踪

时间:2015-09-23 16:16:17

标签: scipy linear-algebra

我希望有效地计算逆矩阵乘积的轨迹,即Tr(A ^ -1 B)。我在许多其他地方使用A的逆,所以我可以访问Cholesky分解或显式逆。

天真的事情将是以下两个之一:

np.trace(np.dot(invA, B))
np.trace(linalg.cho_solve(choA, B))

然而,这似乎是浪费,因为它在O(N ^ 3)处计算完整矩阵A ^ -1 B,然后才使用其对角线来计算轨迹。

给定显式逆,O(N ^ 2)解决方案将是:

np.sum(invA.T * B)

虽然这需要一个明确的反转,这是不可取的。

我认为理想的方法是在Cholesky分解后只计算A ^ -1 B的对角元素,然后简单求和。这可能使用scipy吗?或者在Cholesky分解的情况下,还有另一种以数值稳定的方式计算Tr(invA * B)的方法吗?

1 个答案:

答案 0 :(得分:0)

@ DSM建议的einsum直观地看起来像是fastest way,因为它只会计算所需的条款。在python中手动执行此操作会比较慢,除非numpy / scipy中有专门的例程,数学技巧或者没有用较低级别的语言编写内容,否则我看不到更好办法。为了检查时间,我们设置了一个虚拟数组,

import numpy as np
from scipy import linalg

invA = np.random.rand(100,100)
B = np.random.rand(100,100)
choA = linalg.cholesky(a)

尝试天真的建议,

%timeit np.sum(invA.T * B)
10000 loops, best of 3: 38.5 us per loop

使用逆

的方法
%timeit np.sum(invA.T * B)
10000 loops, best of 3: 39.1 us per loop

似乎差不多。最后使用einsum

%timeit np.einsum("ij,ji", invA, B)
100000 loops, best of 3: 17.4 us per loop

似乎快了两倍。