The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
loclm() implements local linear regression, using
high-level functions. It can handle both numerical and non-numerical
variables. Non-numerical variables are converted to factors.
library(loclm)
show(packageVersion("loclm"))
#> [1] '1.0.0'
show(date())
#> [1] "Thu Jul 30 07:00:27 2026"Here I’m just setting up a nicer plotting frame.
Let’s use the multivariate Banana function variant B from
S. Kok and C. Sandrock, 2009, Locating and Characterizing the Stationary Points of the Extended Rosenbrock Function, Evolutionary Computing, 17(3), pages 437-453.
As the paper explains, variant B is pathological, especially in higher dimensions.
#### d-dimensional Banana function
## (d >= 2 is implied by x)
banana <- function(x) {
stopifnot(is.vector(x, mode = "numeric"))
d <- length(x)
if (d == 1) {
x <- c(x, 1)
d <- 2L
}
robj <- 0
for (j in seq_len(d - 1)) {
robj <- robj + 100 * (x[j]^2 - x[j+1])^2 + (x[j] - 1)^2
}
robj
}Here is a dataset of 101 runs from a 5D banana function, plus a
little noise. Feel free to play with d and
sigma.
## make a dataset
set.seed(1234) # for reproducibility, feel free to change
d <- 3
sigma <- 1
X <- matrix(runif(d * 101), ncol = d)
y <- apply(X, 1, banana) + rnorm(nrow(X), sd = sigma)
## here's where we'll predict
newX <- matrix(runif(d * 23), ncol = d)
newy <- apply(newX, 1, banana) # leave off the noiseNow use Leave-One-Out (LOO) cross-validation to set the span. We need a general-purpose LOO function.
## LOO cross-validation
LOO <- function(X, y, reg, ...) {
n <- length(y)
yhat <- vapply(seq.int(n), \(i) {
fit <- reg(X[-i, , drop=FALSE], y[-i], ...)
predict(fit, X[i, , drop=FALSE])
}, FUN.VALUE = 0)
list(yhat = yhat, res = y - yhat)
}Now call this with loclm as the regression method, and
span as the parameter.
## try different spans
span_vals <- c(seq(0.1, 0.2, 0.01), 0.75)
rmse <- vapply(span_vals, \(span) {
loo <- LOO(X, y, reg = loclm, span = span)
sqrt(mean(loo$res^2))
}, FUN.VALUE = 0)
show(cbind(span = span_vals, rmse = rmse))
#> span rmse
#> [1,] 0.10 8.302191
#> [2,] 0.11 8.136132
#> [3,] 0.12 8.008744
#> [4,] 0.13 7.910766
#> [5,] 0.14 7.944608
#> [6,] 0.15 7.262508
#> [7,] 0.16 7.284905
#> [8,] 0.17 7.398039
#> [9,] 0.18 7.391820
#> [10,] 0.19 7.454959
#> [11,] 0.20 7.617551
#> [12,] 0.75 14.358125
spanhat <- span_vals[which.min(rmse)]
show(c(span = spanhat))
#> span
#> 0.15Try with the optimal span.
fit <- loclm(X, y, span = spanhat)
pp <- predict(fit, newX)
par(op)
matplot(newX[, 2], cbind(newy, pp), pch = c(1, 2), cex = cex,
col = col,
main = sprintf("span = %s (optimal)", format(spanhat)))That’s a big improvement.
Let’s make the first input into a factor.
## first input is a factor
breaks <- seq(0, 1, 0.2)
X <- data.frame(X)
X[[1]] <- factor(LETTERS[cut(X[[1]], breaks)])
show(head(X, 10))
#> X1 X2 X3
#> 1 A 0.56507611 0.3174938
#> 2 D 0.28025778 0.7678555
#> 3 D 0.20419632 0.5263085
#> 4 D 0.13373890 0.7323019
#> 5 E 0.32568192 0.3076657
#> 6 D 0.15506197 0.4041733
#> 7 A 0.12996214 0.2044024
#> 8 B 0.43553106 0.9856331
#> 9 D 0.03864265 0.5663108
#> 10 C 0.71330156 0.2803751
newX <- data.frame(newX)
newX[[1]] <- factor(LETTERS[cut(newX[[1]], breaks)])
## OK, here is the fit
fit <- loclm(X, y, span = spanhat)
pp <- predict(fit, newX)
par(op)
matplot(newX[, 2], cbind(newy, pp), pch = c(1, 2), cex = cex,
col = col,
main = sprintf("First input is a factor"))Not a disaster.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.