我试图理解使用numpy和scipy库进行LU分解的必要性。根据我的理解,我们想要求解Ax = b,我们首先将A分解为两个三角矩阵L和U,然后通过求解Ly = b然后Ux = y来求解LUx = b。通过求解三角矩阵,与高斯消元相比,我们可以减少时间。
所以,我在使用numpy和scipy的python中厌倦了这个想法。
我首先使用玩具示例构建A和b:
A = np.array([[2, 1, 0, 5], [1, 2, 1, 2], [0, 1, 2, 4], [1, 3, 6, 4.5]])
b = np.array([9, 10, -2, 3])
然后首先在np.solve中解决这个玩具示例
%timeit np.linalg.solve(A, b )
时间是
每回路9.76μs±782 ns(平均值±标准偏差,7次运行,每次100000次循环)
然后我使用分解来解决这个系统:
lu, piv = linalg.lu_factor(A)
%timeit linalg.lu_solve((lu, piv), b)
我看到输出是
每回路18.8μs±213 ns(平均值±标准偏差,7次运行,每次100000次循环)
,与np.solve相比安静缓慢。
所以,我的问题是,为什么np.solve比linalg.lu_factor更快?我的猜测是numpy.solve不使用高斯消元法求解方程式?有点混淆这里的结果。
现在,我使用更大的矩阵进行实验(10000 x 10000)。
结果如下: 对于np.linalg.solve
8.64 s ± 180 ms per loop (mean ± std. dev. of 7 runs, 1 loop each);
表示scipy.linalg.lu_solve
121 ms ± 3.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each).
对于lu_solve,我只计算解决时间,不计算分解部分。它现在快得多了!
答案 0 :(得分:4)
这是一个部分答案,因为我对你的一个场所提出异议。
你写道“LU解决方案应该比高斯消除更快”。你似乎误解了LU分解的目的。如果你只解决一个这样的问题(Ax=b
,其中给出了矩阵A
和向量b
),LU解析并不比高斯消除快。实际上,分解的算法非常类似于消除,并且不会更快。
当您获得矩阵A
并且想要为多个不同的给定向量Ax=b
求解等式b
时,LU分解的优势就出现了。高斯消除需要从头开始,每个解决方案都需要相同的时间。在LU分解中,您可以存储第一次计算得到的矩阵L
和U
,这大大加快了使用不同向量b
的后续方程的解。
您可以在C中关于LU Decomposition and Its Applications的数字食谱部分阅读更多相关信息。
答案 1 :(得分:1)
查看numpy.linalg.solve
的文档字符串。它在“注释”部分中说“解决方案是使用LAPACK例程_gesv计算的”。 (下划线是与数据类型对应的字符的占位符。例如,dgesv
使用双精度。)
documentation for dgesv
解释说它使用LU分解。所以你或多或少地复制了计算,但是你在Python中做了更多的步骤,所以你的代码更慢。
答案 2 :(得分:0)
编辑之后,它现在表现得如预期,因为当你使用更大的矩阵时,渐近行为变得更加明显。
使用预先计算的矩阵LUx = y
和L
解决U
的工作量为O(n^2)
,与y
的简单矩阵向量乘法相同倒置矩阵(除了你没有明确的倒置矩阵,你改为L
和U
)。
从头开始求解方程为O(n^3)
,因此对于合理大小的矩阵,需要更长的时间。
在使用大型矩阵之前,调用函数和访问元组组件等所有普通事物的开销大于实际计算所需的时间。