versioninfo()
Methods for solving linear regression $\widehat \beta = (\mathbf{X}^T \mathbf{X})^{-1} \mathbf{X}^T \mathbf{y}$:
Method | Flops | Remarks | Software | Stability |
---|---|---|---|---|
Sweep | $np^2 + p^3$ | $(X^TX)^{-1}$ available | SAS | less stable |
Cholesky | $np^2 + p^3/3$ | less stable | ||
QR by Householder | $2np^2 - (2/3)p^3$ | R | stable | |
QR by MGS | $2np^2$ | $Q_1$ available | stable | |
QR by SVD | $4n^2p + 8np^2 + 9p^3$ | $X = UDV^T$ | most stable |
Remarks:
There is simply no such thing as a universal 'gold standard' when it comes to algorithms.
using SweepOperator, BenchmarkTools, LinearAlgebra
linreg_cholesky(y::Vector, X::Matrix) = cholesky!(X'X) \ (X'y)
linreg_qr(y::Vector, X::Matrix) = X \ y
function linreg_sweep(y::Vector, X::Matrix)
p = size(X, 2)
xy = [X y]
tableau = xy'xy
sweep!(tableau, 1:p)
return tableau[1:p, end]
end
function linreg_svd(y::Vector, X::Matrix)
xsvd = svd(X)
return xsvd.V * ((xsvd.U'y) ./ xsvd.S)
end
using Random
Random.seed!(280) # seed
n, p = 10, 3
X = randn(n, p)
y = randn(n)
# check these methods give same answer
@show linreg_cholesky(y, X)
@show linreg_qr(y, X)
@show linreg_sweep(y, X)
@show linreg_svd(y, X);
n, p = 1000, 300
X = randn(n, p)
y = randn(n)
@benchmark linreg_cholesky(y, X)
@benchmark linreg_sweep(y, X)
@benchmark linreg_qr(y, X)
@benchmark linreg_svd(y, X)