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