python-3.x - LU 分解速度与传统 Ax=b 的比较

标签 python-3.x performance numpy scipy linear-algebra

学习 LU 分解,我使用的教科书声称一旦计算了初始矩阵 LU(假设没有主元矩阵 P 是需要的),解决Ly = b然后Ux = yAx =更快/更高效(也称为更少的失败) b从头开始。但是,当我使用随机 A ⊆ R^(10 x 10) 矩阵和 b ⊆ R^(10 x 1) 在系统上运行它时,结果是慢得多(12.49 秒 vs 6.17 秒)。

这是我的代码:

import numpy as np
from scipy.linalg import lu
from numpy.random import rand
from numpy.linalg import solve
from timeit import timeit as duration

A, b = rand(500, 500), rand(500, 1)
P,L,U = lu(A)

t_vanilla = duration("solve(A,b)", setup="from __main__ import solve, A, b")
print(t_vanilla)
t_decomps = duration("solve(U, solve(L,b))", setup="from __main__ import solve, L, U, b")
print(t_decomps)

对于为什么会出现这种情况有什么想法吗?这是我第一次使用 timeit 库,所以我很可能搞砸了哈哈。我在 Mac OSX、python 3.8 上运行它。

此外,我注意到由于某种原因,scipy.solvenumpy.solve方式(时间超过两倍)。 .有什么直觉可以解释为什么吗?

谢谢!!!

最佳答案

当运行solve(U,solve(L,b))时,你只需给LAPACK gesv np.linalg.solve 背后的例程是盲目求解的两个不同的线性系统,而不考虑 LU 的三角形结构。这是通过分别对每个 LU 分解然后进行前向 (Ly = b) 和后向 (Ux = y) 替换来完成的。这就是为什么您的计时似乎表明大约是单个 solve 调用时间的两倍。

现在,根据您的教科书,更一般地说,已经对矩阵 A 进行 LU 分解所带来的数值效率是,如果您有多个右侧,您可以简单地重用它b 以避免昂贵且冗余的分解步骤。为此,您只需通过前向替换求解两个三角方程组 Ly = b,然后使用后向替换求解 Ux = y。让我按如下方式计时:

import numpy as np
from scipy.linalg import lu_factor, lu_solve, lu

A, b = np.random.rand(500, 500), np.random.rand(500, 1)
P,L,U = lu(A)
lu_A = lu_factor(A)

# LU + forward backward
%timeit np.linalg.solve(A, b)
>>> 1.4 ms ± 10.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# 2 x (LU + forward backward)
%timeit np.linalg.solve(U, np.linalg.solve(L, b))
>>> 2.39 ms ± 85.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# forward backward
%timeit lu_solve(lu_A, b)
>>> 69.8 µs ± 6.48 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

如果您有多个 b 需要求解,效率确实要高得多。

请注意,我使用了 scipy.linalg.lu_factor ,它存储 LU 分解的紧凑形式,后跟 scipy.linalg.lu_solve ,它通过 lu_factor 给出的分解来求解系统。

另请注意,当这些多个 b 不能同时可用时,重用 LU 分解非常有用。相反,如果它们很容易获得,您可以简单地使用水平堆叠的 b 进行单个 solve 调用,具有相同的性能,因为求解器本身将重用为剩下的每个 b 的第一个。

关于 scipy 的性能问题,如果没有有关 numpy/scipy 的更多信息(np.show_config()),很难说。

希望现在更清楚了。

关于python-3.x - LU 分解速度与传统 Ax=b 的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66090768/

相关文章:

python - 包含大量数据的散点图

python - 使用 Logbook 和 ZeroMQ,为什么我需要等待才能传递消息?

Python在网页弹出窗口中从电脑中选择图像

android - 在 Android 上,我可以在不看屏幕的情况下检测到屏幕卡顿吗?

python - 推进 basemap 绘图

python - 函数认为我正在传递一个 float

python - 如何以随机顺序运行函数?

python-3.x - 使用 python 3 将文件夹中的文件名列出到 tkinter 窗口

python 的 `timeit` 并不总是与数字成线性比例?

c# - C# 中 try/finally 的开销?