快速求解最小二乘(欠定系统)(R)

Mar*_*ark 12 r matrix linear-algebra least-squares

我在R中有一个计算大量最小二乘解决方案(> 10,000:通常为100,000+)的程序,并且在分析之后,这些是该程序的当前瓶颈.我有一个矩阵A,其列向量对应于生成向量和解决方案b.我试图求解最小二乘解xAx=b.矩阵的大小通常为4xj - 其中很多都不是正方形(j <4),因此对于欠定系统的一般解决方案正是我所寻求的.

主要问题:在R中解决欠定系统的最快方法是什么?我有很多利用Normal Equation的解决方案,但我在R中寻找比下面任何一种方法更快的例程.

例如:x通过Ax = b给定以下约束来解决给定的系统:

  • 系统没有必要确定[通常不确定](ncol(A)<= length(b)始终保持).因此ncol (A) <= length(b)无效,因为求解需要方阵.
  • 您可以假设solve(A,b)(等效于t(A) %*% A)是非单数的 - 在程序的早期检查它
  • 您可以使用R中免费提供的任何包装
  • 解决方案不一定非常漂亮 - 只需要快速
  • 大小上限crossprod(A)合理地为10x10,零元素很少发生 - A通常非常密集

两个随机矩阵用于测试......

A = matrix(runif(12), nrow = 4)
b = matrix(runif(4), nrow = 4)
Run Code Online (Sandbox Code Playgroud)

以下所有功能均已分析.它们转载于此:

f1 = function(A,b)
{
  solve(t(A) %*% A, t(A) %*% b)
}
f2 = function(A,b)
{
  solve(crossprod(A), crossprod(A, b))
}
f3 = function(A,b)
{
  ginv(crossprod(A)) %*% crossprod(A,b) # From the `MASS` package
}
f4 = function(A,b)
{
  matrix.inverse(crossprod(A)) %*% crossprod(A,b) # From the `matrixcalc` package
}
f5 = function(A,b)
{
  qr.solve(crossprod(A), crossprod(A,b))
}
f6 = function(A,b)
{
  svd.inverse(crossprod(A)) %*% crossprod(A,b)
}
f7 = function(A,b)
{
  qr.solve(A,b)
}
f8 = function(A,b)
{
  Solve(A,b) # From the `limSolve` package
}
Run Code Online (Sandbox Code Playgroud)

经过测试,A是目前的赢家.我还测试了线性模型方法 - 考虑到它们产生的所有其他信息,它们的速度非常慢.代码使用以下内容进行了分析:

library(ggplot2)
library(microbenchmark)

all.equal(
  f1(A,b),
  f2(A,b),
  f3(A,b),
  f4(A,b),
  f5(A,b),
  f6(A,b),
  f7(A,b),
  f8(A,b),
          )

compare = microbenchmark(
  f1(A,b),
  f2(A,b),
  f3(A,b),
  f4(A,b),
  f5(A,b),
  f6(A,b),
  f7(A,b),
  f8(A,b),
  times = 1000)

autoplot(compare)
Run Code Online (Sandbox Code Playgroud)

Kha*_*haa 9

怎么样Rcpp

library(Rcpp)
cppFunction(depends='RcppArmadillo', code='
            arma::mat fRcpp (arma::mat A, arma::mat b) {
            arma::mat betahat ;
            betahat = (A.t() * A ).i() * A.t() * b ;
            return(betahat) ;
            }                                
            ')

all.equal(f1(A, b), f2(A, b), fRcpp(A, b))
#[1] TRUE
microbenchmark(f1(A, b), f2(A, b), fRcpp(A, b))
#Unit: microseconds
#        expr    min     lq     mean  median      uq     max neval
#    f1(A, b) 55.110 57.136 67.42110 59.5680 63.0120 160.873   100
#    f2(A, b) 34.444 37.685 43.86145 39.7120 41.9405 117.920   100
# fRcpp(A, b)  3.242  4.457  7.67109  8.1045  8.9150  39.307   100
Run Code Online (Sandbox Code Playgroud)