आप एक अपघटन अपडेट करके रन के समय को कम कर सकते हैं। यह के बजाय प्रत्येक पुनरावृत्ति पर लागत उत्पन्न करता है जहां n आप विंडो चौड़ाई है। नीचे दो की तुलना करने के लिए एक कोड है। यह सी ++ में बहुत तेज़ी से कर रहा है लेकिन LINPACK dchud
और dchdd
आर के साथ शामिल नहीं हैं इसलिए आपको ऐसा करने के लिए एक पैकेज लिखना होगा। इसके अलावा, मैं पढ़ने याद है कि आप Linpack dchud
और dchdd
आर अद्यतन
library(SamplerCompare) # for LINPACK `chdd` and `chud`
roll_forcast <- function(X, y, width){
n <- nrow(X)
p <- ncol(X)
out <- rep(NA_real_, n)
is_first <- TRUE
i <- width
while(i < n){
if(is_first){
is_first <- FALSE
qr. <- qr(X[1:width, ])
R <- qr.R(qr.)
# Use X^T for the rest
X <- t(X)
XtY <- drop(tcrossprod(y[1:width], X[, 1:width]))
} else {
x_new <- X[, i]
x_old <- X[, i - width]
# update R
R <- .Fortran(
"dchud", R, p, p, x_new, 0., 0L, 0L,
0., 0., numeric(p), numeric(p),
PACKAGE = "SamplerCompare")[[1]]
# downdate R
R <- .Fortran(
"dchdd", R, p, p, x_old, 0., 0L, 0L,
0., 0., numeric(p), numeric(p), integer(1),
PACKAGE = "SamplerCompare")[[1]]
# update XtY
XtY <- XtY + y[i] * x_new - y[i - width] * x_old
}
coef. <- .Internal(backsolve(R, XtY, p, TRUE, TRUE))
coef. <- .Internal(backsolve(R, coef., p, TRUE, FALSE))
i <- i + 1
out[i] <- X[, i] %*% coef.
}
out
}
# simulate data
set.seed(101)
n <- 10000
wdth = 50
X <- matrix(rnorm(10 * n), n, 10)
y <- drop(X %*% runif(10)) + rnorm(n)
Z <- cbind(y, X)
# assign other function
lm_version <- function(Z, width = wdth) {
pred <- Z[width + 1, -1, drop = FALSE]
## fit the model
Z <- Z[-nrow(Z), ]
fit <- lm.fit(Z[, -1, drop = FALSE], Z[,1])
## get things we need to predict, in case pivoting turned on in lm.fit
p <- fit$rank
p1 <- seq_len(p)
piv <- fit$qr$pivot[p1]
## model coefficients
beta <- fit$coefficients
## this gives the predicted value for row 31 of data passed in
drop(pred[, piv, drop = FALSE] %*% beta[piv])
}
# show that they yield the same
library(zoo)
all.equal(
rollapply(Z, wdth + 1, FUN = lm_version,
by.column = FALSE, align = "right", fill = NA_real_),
roll_forcast(X, y, wdth))
#R> [1] TRUE
# benchmark
library(compiler)
roll_forcast <- cmpfun(roll_forcast)
lm_version <- cmpfun(lm_version)
microbenchmark::microbenchmark(
new = roll_forcast(X, y, wdth),
prev = rollapply(Z, wdth + 1, FUN = lm_version,
by.column = FALSE, align = "right", fill = NA_real_),
times = 10)
#R> Unit: milliseconds
#R> expr min lq mean median uq max neval cld
#R> new 113.7637 115.4498 129.6562 118.6540 122.4930 230.3414 10 a
#R> prev 639.6499 674.1677 682.1996 678.6195 686.8816 763.8034 10 b
@Zach मैं, निश्चित रूप से अनुमान आप जानते हैं कि आप यहाँ क्या कर रहे हैं के लिए के अलावा अन्य कार्यान्वयन के साथ तेजी से कर सकते हैं - प्राप्त करने की कोशिश एक कदम आगे की भविष्यवाणियां? –
@ गैविन सिम्पसन हाँ, यही वह है जो मैं कर रहा हूं। मैं इसे समानांतर करने की भी कोशिश कर रहा हूं। – Zach
@Zach - बस एक अपडेट पोस्ट किया गया जिसमें मेरे 'lm.fit()' सुझाव को लागू करने के लिए कोड शामिल है। ऐसा करने से मैं थोड़ा अधिक जटिल था। –