71 lines
2.1 KiB
R
71 lines
2.1 KiB
R
# Rosenbrock function for x in R^2
|
|
fun <- function(x, a = 1, b = 100) {
|
|
(a - x[1])^2 + b * (x[2] - x[1]^2)^2
|
|
}
|
|
# Gradient of the Rosenbrock function
|
|
grad <- function(x, a = 1, b = 100) {
|
|
2 * c(x[1] - a - b * x[1] * (x[2] - x[1]^2), b * (x[2] - x[1]^2))
|
|
}
|
|
# call with initial values (x, y) = (-1, 1)
|
|
stopifnot(all.equal(
|
|
NAGD(fun, grad, c(-1, 1), max.iter = 500L),
|
|
c(1, 1) # known minimum
|
|
))
|
|
|
|
# Equivalent to above, but the parameters are in a list
|
|
fun <- function(params, a = 1, b = 100) {
|
|
(a - params$x)^2 + b * (params$y - params$x^2)^2
|
|
}
|
|
grad <- function(params, a = 1, b = 100) list(
|
|
x = 2 * (params$x - a - b * params$x * (params$y - params$x^2)),
|
|
y = 2 * b * (params$y - params$x^2)
|
|
)
|
|
# need to tell NAGD how to combine parameters
|
|
lincomb <- function(a, LHS, b, RHS) list(
|
|
x = a * LHS$x + b * RHS$x,
|
|
y = a * LHS$y + b * RHS$y
|
|
)
|
|
# and how to compute there norm (squared)
|
|
norm2 <- function(params) {
|
|
sum(unlist(params)^2)
|
|
}
|
|
# callback invoced for each update
|
|
callback <- function(iter, params) {
|
|
cat(sprintf("%3d - fun(%7.4f, %7.4f) = %6.4f\n",
|
|
iter, params$x, params$y, fun(params)))
|
|
}
|
|
# call with initial values (x, y) = (-1, 1)
|
|
fit <- NAGD(fun, grad, list(x = -1, y = 1),
|
|
fun.lincomb = lincomb, fun.norm2 = norm2,
|
|
callback = callback)
|
|
|
|
# Weighted Least Squares for Heterosgedastic Data
|
|
# Predictors
|
|
x <- rnorm(500)
|
|
# "True" parameters
|
|
beta <- c(intercept = 1, slope = 0.5)
|
|
# Model matrix
|
|
X <- cbind(1, x)
|
|
# response + heterosgedastic noise
|
|
y <- X %*% beta + sqrt(x - min(x) + 0.1) * rnorm(length(x))
|
|
|
|
loss <- function(beta, w) {
|
|
sum((y - X %*% beta)^2 * w)
|
|
}
|
|
weights <- function(beta, w, delta = 1e-3) {
|
|
1 / pmax(abs(y - X %*% beta), delta)
|
|
}
|
|
grad <- function(beta, w) {
|
|
-2 * crossprod(X, (y - X %*% beta) * w)
|
|
}
|
|
|
|
fit <- NAGD(loss, grad, coef(lm(y ~ x)), more.params = 1, fun.more.params = weights)
|
|
|
|
# # plot the data
|
|
# plot(x, y)
|
|
# abline(beta[1], beta[2], col = "black", lty = 2, lwd = 2)
|
|
# beta.hat.lm <- coef(lm(y ~ x))
|
|
# abline(beta.hat.lm[1], beta.hat.lm[2], col = "red", lwd = 2)
|
|
# beta.hat.wls <- fit$params
|
|
# abline(beta.hat.wls[1], beta.hat.wls[2], col = "blue", lwd = 2)
|