Matlab使用稀疏命令计算对角矩阵的倒数需要0.02秒。
P = diag(1:10000);
P = sparse(P);
tic;
A = inv(P);
toc
然而,对于Python代码,它需要永远 - 几分钟。
import numpy as np
import time
startTime = time.time()
P = np.diag(range(1,10000))
A = np.linalg.inv(P)
runningTime = (time.time()-startTime)/60
print "The script was running for %f minutes" % runningTime
我尝试使用Scipy.sparse模块,但它没有帮助。运行时间下降,但只有40秒。
import numpy as np
import time
import scipy.sparse as sps
import scipy.sparse.linalg as spsl
startTime = time.time()
P = np.diag(range(1,10000))
P_sps = sps.coo_matrix(P)
A = spsl.inv(P_sps)
runningTime = (time.time()-startTime)/60
print "The script was running for %f minutes" % runningTime
是否可以像在Matlab中一样快地运行代码?
答案 0 :(得分:8)
这是答案。当您在matlab中为稀疏矩阵运行inv时,matlab会检查矩阵的不同属性以优化计算。对于稀疏对角矩阵,您可以运行以下代码来查看matlab正在做什么
n = 10000;
a = diag(1:n);
a = sparse(a);
I = speye(n,n);
spparms('spumoni',1);
ainv = inv(a);
spparms('spumoni',0);
Matlab将打印以下内容:
sp\: bandwidth = 0+1+0.
sp\: is A diagonal? yes.
sp\: do a diagonal solve.
所以matlab只反转对角线。
Scipy如何反转矩阵? 我们在这里有code:
...
from scipy.sparse.linalg import spsolve
...
def inv(A):
"""
Some comments...
"""
I = speye(A.shape[0], A.shape[1], dtype=A.dtype, format=A.format)
Ainv = spsolve(A, I)
return Ainv
# Cover the case where b is also a matrix
Afactsolve = factorized(A)
tempj = empty(M, dtype=int)
x = A.__class__(b.shape)
for j in range(b.shape[1]):
xj = Afactsolve(squeeze(b[:, j].toarray()))
w = where(xj != 0.0)[0]
tempj.fill(j)
x = x + A.__class__((xj[w], (w, tempj[:len(w)])),
shape=b.shape, dtype=A.dtype)
,即scipy factorize A然后求解一组线性系统,其中右侧是坐标向量(形成单位矩阵)。对矩阵中的所有解进行排序,我们得到初始矩阵的逆矩阵。
如果matlab被利用矩阵的对角线结构,但scipy不是(当然scipy也使用矩阵的结构,但效率较低,至少对于例子而言),matlab应该是更快。
修改强> 可以肯定的是,正如@ P.Escondido提出的那样,我们将尝试对矩阵A进行微小的修改,以便在矩阵不是对角线时跟踪matlab过程:
n = 10000; a = diag(1:n); a = sparse(a); ainv = sparse(n,n);
spparms('spumoni',1);
a(100,10) = 500; a(10,1000) = 200;
ainv = inv(a);
spparms('spumoni',0);
打印出以下内容:
sp\: bandwidth = 90+1+990.
sp\: is A diagonal? no.
sp\: is band density (0.00) > bandden (0.50) to try banded solver? no.
sp\: is A triangular? no.
sp\: is A morally triangular? yes.
sp\: permute and solve.
sp\: sprealloc in sptsolve: 10000 10000 10000 15001
答案 1 :(得分:4)
splu()
如何,它更快但需要一个密集阵列并返回密集阵列:
创建一个随机矩阵:
import numpy as np
import time
import scipy.sparse as sps
import scipy.sparse.linalg as spsl
from numpy.random import randint
N = 1000
i = np.arange(N)
j = np.arange(N)
v = np.ones(N)
i2 = randint(0, N, N)
j2 = randint(0, N, N)
v2 = np.random.rand(N)
i = np.concatenate((i, i2))
j = np.concatenate((j, j2))
v = np.concatenate((v, v2))
A = sps.coo_matrix((v, (i, j)))
A = A.tocsc()
%time B = spsl.inv(A)
按splu()
计算逆矩阵:
%%time
lu = spsl.splu(A)
eye = np.eye(N)
B2 = lu.solve(eye)
检查结果:
np.allclose(B.todense(), B2.T)
这是%时间输出:
inv: 2.39 s
splv: 193 ms
答案 2 :(得分:3)
您正在使用软件中的关键信息:矩阵是对角线这一事实使得它非常容易反转:您只需反转其对角线的每个元素:
P = np.diag(range(1,10000))
A = np.diag(1.0/np.arange(1,10000))
当然,这仅适用于对角矩阵......
答案 3 :(得分:0)
如果您尝试使用,结果会更好:
import numpy as np
import time
import scipy.sparse as sps
import scipy.sparse.linalg as spsl
P = np.diag(range(1,10000))
P_sps = sps.coo_matrix(P)
startTime = time.time()
A = spsl.inv(P_sps)
runningTime = (time.time()-startTime)/60
print "The script was running for %f minutes" % runningTime
现在您可以与您的matlab脚本进行比较。