我希望有效地计算逆矩阵乘积的轨迹,即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)的方法吗?
答案 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
似乎快了两倍。