Nothing
###########################################################################
# LaplaceApproximation #
# #
# The purpose of the LaplaceApproximation function is to maximize the #
# logarithm of the unnormalized joint posterior distribution of a #
# Bayesian model with one of many optimization algorithms. #
###########################################################################
LaplaceApproximation <- function(Model, parm, Data, Interval=1.0E-6,
Iterations=100, Method="SPG", Samples=1000, CovEst="Hessian",
sir=TRUE, Stop.Tolerance=1.0E-5, CPUs=1, Type="PSOCK")
{
########################## Initial Checks ##########################
time1 <- proc.time()
LA.call <- match.call()
if(missing(Model)) stop("Model is a required argument.")
if(!is.function(Model)) stop("Model must be a function.")
if(missing(Data)) stop("Data is a required argument.")
if(missing(parm)) {
cat("Initial values were not supplied, and\n")
cat("have been set to zero prior to LaplaceApproximation().\n")
parm <- rep(0, length(Data[["parm.names"]]))}
if(is.null(Data[["mon.names"]]))
stop("In Data, mon.names is NULL.")
if(is.null(Data[["parm.names"]]))
stop("In Data, parm.names is NULL.")
for (i in 1:length(Data)) {
if(is.matrix(Data[[i]])) {
if(all(is.finite(Data[[i]]))) {
mat.rank <- qr(Data[[i]], tol=1e-10)$rank
if(mat.rank < ncol(Data[[i]])) {
cat("WARNING: Matrix", names(Data)[[i]],
"may be rank-deficient.\n")}}}}
if({Interval <= 0} | {Interval > 1}) Interval <- 1.0E-6
Iterations <- min(max(round(Iterations), 10), 1000000)
"%!in%" <- function(x,table) return(match(x, table, nomatch=0) == 0)
if(Method %!in% c("AGA","BFGS","BHHH","CG","DFP","HAR","HJ","LBFGS",
"LM","NM","NR","PSO","Rprop","SGD","SOMA","SPG","SR1","TR"))
stop("Method is unknown.")
if(Stop.Tolerance <= 0) Stop.Tolerance <- 1.0E-5
as.character.function <- function(x, ... )
{
fname <- deparse(substitute(x))
f <- match.fun(x)
out <- c(sprintf('"%s" <- ', fname), capture.output(f))
if(grepl("^[<]", tail(out,1))) out <- head(out, -1)
return(out)
}
acount <- length(grep("apply", as.character.function(Model)))
if(acount > 0) {
cat("Suggestion:", acount, " possible instance(s) of apply functions\n")
cat( "were found in the Model specification. Iteration speed will\n")
cat(" increase if apply functions are vectorized in R or coded\n")}
acount <- length(grep("for", as.character.function(Model)))
if(acount > 0) {
cat("Suggestion:", acount, " possible instance(s) of for loops\n")
cat(" were found in the Model specification. Iteration speed will\n")
cat(" increase if for loops are vectorized in R or coded in a\n")
cat(" faster language such as C++ via the Rcpp package.\n")}
### Sample Size of Data
if(!is.null(Data[["n"]])) if(length(Data[["n"]]) == 1) N <- Data[["n"]]
if(!is.null(Data[["N"]])) if(length(Data[["N"]]) == 1) N <- Data[["N"]]
if(!is.null(Data[["y"]])) N <- nrow(matrix(Data[["y"]]))
if(!is.null(Data[["Y"]])) N <- nrow(matrix(Data[["Y"]]))
if(Method == "SGD") if(!is.null(Data[["Nr"]])) N <- Data[["Nr"]]
if(!is.null(N)) cat("Sample Size: ", N, "\n")
else stop("Sample size of Data not found in n, N, y, or Y.")
########################### Preparation ############################
m.old <- Model(parm, Data)
if(!is.list(m.old)) stop("Model must return a list.")
if(length(m.old) != 5) stop("Model must return five components.")
if(any(names(m.old) != c("LP","Dev","Monitor","yhat","parm")))
stop("Name mismatch in returned list of Model function.")
if(length(m.old[["LP"]]) > 1) stop("Multiple joint posteriors exist!")
if(!identical(length(parm), length(m.old[["parm"]])))
stop("The number of initial values and parameters differs.")
if(!is.finite(m.old[["LP"]])) {
cat("Generating initial values due to a non-finite posterior.\n")
if(!is.null(Data[["PGF"]]))
Initial.Values <- GIV(Model, Data, PGF=TRUE)
else Initial.Values <- GIV(Model, Data, PGF=FALSE)
m.old <- Model(Initial.Values, Data)
}
if(!is.finite(m.old[["LP"]])) stop("The posterior is non-finite.")
if(!is.finite(m.old[["Dev"]])) stop("The deviance is non-finite.")
parm <- m.old[["parm"]]
if(!identical(Model(m.old[["parm"]], Data)[["LP"]], m.old[["LP"]])) {
cat("WARNING: LP differs when initial values are held constant.\n")
cat(" Derivatives may be problematic if used.\n")}
#################### Begin Laplace Approximation ###################
cat("Laplace Approximation begins...\n")
if(Method == "AGA") {
LA <- .laaga(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "BFGS") {
LA <- .labfgs(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "BHHH") {
LA <- .labhhh(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "CG") {
LA <- .lacg(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "DFP") {
LA <- .ladfp(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "HAR") {
LA <- .lahar(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "HJ") {
LA <- .lahj(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old)
}
else if(Method == "LBFGS") {
LA <- .lalbfgs(Model, parm, Data, Iterations, Stop.Tolerance,
m.old)
}
else if(Method == "LM") {
LA <- .lalm(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "NM") {
LA <- .lanm(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "NR") {
LA <- .lanr(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "PSO") {
LA <- .lapso(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "Rprop") {
LA <- .larprop(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "SGD") {
LA <- .lasgd(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
}
else if(Method == "SOMA") {
LA <- .lasoma(Model, parm, Data,
options=list(maxiter=Iterations, tol=Stop.Tolerance))
}
else if(Method == "SPG") {
LA <- .laspg(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "SR1") {
LA <- .lasr1(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
}
else if(Method == "TR") {
LA <- .latr(Model, parm, Data, Iterations, m.old)
}
Dev <- as.vector(LA$Dev)
if(is.null(LA$H)) H <- FALSE
else H <- LA$H
iter <- LA$iter
parm.len <- LA$parm.len
parm.new <- LA$parm.new
parm.old <- LA$parm.old
post <- LA$post
Step.Size <- LA$Step.Size
tol.new <- LA$tol.new
rm(LA)
if(iter == 1) stop("LaplaceApproximation stopped at iteration 1.")
if(tol.new <= Stop.Tolerance) converged <- TRUE
else converged <- FALSE
### Column names to samples
if(ncol(post) == length(Data[["parm.names"]]))
colnames(post) <- Data[["parm.names"]]
rownames(post) <- 1:nrow(post)
######################## Covariance Matirx #########################
cat("Estimating the Covariance Matrix\n")
if(all(H == FALSE)) {
VarCov <- CovEstim(Model, parm.new, Data, Method=CovEst)
}
else {
VarCov <- -as.inverse(as.symmetric.matrix(H))
diag(VarCov) <- abs(diag(VarCov))
}
################# Sampling Importance Resampling ##################
if({sir == TRUE} & {converged == TRUE}) {
cat("Sampling from Posterior with Sampling Importance Resampling\n")
posterior <- SIR(Model, Data, mu=parm.new, Sigma=VarCov,
n=Samples, CPUs=CPUs, Type=Type)
Mon <- matrix(0, nrow(posterior), length(Data[["mon.names"]]))
dev <- rep(0, nrow(posterior))
for (i in 1:nrow(posterior)) {
mod <- Model(posterior[i,], Data)
dev[i] <- mod[["Dev"]]
Mon[i,] <- mod[["Monitor"]]
}
colnames(Mon) <- Data[["mon.names"]]}
else {
if({sir == TRUE} & {converged == FALSE})
cat("Posterior samples are not drawn due to Converge=FALSE\n")
posterior <- NA; Mon <- NA}
##################### Summary, Point-Estimate ######################
cat("Creating Summary from Point-Estimates\n")
Summ1 <- matrix(NA, parm.len, 4, dimnames=list(Data[["parm.names"]],
c("Mode","SD","LB","UB")))
Summ1[,1] <- parm.new
Summ1[,2] <- sqrt(diag(VarCov))
Summ1[,3] <- parm.new - 2*Summ1[,2]
Summ1[,4] <- parm.new + 2*Summ1[,2]
################### Summary, Posterior Samples ####################
Summ2 <- NA
if({sir == TRUE} & {converged == TRUE}) {
cat("Creating Summary from Posterior Samples\n")
Summ2 <- matrix(NA, ncol(posterior), 7,
dimnames=list(Data[["parm.names"]],
c("Mode","SD","MCSE","ESS","LB","Median","UB")))
Summ2[,1] <- colMeans(posterior)
Summ2[,2] <- sqrt(.colVars(posterior))
Summ2[,3] <- Summ2[,2] / sqrt(nrow(posterior))
Summ2[,4] <- rep(nrow(posterior), ncol(posterior))
Summ2[,5] <- apply(posterior, 2, quantile, c(0.025))
Summ2[,6] <- apply(posterior, 2, quantile, c(0.500))
Summ2[,7] <- apply(posterior, 2, quantile, c(0.975))
Deviance <- rep(0, 7)
Deviance[1] <- mean(dev)
Deviance[2] <- sd(dev)
Deviance[3] <- sd(dev) / sqrt(nrow(posterior))
Deviance[4] <- nrow(posterior)
Deviance[5] <- as.numeric(quantile(dev, probs=0.025, na.rm=TRUE))
Deviance[6] <- as.numeric(quantile(dev, probs=0.500, na.rm=TRUE))
Deviance[7] <- as.numeric(quantile(dev, probs=0.975, na.rm=TRUE))
Summ2 <- rbind(Summ2, Deviance)
for (j in 1:ncol(Mon)) {
Monitor <- rep(NA,7)
Monitor[1] <- mean(Mon[,j])
Monitor[2] <- sd(as.vector(Mon[,j]))
Monitor[3] <- sd(as.vector(Mon[,j])) / sqrt(nrow(Mon))
Monitor[4] <- nrow(Mon)
Monitor[5] <- as.numeric(quantile(Mon[,j], probs=0.025,
na.rm=TRUE))
Monitor[6] <- as.numeric(quantile(Mon[,j], probs=0.500,
na.rm=TRUE))
Monitor[7] <- as.numeric(quantile(Mon[,j], probs=0.975,
na.rm=TRUE))
Summ2 <- rbind(Summ2, Monitor)
rownames(Summ2)[nrow(Summ2)] <- Data[["mon.names"]][j]
}
}
############### Logarithm of the Marginal Likelihood ###############
LML <- list(LML=NA, VarCov=VarCov)
if({sir == TRUE} & {converged == TRUE}) {
cat("Estimating Log of the Marginal Likelihood\n")
lml <- LML(theta=posterior, LL=(dev*(-1/2)), method="NSIS")
LML[[1]] <- lml[[1]]}
else if({sir == FALSE} & {converged == TRUE}) {
cat("Estimating Log of the Marginal Likelihood\n")
LML <- LML(Model, Data, Modes=parm.new, Covar=VarCov,
method="LME")}
colnames(VarCov) <- rownames(VarCov) <- Data[["parm.names"]]
time2 <- proc.time()
############################# Output ##############################
LA <- list(Call=LA.call,
Converged=converged,
Covar=VarCov,
Deviance=as.vector(Dev),
History=post,
Initial.Values=parm,
Iterations=iter,
LML=LML[[1]],
LP.Final=as.vector(Model(parm.new, Data)[["LP"]]),
LP.Initial=m.old[["LP"]],
Minutes=round(as.vector(time2[3] - time1[3]) / 60, 2),
Monitor=Mon,
Posterior=posterior,
Step.Size.Final=Step.Size,
Step.Size.Initial=1,
Summary1=Summ1,
Summary2=Summ2,
Tolerance.Final=tol.new,
Tolerance.Stop=Stop.Tolerance)
class(LA) <- "laplace"
cat("Laplace Approximation is finished.\n\n")
return(LA)
}
.laaga <- function(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old)
{
alpha.star <- 0.234
Dev <- matrix(m.old[["Dev"]],1,1)
parm.len <- length(as.vector(parm))
parm.new <- parm.old <- m.old[["parm"]]
names(parm.new) <- names(parm.old) <- Data[["parm.names"]]
tol.new <- 1
Step.Size <- 1 / parm.len
post <- matrix(parm.new, 1, parm.len)
for (iter in 1:Iterations) {
parm.old <- parm.new
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Approximate Truncated Gradient
approx.grad <- partial(Model, parm.old, Data, Interval)
approx.grad <- interval(approx.grad, -1000, 1000, reflect=FALSE)
### Proposal
parm.new <- parm.old + Step.Size * approx.grad
if(any(!is.finite(parm.new))) parm.new <- parm.old
m.new <- Model(parm.new, Data)
tol.new <- max(sqrt(sum(approx.grad^2)),
sqrt(sum({parm.new - parm.old}^2)))
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]])))) {
m.new <- m.old
parm.new <- parm.old}
### Accept/Reject and Adapt
if(m.new[["LP"]] > m.old[["LP"]]) {
m.old <- m.new
parm.new <- m.new[["parm"]]
Step.Size <- Step.Size + (Step.Size / (alpha.star *
(1 - alpha.star))) * (1 - alpha.star) / iter
}
else {
m.new <- m.old
parm.new <- parm.old
Step.Size <- abs(Step.Size - (Step.Size / (alpha.star *
(1 - alpha.star))) * alpha.star / iter)
}
post <- rbind(post, parm.new)
Dev <- rbind(Dev, m.new[["Dev"]])
if(tol.new <= Stop.Tolerance) break
}
Dev <- Dev[-1,]; post <- post[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm.new,
parm.old=parm.old, post=post, Step.Size=Step.Size,
tol.new=tol.new)
return(LA)
}
.labfgs <- function(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old) {
m.new <- m.old
Dev <- matrix(m.old[["Dev"]],1,1)
parm.old <- parm
parm.len <- length(as.vector(parm))
post <- matrix(m.old[["parm"]], 1, parm.len)
tol.new <- 1
keepgoing <- TRUE
g.old <- g.new <- rep(0, parm.len)
B <- diag(parm.len) #Approximate Hessian
options(warn=-1)
for (iter in 2:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Gradient and Direction p
g.old <- g.new
g.new <- -1*partial(Model, m.old[["parm"]], Data, Interval)
p <- as.vector(tcrossprod(g.new, -B))
p[which(!is.finite(p))] <- 0
### Step-size Line Search
Step.Size <- 0.8
changed <- TRUE
while(m.new[["LP"]] <= m.old[["LP"]] & changed == TRUE) {
Step.Size <- Step.Size * 0.2
s <- Step.Size*p
prop <- m.old[["parm"]] + s
changed <- !identical(m.old[["parm"]], prop)
m.new <- Model(prop, Data)
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
}
### BFGS Update to Approximate Hessian B
if(m.new[["LP"]] > m.old[["LP"]]) {
m.old <- m.new
g <- g.new - g.old
CC <- sum(s*g) #Curvature condition
if(CC > 0) {
y <- as.vector(crossprod(B, g))
D <- as.double(1 + crossprod(g, y)/CC)
B <- B - (tcrossprod(s, y) + tcrossprod(y, s) -
D * tcrossprod(s, s))/CC}
if(any(!is.finite(B))) B <- diag(parm.len)
}
### Storage
post <- rbind(post, m.old[["parm"]])
Dev <- rbind(Dev, m.old[["Dev"]])
### Tolerance
tol.new <- sqrt(sum(s*s))
if(keepgoing == FALSE) tol.new <- 0
if(tol.new <= Stop.Tolerance) break
}
options(warn=0)
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len,
parm.new=m.old[["parm"]], parm.old=parm.old, post=post,
Step.Size=Step.Size, tol.new=tol.new)
return(LA)
}
.labhhh <- function(Model, parm, Data, Interval, Iterations=100,
Stop.Tolerance, m.old)
{
### Check data for X and y or Y
if(is.null(Data[["X"]])) stop("X is required in the data.")
y <- TRUE
if(is.null(Data[["y"]])) {
y <- FALSE
if(is.null(Data[["Y"]])) stop("y or Y is required in the data.")}
if(y == TRUE) {
if(length(Data[["y"]]) != nrow(Data[["X"]]))
stop("length of y differs from rows in X.")
}
else {
if(nrow(Data[["Y"]]) != nrow(Data[["X"]]))
stop("The number of rows differs in y and X.")}
m.new <- m.old
Dev <- matrix(m.old[["Dev"]],1,1)
parm.old <- parm
parm.len <- length(parm)
post <- matrix(parm, 1, parm.len)
tol.new <- 1
options(warn=-1)
for (iter in 2:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Gradient p, OPG A from gradient g, and direction delta
p <- partial(Model, m.old[["parm"]], Data, Interval)
A <- matrix(0, parm.len, parm.len)
for (i in 1:nrow(Data[["X"]])) {
Data.temp <- Data
Data.temp$X <- Data.temp$X[i,,drop=FALSE]
if(y == TRUE) Data.temp$y <- Data.temp$y[i]
else Data.temp$Y <- Data.temp$Y[i,]
g <- partial(Model, m.old[["parm"]], Data.temp, Interval)
A <- A + tcrossprod(g,g)}
A <- -as.inverse(as.symmetric.matrix(A))
delta <- as.vector(tcrossprod(p, -A))
### Step-size Line Search
Step.Size <- 0.8
changed <- TRUE
while(m.new[["LP"]] <= m.old[["LP"]] & changed == TRUE) {
Step.Size <- Step.Size * 0.2
s <- Step.Size*delta
prop <- m.old[["parm"]] + s
changed <- !identical(m.old[["parm"]], prop)
m.new <- Model(prop, Data)
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
}
if(m.new[["LP"]] > m.old[["LP"]]) m.old <- m.new
### Storage
post <- rbind(post, m.old[["parm"]])
Dev <- rbind(Dev, m.old[["Dev"]])
### Tolerance
tol.new <- sqrt(sum(delta*delta))
if(tol.new < Stop.Tolerance) break
}
options(warn=0)
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len,
parm.new=m.old[["parm"]], parm.old=parm.old, post=post,
Step.Size=Step.Size, tol.new=tol.new)
return(LA)
}
.lacg <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
m.best <- m.new <- m.old
parm.len <- length(parm)
tol <- Stop.Tolerance
tol.new <- 1
Dev <- matrix(m.old[["Dev"]],1,1)
post <- matrix(parm, 1, parm.len)
eps <- 1e-7
bvec <- parm.old <- parm
n <- length(bvec)
ig <- 0 # count gradient evaluations
stepredn <- 0.15 # Step reduction in line search
acctol <- 1e-04 # acceptable point tolerance
reltest <- 100 # relative equality test
accpoint <- as.logical(FALSE) # so far do not have an acceptable point
cyclimit <- min(2.5 * n, 10 + sqrt(n))
fmin <- f <- m.old[["LP"]] * -1
bvec <- m.old[["parm"]]
keepgoing <- TRUE
oldstep <- steplength <- 0.8
fdiff <- NA # initially no decrease
cycle <- 0 # !! cycle loop counter
options(warn=-1)
while (keepgoing == TRUE) {
t <- as.vector(rep(0, n)) # zero step vector
c <- t # zero 'last' gradient
while ({keepgoing == TRUE} && {cycle < cyclimit}) {
cycle <- cycle + 1
parm <- bvec
ig <- ig + 1
post <- rbind(post, m.best[["parm"]])
Dev <- rbind(Dev, m.best[["Dev"]])
### Print Status
if(ig %% round(Iterations / 10) == 0)
cat("Iteration: ", ig, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
if(ig > Iterations) {
ig <- Iterations
LA <- list(Dev=Dev, iter=ig, parm.len=parm.len,
parm.new=parm, parm.old=parm.old, post=post,
Step.Size=steplength, tol.new=tol.new)
return(LA)}
g <- partial(Model, bvec, Data) * -1
g1 <- sum(g * (g - c))
g2 <- sum(t * (g - c))
gradsqr <- sum(g * g)
c <- g
g3 <- 1
if(gradsqr > tol * (abs(fmin) + reltest)) {
if(g2 > 0) {
betaDY <- gradsqr / g2
betaHS <- g1 / g2
g3 <- max(0, min(betaHS, betaDY))}
}
else {
keepgoing <- FALSE
tol.new <- gradsqr
break}
if(g3 == 0 || cycle >= cyclimit) {
fdiff <- NA
cycle <- 0
break
}
else {
t <- t * g3 - g
gradproj <- sum(t * g)
### Line search
OKpoint <- FALSE
steplength <- oldstep * 1.5
f <- fmin
changed <- TRUE
while ({f >= fmin} && {changed == TRUE}) {
bvec <- parm + steplength * t
changed <- !identical((bvec + reltest),
(parm + reltest))
if(changed == TRUE) {
m.old <- m.new
m.new <- Model(bvec, Data)
if(any(!is.finite(c(m.new[["LP"]],
m.new[["Dev"]], m.new[["Monitor"]])))) {
f <- fmin + 1
m.new <- m.old
}
else {
if(m.new[["LP"]] > m.best[["LP"]])
m.best <- m.new
f <- m.new[["LP"]] * -1
tol.new <- max(sqrt(sum(g*g)),
sqrt(sum({m.new[["parm"]] -
m.old[["parm"]]}^2)))
}
bvec <- m.new[["parm"]]
if(f < fmin) f1 <- f
else {
savestep <-steplength
steplength <- steplength * stepredn
if(steplength >= savestep) changed <-FALSE}}}
changed1 <- changed
if(changed1 == TRUE) {
newstep <- 2 * (f - fmin - gradproj * steplength)
if(newstep > 0)
newstep <- -(gradproj * steplength *
steplength / newstep)
bvec <- parm + newstep * t
changed <- !identical((bvec + reltest),
(parm + reltest))
if(changed == TRUE) {
m.old <- m.new
m.new <- Model(bvec, Data)
if(any(!is.finite(c(m.new[["LP"]],
m.new[["Dev"]], m.new[["Monitor"]])))) {
f <- fmin + 1
m.new <- m.old
}
else {
if(m.new[["LP"]] > m.best[["LP"]])
m.best <- m.new
f <- m.new[["LP"]] * -1
tol.new <- max(sqrt(sum(g*g)),
sqrt(sum({m.new[["parm"]] -
m.old[["parm"]]}^2)))
}
bvec <- m.new[["parm"]]}
if(f < min(fmin, f1)) {
OKpoint <- TRUE
accpoint <- (f <= fmin + gradproj *
newstep * acctol)
fdiff <- (fmin - f)
fmin <- f
oldstep <- newstep
}
else {
if(f1 < fmin) {
bvec <- parm + steplength * t
accpoint <- (f1 <= fmin + gradproj *
steplength * acctol)
OKpoint <- TRUE
fdiff <- (fmin - f1)
fmin <- f1
oldstep <- steplength
}
else {
fdiff <- NA
accpoint <- FALSE}
}
if(accpoint == FALSE) {
keepgoing <- FALSE
break}
}
else {
if(cycle == 1) {
keekpgoing <- FALSE
break}}}
}
if(oldstep < acctol) oldstep <- acctol
if(oldstep > 1) oldstep <- 1
}
options(warn=0)
Dev <- Dev[-1,]; post <- post[-1,]
if({ig < Iterations} & {tol.new > Stop.Tolerance})
tol.new <- Stop.Tolerance
### Output
LA <- list(Dev=Dev, iter=ig, parm.len=parm.len,
parm.new=m.best[["parm"]], parm.old=parm.old, post=post,
Step.Size=steplength, tol.new=tol.new)
return(LA)
}
.ladfp <- function(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old) {
m.new <- m.old
Dev <- matrix(m.old[["Dev"]],1,1)
parm.old <- parm
parm.len <- length(as.vector(parm))
post <- matrix(m.old[["parm"]], 1, parm.len)
tol.new <- 1
keepgoing <- TRUE
g.old <- g.new <- -1*partial(Model, m.old[["parm"]], Data, Interval)
B <- Iden <- diag(parm.len) #Approximate Hessian
options(warn=-1)
for (iter in 2:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Gradient and Direction p
g.old <- g.new
p <- as.vector(tcrossprod(g.old, -B))
p[which(!is.finite(p))] <- 0
### Step-size Line Search
Step.Size <- 0.8
changed <- TRUE
while(m.new[["LP"]] <= m.old[["LP"]] & changed == TRUE) {
Step.Size <- Step.Size * 0.2
s <- Step.Size*p
prop <- m.old[["parm"]] + s
changed <- !identical(m.old[["parm"]], prop)
m.new <- Model(prop, Data)
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
}
g.new <- -1*partial(Model, m.new[["parm"]], Data, Interval)
### DFP Update to Approximate Hessian B
if(m.new[["LP"]] > m.old[["LP"]]) {
m.old <- m.new
g <- g.new - g.old
if(sum(s*g) > 0) {
denom <- as.vector(t(g) %*% s)
B <- (Iden - ((g %*% t(s)) / denom)) %*% B %*%
(Iden - ((s %*% t(g)) / denom)) +
((g %*% t(g)) / denom)
if(any(!is.finite(B))) B <- diag(parm.len)}}
### Storage
post <- rbind(post, m.old[["parm"]])
Dev <- rbind(Dev, m.old[["Dev"]])
### Tolerance
tol.new <- sqrt(sum(g.new*g.new))
if(keepgoing == FALSE) tol.new <- 0
if(tol.new <= Stop.Tolerance) break
}
options(warn=0)
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len,
parm.new=m.old[["parm"]], parm.old=parm.old, post=post,
Step.Size=Step.Size, tol.new=tol.new)
return(LA)
}
.lahar <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
alpha.star <- 0.234
tau <- 1
Dev <- matrix(m.old[["Dev"]],1,1)
parm.len <- length(as.vector(parm))
parm.new <- parm.old <- parm
names(parm.new) <- names(parm.old) <- Data[["parm.names"]]
tol.new <- 1
post <- matrix(parm.new, 1, parm.len)
for (iter in 1:Iterations) {
parm.old <- parm.new
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Propose new parameter values
theta <- rnorm(parm.len)
d <- theta / sqrt(sum(theta*theta))
Step.Size <- runif(1,0,tau)
parm.new <- parm.old + Step.Size * d
m.new <- Model(parm.new, Data)
tol.new <- sqrt(sum({m.new[["parm"]] - parm.old}^2))
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
### Accept/Reject and Adapt
if(m.new[["LP"]] > m.old[["LP"]]) {
m.old <- m.new
parm.new <- m.new[["parm"]]
tau <- tau + (tau / (alpha.star *
(1 - alpha.star))) * (1 - alpha.star) / iter
}
else {
m.new <- m.old
parm.new <- parm.old
tau <- abs(tau - (tau / (alpha.star *
(1 - alpha.star))) * alpha.star / iter)
}
post <- rbind(post, parm.new)
Dev <- rbind(Dev, m.new[["Dev"]])
if(tol.new <= Stop.Tolerance) break
}
Dev <- Dev[-1,]; post <- post[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm.new,
parm.old=parm.old, post=post, Step.Size=Step.Size,
tol.new=tol.new)
return(LA)
}
.lahj <- function(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
n <- length(parm)
post <- matrix(parm, 1, n)
if(n == 1)
stop("For univariate functions use some different method.")
tol.new <- 1
f <- function(x, Data) {
fun <- Model(x, Data)
fun[["LP"]] <- fun[["LP"]] * -1
return(fun)}
steps <- 2^c(-(0:(Iterations-1)))
dir <- diag(1, n, n)
x <- parm.old <- parm
fx <- f(x, Data)
fcount <- 1
### Search with a single scale
.lahjsearch <- function(xb, f, h, dir, fcount, Data)
{
x <- xb
xc <- x
sf <- 0
finc <- 0
hje <- .lahjexplore(xb, xc, f, h, dir, Data=Data)
x <- hje$x
fx <- hje$fx
sf <- hje$sf
finc <- finc + hje$numf
### Pattern move
while (sf == 1) {
d <- x - xb
xb <- x
xc <- x + d
fb <- fx
hje <- .lahjexplore(xb, xc, f, h, dir, fb, Data)
x <- hje$x
fx <- hje$fx
sf <- hje$sf
finc <- finc + hje$numf
if(sf == 0) { # pattern move failed
hje <- .lahjexplore(xb, xb, f, h, dir, fb, Data)
x <- hje$x
fx <- hje$fx
sf <- hje$sf
finc <- finc + hje$numf}
}
return(list(x=x, fx=fx, sf=sf, finc=finc))
}
### Exploratory move
.lahjexplore <- function(xb, xc, f, h, dir, fbold, Data)
{
n <- length(xb)
x <- xb
if(missing(fbold)) {
fb <- f(x, Data)
x <- fb[["parm"]]
numf <- 1
}
else {
fb <- fbold
numf <- 0}
fx <- fb
xt <- xc
sf <- 0 # do we find a better point ?
dirh <- h * dir
fbold <- fx
for (k in sample.int(n, n)) { # resample orthogonal directions
p <- xt + dirh[, k]
ft <- f(p, Data)
p <- ft[["parm"]]
numf <- numf + 1
if(ft[["LP"]] >= fb[["LP"]]) {
p <- xt - dirh[, k]
ft <- f(p, Data)
p <- ft[["parm"]]
numf <- numf + 1
}
else {
sf <- 1
xt <- p
fb <- ft}
}
if(sf == 1) {
x <- xt
fx <- fb}
return(list(x=x, fx=fx, sf=sf, numf=numf))
}
### Start the main loop
for (iter in 1:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(fx[["LP"]],1), "\n")
hjs <- .lahjsearch(x, f, steps[iter], dir, fcount, Data)
x <- hjs$x
fx <- hjs$fx
sf <- hjs$sf
fcount <- fcount + hjs$finc
post <- rbind(post, x)
Dev <- rbind(Dev, fx[["Dev"]])
tol.new <- sqrt(sum({fx[["parm"]] - parm.old}^2))
if(tol.new <= Stop.Tolerance) break
parm.old <- x
}
Dev <- Dev[-1,]; post <- post[-1,]
LA <- list(Dev=Dev, iter=iter, parm.len=n, parm.new=x,
parm.old=parm, post=post, Step.Size=steps[iter],
tol.new=tol.new)
return(LA)
}
.lalbfgs <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
parm.len <- length(as.vector(parm))
parm.new <- parm.old <- m.old[["parm"]]
names(parm.new) <- names(parm.old) <- Data[["parm.names"]]
tol.new <- 1
post <- matrix(parm.new, 1, parm.len)
ModelWrapper <- function(parm.new) {
out <- Model(parm.new, Data)[["LP"]]
return(out)
}
for (iter in 1:Iterations) {
parm.old <- parm.new
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### LBFGS
Fit <- optim(par=parm.new, fn=ModelWrapper,
method="L-BFGS-B", control=list(fnscale=-1, maxit=1))
m.new <- Model(Fit$par, Data)
tol.new <- sqrt(sum({m.new[["parm"]] - parm.old}^2))
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))) | {m.new[["LP"]] < m.old[["LP"]]})
m.new <- m.old
m.old <- m.new
parm.new <- m.new[["parm"]]
post <- rbind(post, parm.new)
Dev <- rbind(Dev, m.new[["Dev"]])
if(tol.new <= Stop.Tolerance) break
}
Dev <- Dev[-1,]; post <- post[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm.new,
parm.old=parm.old, post=post, Step.Size=0,
tol.new=tol.new)
return(LA)
}
.lalm <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
Norm <- function(x, p=2) {
stopifnot(is.numeric(x) || is.complex(x), is.numeric(p),
length(p) == 1)
if(p > -Inf && p < Inf) return(sum(abs(x)^p)^(1/p))
else if(p == Inf) return(max(abs(x)))
else if(p == -Inf) return(min(abs(x)))
else return(NULL)
}
Dev <- matrix(m.old[["Dev"]],1,1)
tau <- 1e-3 ### Damping constant
tolg <- 1e-8
n <- length(parm)
m <- 1
x <- xnew <- parm
mod <- modbest <- m.old
r <- r.adj <- mod[["LP"]]
if(r.adj > 0) r.adj <- r.adj * -1
dold <- dnew <- mod[["Dev"]]
x <- parm <- mod[["parm"]]
post <- matrix(parm, 1, n)
f <- 0.5 * r * r
J <- rbind(partial(Model, x, Data))
g <- t(J) %*% r.adj
ng <- max(abs(g))
A <- t(J) %*% J
mu <- tau * max(diag(A)) ### Damping parameter
nu <- 2
nh <- 0
iter <- 1
while (iter < Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(mod[["LP"]],1), "\n")
iter <- iter + 1
R <- chol(A + mu*diag(n))
h <- c(-t(g) %*% chol2inv(R))
bad <- !is.finite(h)
h[bad] <- 1e-10 * J[1,bad] #Small gradient if ill-conditioned
nh <- Norm(h)
xnew <- x + h
h <- xnew - x
dL <- sum(h*(mu*h - g)) / 2
mod <- Model(xnew, Data)
if(all(is.finite(c(mod[["LP"]], mod[["Dev"]],
mod[["Monitor"]])))) {
if(mod[["LP"]] > modbest[["LP"]]) modbest <- mod
rn <- mod[["LP"]]
xnew <- mod[["parm"]]
}
else {
rn <- r
xnew <- x}
fn <- 0.5 * rn * rn
Jn <- rbind(partial(Model, xnew, Data))
df <- f - fn
if(rn > 0) df <- fn - f
if(dL > 0 && df > 0) {
tol.new <- sqrt(sum({xnew - x}^2))
x <- xnew
f <- fn
J <- Jn
r <- r.adj <- rn
if(r.adj > 0) r.adj <- r.adj * -1
A <- t(J) %*% J
g <- t(J) %*% r.adj
ng <- Norm(g, Inf)
mu <- mu * max(1/3, 1 - (2*df/dL - 1)^3)
nu <- 2}
else {mu <- mu*nu
nu <- 2*nu}
post <- rbind(post, modbest[["parm"]])
Dev <- rbind(Dev, modbest[["Dev"]])
if(ng <= Stop.Tolerance) {
tol.new <- ng
break
}
else if(nh <= Stop.Tolerance) {
tol.new <- nh
break}
}
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=n, parm.new=modbest[["parm"]],
parm.old=parm, post=post, Step.Size=nh, tol.new=tol.new)
return(LA)
}
.lanm <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
n <- length(as.vector(parm))
parm.old <- m.old[["parm"]]
Step.Size <- 1
if(!is.numeric(parm) || length(parm) < 2)
stop("Parameters must be a numeric vector of length > 1.")
# simplex vertices around parm
V <- t(1/(2*n) * cbind(diag(n), rep(-1, n)) + parm)
P <- Q <- c()
# Function values at vertices
Y <- numeric(n+1)
for (j in 1:(n+1)) {
Mo <- Model(V[j, ], Data)
Y[j] <- Mo[["LP"]] * -1
V[j,] <- Mo[["parm"]]}
ho <- lo <- which.min(Y)
li <- hi <- which.max(Y)
for (j in 1:(n+1)) {
if(j != lo && j != hi && Y[j] <= Y[li]) li <- j
if(j != hi && j != lo && Y[j] >= Y[ho]) ho <- j}
iter <- 0
while(Y[hi] > Y[lo] + Stop.Tolerance && iter < Iterations) {
S <- numeric(n)
for (j in 1:(n+1)) S <- S + V[j,1:n]
M <- (S - V[hi,1:n])/n
R <- 2*M - V[hi,1:n]
Mo <- Model(R, Data)
yR <- Mo[["LP"]] * -1
R <- Mo[["parm"]]
if(yR < Y[ho]) {
if(Y[li] < yR) {
V[hi,1:n] <- R
Y[hi] <- yR
}
else {
E <- 2*R - M
Mo <- Model(E, Data)
yE <- Mo[["LP"]] * -1
E <- Mo[["parm"]]
if(yE < Y[li]) {
V[hi,1:n] <- E
Y[hi] <- yE
}
else {
V[hi,1:n] <- R
Y[hi] <- yR
}
}
}
else {
if(yR < Y[hi]) {
V[hi,1:n] <- R
Y[hi] <- yR}
C <- (V[hi,1:n] + M) / 2
Mo <- Model(C, Data)
yC <- Mo[["LP"]] * -1
C <- Mo[["parm"]]
C2 <- (M + R) / 2
Mo <- Model(C2, Data)
yC2 <- Mo[["LP"]] * -1
C2 <- Mo[["parm"]]
if(yC2 < yC) {
C <- C2
yC <- yC2}
if(yC < Y[hi]) {
V[hi,1:n] <- C
Y[hi] <- yC
}
else {
for (j in 1:(n+1)) {
if(j != lo) {
V[j,1:n] <- (V[j,1:n] + V[lo,1:n]) / 2
Z <- V[j,1:n]
Mo <- Model(Z, Data)
Y[j] <- Mo[["LP"]] * -1
Z <- Mo[["parm"]]
V[j,1:n] <- Z}}}}
ho <- lo <- which.min(Y)
li <- hi <- which.max(Y)
for (j in 1:(n+1)) {
if(j != lo && j != hi && Y[j] <= Y[li]) li <- j
if(j != hi && j != lo && Y[j] >= Y[ho]) ho <- j}
iter <- iter + 1
if(iter %% round(Iterations / 10) == 0) {
cat("Iteration: ", iter, " of ", Iterations, "\n")}
P <- rbind(P, V[lo, ])
Q <- c(Q, Y[lo])
Dev <- rbind(Dev, Model(V[lo,], Data)[["Dev"]])
}
snorm <- 0
for (j in 1:(n+1)) {
s <- abs(V[j] - V[lo])
if(s >= snorm) snorm <- s}
V0 <- V[lo, 1:n]
y0 <- Y[lo]
dV <- snorm
dy <- abs(Y[hi] - Y[lo])
Dev <- Dev[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=n, parm.new=V0,
parm.old=parm.old, post=P, Step.Size=Step.Size,
tol.new=Y[hi] - Y[lo])
return(LA)
}
.lanr <- function(Model, parm, Data, Interval, Iterations=100, Stop.Tolerance,
m.old)
{
m.new <- m.old
Dev <- matrix(m.old[["Dev"]],1,1)
Step.Size <- 1 / length(parm)
parm.old <- parm
parm.len <- length(parm)
converged <- FALSE
post <- matrix(parm, 1, parm.len)
for (iter in 1:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
check1 <- TRUE; check2 <- FALSE
m.old <- Model(parm, Data)
p <- partial(Model, m.old[["parm"]], Data, Interval)
H <- Hessian(Model, m.old[["parm"]], Data)
if(all(is.finite(H))) {
Sigma <- -as.inverse(H)
delta <- as.vector(tcrossprod(p, Sigma))
}
else check1 <- FALSE
if(check1 == TRUE) {
if(any(!is.finite(delta))) check1 <- FALSE
if(check1 == TRUE) {
temp1 <- temp2 <- temp3 <- parm
Step.Size1 <- Step.Size / 2
Step.Size3 <- Step.Size * 2
temp1 <- temp1 + Step.Size1 * delta
temp2 <- temp2 + Step.Size * delta
temp3 <- temp3 + Step.Size3 * delta
Mo1 <- Model(temp1, Data)
Mo2 <- Model(temp2, Data)
Mo3 <- Model(temp3, Data)
check2 <- FALSE
if({Mo1[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo1[["LP"]] > m.old[["LP"]]) {
Step.Size <- Step.Size1
parm <- parm + Step.Size * delta
m.old <- m.new <- Mo1
}
else if({Mo2[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo2[["LP"]] > m.old[["LP"]]) {
parm <- parm + Step.Size * delta
m.old <- m.new <- Mo2
}
else if({Mo3[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo3[["LP"]] > m.old[["LP"]]) {
Step.Size <- Step.Size3
parm <- parm + Step.Size * delta
m.old <- m.new <- Mo3
}
else check2 <- TRUE}}
if({check1 == FALSE} | {check2 == TRUE}) {
delta <- p
temp1 <- temp2 <- temp3 <- parm
Step.Size1 <- Step.Size / 2
Step.Size3 <- Step.Size * 2
temp1 <- temp1 + Step.Size1 * delta
temp2 <- temp2 + Step.Size * delta
temp3 <- temp3 + Step.Size3 * delta
Mo1 <- Model(temp1, Data)
Mo2 <- Model(temp2, Data)
Mo3 <- Model(temp3, Data)
if({Mo1[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo1[["LP"]] > m.old[["LP"]]) {
Step.Size <- Step.Size1
parm <- parm + Step.Size * delta
m.old <- m.new <- Mo1
}
else if({Mo2[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo2[["LP"]] > m.old[["LP"]]) {
parm <- parm + Step.Size * delta
f <- Mo2
}
else if({Mo3[["LP"]] == max(Mo1[["LP"]], Mo2[["LP"]],
Mo3[["LP"]])} & Mo3[["LP"]] > m.old[["LP"]]) {
Step.Size <- Step.Size3
parm <- parm + Step.Size * delta
m.old <- m.new <- Mo3
}
else { #Jitter in case of failure
Step.Size <- Step.Size / 2
parm <- parm + Step.Size * rnorm(length(parm))}}
post <- rbind(post, parm)
Dev <- rbind(Dev, m.new[["Dev"]])
Step.Size <- max(Step.Size, .Machine$double.eps)
tol.new <- sqrt(sum(delta^2))
if(tol.new < Stop.Tolerance) {converged <- TRUE; break}
}
Dev <- Dev[-1,]; post <- post[-1,]
LA <- list(Dev=Dev, H=H, iter=iter, parm.len=parm.len, parm.new=parm,
parm.old=parm.old, post=post, Step.Size=Step.Size,
tol.new=tol.new)
return(LA)
}
.lapso <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
LP <- NA
parm.len <- length(parm)
parm.new <- parm.old <- parm
tol.new <- 1
post <- matrix(parm.new, 1, parm.len)
p.s <- floor(10 + 2*sqrt(parm.len)) ## Swarm size
k <- 3 ### Exponent for calculating number of informants
p.p <- 1-(1-1/p.s)^k ### Average % of informants
p.w0 <- p.w1 <- 1 / (2*log(2)) ### Exploitation constants
p.c.p <- 0.5 + log(2) ### Local exploration constant
p.c.g <- 0.5 + log(2) ### Global exploration constant
p.randorder <- TRUE ### Randomize Particle Order
X <- V <- matrix(parm, parm.len, p.s)
if(!is.null(Data[["PGF"]])) {
for (i in 2:ncol(X)) X[,i] <- GIV(Model, Data, PGF=TRUE)
for (i in 1:ncol(V)) V[,i] <- GIV(Model, Data, PGF=TRUE)
}
else {
for (i in 2:ncol(X)) X[,i] <- GIV(Model, Data, PGF=FALSE)
for (i in 1:ncol(V)) V[,i] <- GIV(Model, Data, PGF=FALSE)}
V <- (V - X) / 2 ### Velocity
mods <- apply(X, 2, function(x) Model(x, Data))
f.x <- sapply(mods, with, LP) * -1
f.d <- sapply(mods, with, Dev)
X <- matrix(sapply(mods, with, parm), nrow(X), ncol(X))
P <- X
f.p <- f.x
P.improved <- rep(FALSE, p.s)
i.best <- which.min(f.p)
error <- f.p[i.best]
init.links <- TRUE
iter <- 1
while (iter < Iterations && tol.new > Stop.Tolerance) {
iter <- iter + 1
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(mod[["LP"]],1), "\n")
if(p.p != 1 && init.links == TRUE) {
links <- matrix(runif(p.s*p.s, 0, 1) <= p.p, p.s, p.s)
diag(links) <- TRUE}
if(p.randorder == TRUE) index <- sample(p.s)
else index <- 1:p.s
for (i in index) {
if(p.p == 1) j <- i.best
else j <- which(links[,i])[which.min(f.p[links[,i]])]
temp <- p.w0 + (p.w1 - p.w0)*(iter / Iterations)
V[,i] <- temp*V[,i]
V[,i] <- V[,i] +
runif(parm.len, 0, p.c.p)*(P[,i] - X[,i])
if(i != j)
V[,i] <- V[,i] +
runif(parm.len, 0, p.c.g)*(P[,j] - X[,i])
X[,i] <- X[,i] + V[,i]
mod <- Model(X[,i], Data)
f.x[i] <- mod[["LP"]] * -1
f.d[i] <- mod[["Dev"]]
X[,i] <- mod[["parm"]]
if(f.x[i] < f.p[i]) { ### Improvement
P[,i] <- X[,i]
f.p[i] <- f.x[i]
if(f.p[i] < f.p[i.best]) i.best <- i}
}
post <- rbind(post, P[,i.best])
Dev <- rbind(Dev, f.d[i.best])
tol.new <- mean(abs(V[,i.best]))
init.links <- f.p[i.best] == error
error <- f.p[i.best]
}
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=P[,i.best],
parm.old=parm.old, post=post, Step.Size=mean(abs(V[,i.best])),
tol.new=tol.new)
return(LA)
}
.larprop <- function(Model, parm, Data, Interval, Iterations,
Stop.Tolerance, m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
parm.len <- length(as.vector(parm))
approx.grad.old <- approx.grad.new <- rep(0, parm.len)
parm.old <- m.old[["parm"]]
parm.new <- parm.old - 0.1 #First step
names(parm.new) <- names(parm.old) <- Data[["parm.names"]]
tol.new <- 1
post <- matrix(parm.new, 1, parm.len)
Step.Size <- rep(0.0125, parm.len)
for (iter in 1:Iterations) {
approx.grad.old <- approx.grad.new
parm.old <- parm.new
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Approximate Truncated Gradient
approx.grad.new <- partial(Model, parm.old, Data, Interval)
approx.grad.new <- interval(approx.grad.new, -1000, 1000,
reflect=FALSE)
### Determine if Gradients Changed Sign
change <- (approx.grad.old >= 0) == (approx.grad.new >= 0)
### Adjust weight (step size) based on sign change
Step.Size[change == TRUE] <- Step.Size[change == TRUE] * 0.5
Step.Size[change == FALSE] <- Step.Size[change == FALSE] * 1.2
Step.Size <- interval(Step.Size, 0.0001, 50, reflect=FALSE)
### Propose new state based on weighted approximate gradient
parm.new <- parm.old + Step.Size * approx.grad.new
m.new <- Model(parm.new, Data)
tol.new <- max(sqrt(sum(approx.grad.new^2)),
sqrt(sum({m.new[["parm"]] - parm.old}^2)))
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))) | {m.new[["LP"]] < m.old[["LP"]]}) {
p.order <- sample(1:length(parm.new))
parm.temp <- parm.old
for (i in 1:length(p.order)) {
parm.temp[p.order[i]] <- parm.new[p.order[i]]
m.new <- Model(parm.temp, Data)
if(m.new[["LP"]] < m.old[["LP"]])
parm.temp[p.order[i]] <- parm.old[p.order[i]]}
m.new <- Model(parm.temp, Data)}
parm.new <- m.new[["parm"]]
post <- rbind(post, parm.new)
Dev <- rbind(Dev, m.new[["Dev"]])
if(tol.new <= Stop.Tolerance) break
}
Dev <- Dev[-1,]; post <- post[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm.new,
parm.old=parm.old, post=post, Step.Size=Step.Size,
tol.new=tol.new)
return(LA)
}
.lasgd <- function(Model, parm, Data, Iterations, Stop.Tolerance, m.old)
{
Dev <- matrix(m.old[["Dev"]],1,1)
m.new <- m.old
parm.len <- length(as.vector(parm))
parm.new <- parm.old <- parm
names(parm.new) <- names(parm.old) <- Data[["parm.names"]]
tol.new <- 1
post <- matrix(parm.new, 1, parm.len)
#Read SGD specifications
if(is.null(Data[["file"]]))
stop("SGD requires Data$file, which is missing.")
if(is.null(Data[["Nr"]])) stop("SGD requires Data$Nr, which is missing.")
if(is.null(Data[["Nc"]])) stop("SGD requires Data$Nc, which is missing.")
if(is.null(Data[["size"]]))
stop("SGD requires Data$size, which is missing.")
if(is.null(Data[["epsilon"]]))
stop("SGD requires Data$epsilon, which is missing.")
con <- file(Data[["file"]], open="r")
on.exit(close(con))
for (iter in 1:Iterations) {
parm.old <- parm.new
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Sample Data
seek(con, 0)
skip.rows <- sample.int(Data[["Nr"]] - Data[["size"]], size=1)
Data[["X"]] <- matrix(scan(file=con, sep=",", skip=skip.rows,
nlines=Data[["size"]], quiet=TRUE), Data[["size"]],
Data[["Nc"]], byrow=TRUE)
### Propose new parameter values
g <- partial(Model, m.old[["parm"]], Data)
parm.new <- m.new[["parm"]] + {Data[["epsilon"]] / 2} * g
m.new <- Model(parm.new, Data)
tol.new <- max(sqrt(sum(g^2)),
sqrt(sum({m.new[["parm"]] - parm.old}^2)))
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
post <- rbind(post, parm.new)
Dev <- rbind(Dev, m.new[["Dev"]])
if(tol.new <= Stop.Tolerance) break
}
Dev <- Dev[-1,]; post <- post[-1,]
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm.new,
parm.old=parm.old, post=post, Step.Size=Data[["epsilon"]],
tol.new=tol.new)
return(LA)
}
.lasoma <- function(Model, parm, Data, bounds, options=list())
{
### Initial Checks
if(missing(bounds)) {
bounds <- list(min=rep(-.Machine$double.xmax,
length(parm)),
max=rep(.Machine$double.xmax, length(parm)))
}
if(!(all(c("min","max") %in% names(bounds))))
stop("Bounds list must contain \"min\" and \"max\" vector elements")
if(length(bounds$min) != length(bounds$max))
stop("Bounds are not of equal length.")
### Option Defaults
defaultOptions <- list(pathLength=3, stepLength=0.11,
perturbationChance=0.1, tol=1e-3, maxiter=1000,
populationSize=10)
defaultsNeeded <- setdiff(names(defaultOptions), names(options))
spuriousOptions <- setdiff(names(options), names(defaultOptions))
options[defaultsNeeded] <- defaultOptions[defaultsNeeded]
if(length(spuriousOptions) > 0)
warning("The following specified options are unused: ",
paste(spuriousOptions,collapse=", "))
### Setup
nParams <- length(bounds$min)
nParamsTotal <- nParams * options$populationSize
steps <- seq(0, options$pathLength, options$stepLength)
nSteps <- length(steps)
steps <- rep(steps, each=nParamsTotal)
post <- matrix(parm, 1, nParams)
### Create Population
population <- matrix(parm, nrow=nParams, ncol=options$populationSize)
for (i in 2:ncol(population)) {
if(!is.null(Data[["PGF"]]))
population[,i] <- GIV(Model, Data, PGF=TRUE)
else population[,i] <- GIV(Model, Data)}
### Calculate initial LP and Dev per individual in population
temp <- apply(population, 2, function(x) Model(x, Data))
population <- sapply(temp, function(l) l$parm)
LP <- sapply(temp, function(l) l$LP)
Dev <- sapply(temp, function(l) l$Dev)
iteration <- 0
DevHistory <- LPHistory <- numeric(0)
if((max(LP) - min(LP)) < options$tol) {
population <- matrix(runif(nParamsTotal,-10,10), nrow=nParams,
ncol=options$populationSize)}
if(all(!is.finite(LP))) stop("All individuals have non-finite LPs.")
### Evolution Begins
repeat {
### Find the current leader
leaderIndex <- which.max(LP)
leaderDev <- Dev[leaderIndex]
leaderLP <- LP[leaderIndex]
### Check termination criteria
if(iteration == options$maxiter) break
LPdiff <- max(LP) - min(LP)
if(!is.finite(LPdiff)) LPdiff <- 1
if(LPdiff < options$tol) break
DevHistory <- c(DevHistory, leaderDev)
LPHistory <- c(LPHistory, leaderLP)
### Find the migration direction for each individual
directionsFromLeader <- apply(population, 2, "-",
population[,leaderIndex])
### Establish which parameters will be changed
toPerturb <- runif(nParamsTotal) < options$perturbationChance
# Second line here has a minus, so directions are away from leader
populationSteps <- array(rep(population, nSteps),
dim=c(nParams, options$populationSize, nSteps))
populationSteps <- populationSteps -
steps * rep(directionsFromLeader * toPerturb, nSteps)
### Replace out-of-bounds parameters with random valid values
outOfBounds <- which(populationSteps < bounds$min |
populationSteps > bounds$max)
randomSteps <- array(runif(nParamsTotal*nSteps),
dim=c(nParams, options$populationSize, nSteps))
randomSteps <- randomSteps * (bounds$max-bounds$min) + bounds$min
populationSteps[outOfBounds] <- randomSteps[outOfBounds]
### Values over potential locations
temp <- apply(populationSteps, 2:3, function(x) Model(x, Data))
population <- sapply(temp, function(l) l$parm)
LP <- sapply(temp, function(l) l$LP)
LP <- matrix(LP, length(LP) / nSteps, nSteps)
Dev <- sapply(temp, function(l) l$Dev)
Dev <- matrix(Dev, length(Dev) / nSteps, nSteps)
individualBestLocs <- apply(LP, 1, which.max)
### Migrate each individual to its best new location, and update LP
indexingMatrix <- cbind(seq_len(options$populationSize),
individualBestLocs)
population <- t(apply(populationSteps, 1, "[", indexingMatrix))
LP <- LP[indexingMatrix]
Dev <- Dev[indexingMatrix]
post <- rbind(post, population[,leaderIndex])
iteration <- iteration + 1
if(iteration %% round(options$maxiter / 10) == 0)
cat("Iteration: ", iteration, " of ", options$maxiter, "\n")
}
### Output
LA <- list(Dev=DevHistory,
iter=iteration,
parm.len=nParams,
parm.new=population[,leaderIndex],
parm.old=parm,
post=post[-1,],
Step.Size=options$stepLength,
tol.new=signif(LPdiff,3))
return(LA)
}
.laspg <- function(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old)
{
parm.old <- parm
parm.len <- length(parm)
Dev <- matrix(m.old[["Dev"]],1,1)
post <- matrix(parm, 1, parm.len)
M <- 10
ftol <- 1e-10
maxfeval <- 10000
quiet <- FALSE
feval <- 1
f0 <- fbest <- f <- m.old[["LP"]] * -1
nmls <- function(p, f, d, gtd, lastfv, feval, Model, maxfeval, Data)
{
# Non-monotone line search of Grippo with safe-guarded quadratic
# interpolation
gamma <- 1.e-04
fmax <- max(lastfv)
alpha <- 1
pnew <- p + alpha*d
m.new <- try(Model(pnew, Data), silent=TRUE)
feval <- feval + 1
if(class(m.new) == "try-error" | !is.finite(m.new[["LP"]]))
return(list(p=NA, f=NA, feval=NA, lsflag=1))
fnew <- m.new[["LP"]] * -1
pnew <- m.new[["parm"]]
while(fnew > fmax + gamma*alpha*gtd) {
if(alpha <= 0.1) alpha <- alpha/2
else {
atemp <- -(gtd*alpha^2) / (2*(fnew - f - alpha*gtd))
if(atemp < 0.1 | atemp > 0.9*alpha) atemp <- alpha/2
alpha <- atemp
}
pnew <- p + alpha*d
m.new <- try(Model(pnew, Data), silent=TRUE)
feval <- feval + 1
if(class(m.new) == "try-error" | !is.finite(m.new[["LP"]]))
return(list(p=NA, f=NA, feval=NA, lsflag=1))
fnew <- m.new[["LP"]] * -1
pnew <- m.new[["parm"]]
if(feval > maxfeval)
return(list(p=NA, f=NA, feval=NA, lsflag=2))
}
return(list(p=pnew, f=fnew, feval=feval, m.new=m.new, lsflag=0))
}
### Initialization
lmin <- 1e-30
lmax <- 1e30
iter <- geval <- 0
lastfv <- rep(-1e99, M)
fbest <- NA
fchg <- Inf
if(any(!is.finite(parm))) stop("Failure in initial guess!")
pbest <- parm
g <- partial(Model, parm, Data, Interval) * -1
geval <- geval + 1
lastfv[1] <- fbest <- f
pg <- parm - g
if(any(is.nan(pg))) stop("Failure in initial projection!")
pg <- pg - parm
pg2n <- sqrt(sum(pg*pg))
pginfn <- max(abs(pg))
gbest <- pg2n
if(pginfn != 0) lambda <- min(lmax, max(lmin, 1/pginfn))
### Main iterative loop
lsflag <- NULL
while ({iter <= Iterations} &
({pginfn > Stop.Tolerance} | {fchg > ftol})) {
iter <- iter + 1
d <- parm - lambda * g
d <- d - parm
gtd <- sum(g * d)
if(is.infinite(gtd)) {
lsflag <- 4
break}
nmls.ans <- nmls(parm, f, d, gtd, lastfv, feval , Model,
maxfeval, Data)
lsflag <- nmls.ans$lsflag
if(lsflag != 0) break
fchg <- abs(f - nmls.ans$f)
f <- nmls.ans$f
pnew <- nmls.ans$p
feval <- nmls.ans$feval
m.new <- nmls.ans$m.new
lastfv[(iter %% M) + 1] <- f
gnew <- try(partial(Model, pnew, Data, Interval) * -1,
silent=TRUE)
geval <- geval + 1
if(class(gnew) == "try-error" | any(is.nan(gnew))) {
lsflag <- 3
break}
s <- pnew - parm
y <- gnew - g
sts <- sum(s*s)
yty <- sum(y*y)
sty <- sum(s*y)
if(sts == 0 | yty == 0) lambda <- lmax
else lambda <- min(lmax, max(lmin, sqrt(sts/yty)))
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.new[["LP"]],1), "\n")
post <- rbind(post, pnew)
Dev <- rbind(Dev, m.new[["Dev"]])
parm <- pnew
g <- gnew
pg <- parm - g - parm
pg2n <- sqrt(sum(pg*pg))
pginfn <- max(abs(pg))
f.rep <- f * -1
if(f < fbest) {
fbest <- f
pbest <- pnew
gbest <- pginfn}
}
### Output
if(iter < Iterations) pginfn <- max(fchg, pginfn)
if(is.null(lsflag)) lsflag <- 0
if(lsflag == 0) parm <- pbest
else {
parm <- pbest
pginfn <- gbest
}
m.new <- Model(parm, Data)
Dev[nrow(Dev),] <- m.new[["Dev"]]
post[nrow(post),] <- m.new[["parm"]]
Dev <- Dev[-c(1:2),]; post <- post[-c(1:2),]
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len, parm.new=parm,
parm.old=parm.old, post=post, Step.Size=1,
tol.new=pginfn)
return(LA)
}
.lasr1 <- function(Model, parm, Data, Interval, Iterations, Stop.Tolerance,
m.old) {
m.new <- m.old
Dev <- matrix(m.old[["Dev"]],1,1)
parm.old <- parm
parm.len <- length(as.vector(parm))
post <- matrix(m.old[["parm"]], 1, parm.len)
tol.new <- 1
keepgoing <- TRUE
g.old <- g.new <- -1*partial(Model, m.old[["parm"]], Data, Interval)
B <- diag(parm.len) #Approximate Hessian
options(warn=-1)
for (iter in 2:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(m.old[["LP"]],1), "\n")
### Gradient and Direction p
g.old <- g.new
p <- as.vector(tcrossprod(g.old, -as.inverse(B)))
p[which(!is.finite(p))] <- 0
### Step-size Line Search
Step.Size <- 0.8
changed <- TRUE
while(m.new[["LP"]] <= m.old[["LP"]] & changed == TRUE) {
Step.Size <- Step.Size * 0.2
s <- Step.Size*p
prop <- m.old[["parm"]] + s
changed <- !identical(m.old[["parm"]], prop)
m.new <- Model(prop, Data)
if(any(!is.finite(c(m.new[["LP"]], m.new[["Dev"]],
m.new[["Monitor"]]))))
m.new <- m.old
}
g.new <- -1*partial(Model, m.old[["parm"]], Data, Interval)
### SR1 Update to B, the Secant Approximation of the Hessian
if(m.new[["LP"]] > m.old[["LP"]]) {
m.old <- m.new
g <- g.new - g.old
if(sum(s*g) > 0) {
part1 <- g - B %*% s
if(abs(t(s) %*% part1) >=
1e-8*sqrt(sum(s*s))*sqrt(sum(part1*part1)))
B <- B + (part1 %*% t(part1)) /
as.vector(t(part1) %*% s)
if(any(!is.finite(B))) B <- diag(parm.len)}
else B <- diag(parm.len)}
### Storage
post <- rbind(post, m.old[["parm"]])
Dev <- rbind(Dev, m.old[["Dev"]])
### Tolerance
tol.new <- sqrt(sum(g.new*g.new))
if(keepgoing == FALSE) tol.new <- 0
if(tol.new <= Stop.Tolerance) break
}
options(warn=0)
### Output
LA <- list(Dev=Dev, iter=iter, parm.len=parm.len,
parm.new=m.old[["parm"]], parm.old=parm.old, post=post,
Step.Size=Step.Size, tol.new=tol.new)
return(LA)
}
.latr <- function(Model, parm, Data, Iterations, m.old)
{
fterm <- sqrt(.Machine$double.eps)
mterm <- sqrt(.Machine$double.eps)
Norm <- function(x) return(sqrt(sum(x^2)))
parm.len <- length(parm)
post <- matrix(parm, 1, parm.len)
Dev <- matrix(m.old[["Dev"]],1,1)
r <- rinit <- 1
rmax <- 1e10
theta <- parm.old <- parm
Mo <- m.old
LP <- Mo[["LP"]]
theta <- Mo[["parm"]]
grad <- partial(Model, theta, Data)
H <- Hessian(Model, theta, Data)
accept <- TRUE
for (iter in 1:Iterations) {
### Print Status
if(iter %% round(Iterations / 10) == 0)
cat("Iteration: ", iter, " of ", Iterations,
", LP: ", round(Mo[["LP"]],1), "\n")
if(accept == TRUE) {
B <- H
g <- grad
f <- LP
out.value.save <- f
B <- - B
g <- - g
f <- - f
eout <- eigen(B, symmetric=TRUE)
gq <- as.numeric(t(eout$vectors) %*% g)}
is.newton <- FALSE
if(all(eout$values > 0)) {
ptry <- as.numeric(- eout$vectors %*% (gq / eout$values))
if(Norm(ptry) <= r) is.newton <- TRUE}
if(is.newton == FALSE) {
lambda.min <- min(eout$values)
beta <- eout$values - lambda.min
imin <- beta == 0
C1 <- sum((gq / beta)[!imin]^2)
C2 <- sum(gq[imin]^2)
C3 <- sum(gq^2)
if(C2 > 0 || C1 > r^2) {
is.easy <- TRUE
is.hard <- (C2 == 0)
beta.dn <- sqrt(C2) / r
beta.up <- sqrt(C3) / r
beta.adj <- function(x) {
if(x == 0) {
if(C2 > 0) return(- 1 / r)
else return(sqrt(1 / C1) - 1 / r)}
return(sqrt(1 / sum((gq /
{beta + x})^2)) - 1 / r)}
if(beta.adj(beta.up) <= 0) uout <- list(root=beta.up)
else if(beta.adj(beta.dn) >= 0) uout <- list(root=beta.dn)
else uout <- uniroot(beta.adj, c(beta.dn, beta.up))
wtry <- gq / {beta + uout$root}
ptry <- as.numeric(-eout$vectors %*% wtry)
}
else {
is.hard <- TRUE
is.easy <- FALSE
wtry <- gq / beta
wtry[imin] <- 0
ptry <- as.numeric(- eout$vectors %*% wtry)
utry <- sqrt(r^2 - sum(ptry^2))
if(utry > 0) {
vtry <- eout$vectors[ , imin, drop=FALSE]
vtry <- vtry[ , 1]
ptry <- ptry + utry * vtry}
}
}
preddiff <- sum(ptry * {g + as.numeric(B %*% ptry) / 2})
theta.try <- theta + ptry
Mo <- Model(theta.try, Data)
LP <- Mo[["LP"]]
theta.try <- Mo[["parm"]]
grad <- partial(Model, theta.try, Data)
H <- Hessian(Model, theta.try, Data)
ftry <- LP
ftry <- ftry * -1
rho <- {ftry - f} / preddiff
if(ftry < Inf) {
is.terminate <- {abs(ftry - f) < fterm} || {
abs(preddiff) < mterm}
}
else {
is.terminate <- FALSE
rho <- -Inf}
if(is.terminate == TRUE) {
if(ftry < f) {
accept <- TRUE
theta <- theta.try
post <- rbind(post, theta)
Dev <- rbind(Dev, Mo[["Dev"]])}
}
else {
if(rho < 1 / 4) {
accept <- FALSE
r <- r / 4
}
else {
accept <- TRUE
theta <- theta.try
post <- rbind(post, theta)
Dev <- rbind(Dev, Mo[["Dev"]])
if({rho > 3 / 4} && {is.newton == FALSE})
r <- min(2 * r, rmax)}}
if(is.terminate == TRUE) break
}
Mo <- Model(theta, Data)
theta <- Mo[["parm"]]
LA <- list(Dev=Dev, H=H, iter=iter, parm.len=parm.len,
parm.new=theta, parm.old=parm.old, post=post,
Step.Size=abs(ftry-f), tol.new=abs(preddiff))
return(LA)
}
#End
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.