Numpy/Scipy:使用相同的设计矩阵求解多个最小二乘
我面临一个最小二乘问题,我通过Numpy/Scipy:使用相同的设计矩阵求解多个最小二乘,numpy,scipy,least-squares,Numpy,Scipy,Least Squares,我面临一个最小二乘问题,我通过scipy.linalg.lstsq(M,b)解决,其中: M具有形状(n,n) b具有形状(n,) 问题是我必须为不同的b解决很多时间。我怎样才能做得更有效率?我猜lstsq做了很多事情,与b的值无关 想法 你的问题不清楚,但我猜你的意思是通过scipy.linalg.lstsq(M,b)计算不同数组(b0,b1,b2..)的方程Mx=b)。如果是这种情况,您可以使用concurrent.futures.ProcessPoolExecutor并行化进程。这方面
scipy.linalg.lstsq(M,b)
解决,其中:
具有形状M
(n,n)
具有形状b
(n,)
b
解决很多时间。我怎样才能做得更有效率?我猜lstsq
做了很多事情,与b
的值无关
想法 你的问题不清楚,但我猜你的意思是通过
scipy.linalg.lstsq(M,b)
计算不同数组(b0,b1,b2..
)的方程Mx=b
)。如果是这种情况,您可以使用concurrent.futures.ProcessPoolExecutor
并行化进程。这方面的文档相当简单,可以帮助python同时运行多个scipy解算器
希望这有帮助。您可以将
M
分解为QR或SVD产品,并手动找到lsq解决方案。如果您的线性系统已确定,我将存储M
LU分解,并将其单独用于所有b
,或者只需对表示水平堆叠b
的2d数组b
执行一次解算调用,这实际上取决于您的问题,但这在全局上是相同的想法。假设每个b
一次一个,然后:
import numpy as np
from scipy.linalg import lstsq, lu_factor, lu_solve, svd, pinv
# as you didn't specified any practical dimensions
n = 100
# number of b's
nb_b = 10
# generate random n-square matrix M
M = np.random.rand(n**2).reshape(n,n)
# Set of nb_b of right hand side vector b as columns
B = np.random.rand(n*nb_b).reshape(n,nb_b)
# compute pivoted LU decomposition of M
M_LU = lu_factor(M)
# then solve for each b
X_LU = np.asarray([lu_solve(M_LU,B[:,i]) for i in range(nb_b)])
但是,如果确定不足或过高,您需要像以前一样使用:
X_lstsq = np.asarray([lstsq(M,B[:,i])[0] for i in range(nb_b)])
或者只需使用(基于lstsq构建)或(基于SVD构建)存储伪逆M_pinv
:
或者您也可以自己做这项工作,例如在pinv2
中,只需存储M
的SVD,然后手动解决此问题:
# compute svd of M
U,s,Vh = svd(M)
def solve_svd(U,s,Vh,b):
# U diag(s) Vh x = b <=> diag(s) Vh x = U.T b = c
c = np.dot(U.T,b)
# diag(s) Vh x = c <=> Vh x = diag(1/s) c = w (trivial inversion of a diagonal matrix)
w = np.dot(np.diag(1/s),c)
# Vh x = w <=> x = Vh.H w (where .H stands for hermitian = conjugate transpose)
x = np.dot(Vh.conj().T,w)
return x
X_svd = np.asarray([solve_svd(U,s,Vh,B[:,i]) for i in range(nb_b)])
然而,这取决于你检查这些与适当的尺寸
希望这能有所帮助。是的,这正是我正在做的,我想知道是否有更好的解决方案,因为最小二乘问题(
M
)的设计没有改变,也许一部分计算可以一次性完成,但是我不认为解算器是独立于b
计算任何非琐碎的东西。我想你明白了。这是可悲的:(
# compute svd of M
U,s,Vh = svd(M)
def solve_svd(U,s,Vh,b):
# U diag(s) Vh x = b <=> diag(s) Vh x = U.T b = c
c = np.dot(U.T,b)
# diag(s) Vh x = c <=> Vh x = diag(1/s) c = w (trivial inversion of a diagonal matrix)
w = np.dot(np.diag(1/s),c)
# Vh x = w <=> x = Vh.H w (where .H stands for hermitian = conjugate transpose)
x = np.dot(Vh.conj().T,w)
return x
X_svd = np.asarray([solve_svd(U,s,Vh,B[:,i]) for i in range(nb_b)])
%timeit M_LU = lu_factor(M); X_LU = np.asarray([lu_solve(M_LU,B[:,i]) for i in range(nb_b)])
1000 loops, best of 3: 1.01 ms per loop
%timeit X_lstsq = np.asarray([lstsq(M,B[:,i])[0] for i in range(nb_b)])
10 loops, best of 3: 47.8 ms per loop
%timeit M_pinv = pinv(M); X_pinv = np.asarray([np.dot(M_pinv,B[:,i]) for i in range(nb_b)])
100 loops, best of 3: 8.64 ms per loop
%timeit U,s,Vh = svd(M); X_svd = np.asarray([solve_svd(U,s,Vh,B[:,i]) for i in range(nb_b)])
100 loops, best of 3: 5.68 ms per loop