Introduction

This vignette focus on the use of the calibrate() for parameter estimation. We suggest to see the vignette ‘Getting started with the calibrar package’ before reading this one, specially if you do not have previous experience doing optimization in R.

Estimating parameters for a linear model

As a first example, we will estimate the parameters for a linear model by manually performing the optimization, in opposition of the standard method using the stats::lm(). The objetive of this is to introduce the features of the calibrate() function with a simple and fast model. Let’s start by creating some parameters for the linear model.

library(calibrar)
N = 7 # number of variables in the linear model
T = 100 # number of observations
sd = 0.25 # standard deviation of the gaussian noise
# observed data
x = matrix(rnorm(N*T, sd=sd), nrow=T, ncol=N)
# slopes for the linear model (real parameters)
slope = seq_len(N) 
# intercept for the linear model (real parameters)
intercept = pi
# real parameters
real = list(intercept=intercept, slope=slope)
real
#> $intercept
#> [1] 3.141593
#> 
#> $slope
#> [1] 1 2 3 4 5 6 7

Now, let’s create a function so simulate the linear model.

# function to simulate the linear model
linear = function(x, par) {
  stopifnot(length(x)==length(par$slope))
  out = sum(x*par$slope) + par$intercept
  return(out)
}

And, finally, the simulated data for the exercise:

# simulated data 
y = apply(x, 1, linear, par=real)

Of course, the solution can be found using the lm() function:

mod = lm(y ~ x)
mod
#> 
#> Call:
#> lm(formula = y ~ x)
#> 
#> Coefficients:
#> (Intercept)           x1           x2           x3           x4           x5  
#>       3.142        1.000        2.000        3.000        4.000        5.000  
#>          x6           x7  
#>       6.000        7.000

Now, in order to proceed to find the solution by an explicit numerical optimization, we need to define the objective function to be minimized:

# objective function (residual squares sum)
obj = function(par, x, y) {
  y_sim = apply(x, 1, linear, par=par)
  out = sum((y_sim - y)^2)
  return(out)
}

So now we can proceed with the optimization:

# initial guess for optimization
start = list(intercept=0, slope=rep(0, N))
bfgs = calibrate(par=start, fn=obj, x=x, y=y)
#> Using optimization method 'Rvmmin'.
#> Elapsed time: 0.13s
#> Function value: 3.92087e-14
#> Parameter values: 3.14 1 2 3 4 5 6 7
#> 
#> Status: Rvmminu appears to have converged
# using coef to extract optimal parameters
coef(bfgs)
#> $intercept
#> [1] 3.141593
#> 
#> $slope
#> [1] 1 2 3 4 5 6 7

As expected, we were able to recover the real parameters of the model. Now, let’s specify lower and upper bounds for the algorithms that require them:

lower = relist(rep(-10, N+1), skeleton=start)
upper = relist(rep(+10, N+1), skeleton=start)

And repeat the exercise with several optimization algorithms:

set.seed(880820) # for reproducibility
cg = calibrate(par=start, fn=obj, x=x, y=y, method='CG')
#> Using optimization method 'CG'.
#> Elapsed time: 0.38s
#> Function value: 1.00008e-13
#> Parameter values: 3.14 1 2 3 4 5 6 7
#> 
#> Status: -
nm = calibrate(par=start, fn=obj, x=x, y=y, method='nmkb', lower=lower, upper=upper)
#> Using optimization method 'nmkb'.
#> Elapsed time: 0.28s
#> Function value: 1.09321e-06
#> Parameter values: 3.14 1 2 3 4 5 6 7
#> 
#> Status: -
ahres = calibrate(par=start, fn=obj, x=x, y=y, method='AHR-ES')
#> Using optimization method 'AHR-ES'.
#> Elapsed time: 1.88s
#> Function value: 1.41888e-18
#> Parameter values: 3.14 1 2 3 4 5 6 7
#> 
#> Status: Stopping criteria reached in 241 generations.
hjn = calibrate(par=start, fn=obj, x=x, y=y, method='hjn', lower=lower, upper=upper)
#> Using optimization method 'hjn'.
#> Elapsed time: 0.47s
#> Function value: 2.15391e-13
#> Parameter values: 3.14 1 2 3 4 5 6 7
#> 
#> Status: -

And compare the results:

summary(ahres, hjn, nm, bfgs, cg, par.only=TRUE)
#>       method intercept slope1 slope2 slope3 slope4 slope5 slope6 slope7
#> ahres AHR-ES      3.14      1      2      3      4      5      6      7
#> hjn      hjn      3.14      1      2      3      4      5      6      7
#> nm      nmkb      3.14      1      2      3      4      5      6      7
#> bfgs  Rvmmin      3.14      1      2      3      4      5      6      7
#> cg        CG      3.14      1      2      3      4      5      6      7

As we can see, for this simple example, all the algorithms used were able to find the solution within a reasonable time, but some were faster than others. In the next examples we will see this is not always the case, and some algorithms can perform very differently or even fail for a particular optimization problem.

Fitting a biomass production model with harvest

As a second example, we will estimate the parameters for a difference equation system, simulating the dynamics of the biomass \(B\) of a harvested population:

\[B_{t+1} = B_t + rB_t\left(1-\frac{B_t}{K}\right) - C_t,\] where \(B_t\) is the biomass in time t, \(C_t\) is the catch during the interval \([t, t+1[\), \(r\) is the intrinsic population growth rate and \(K\) is the carrying capacity of the system.

We will define some values for all the parameters so we can perform an optimization an try to recover them from the simulated data:

set.seed(880820)
T = 50
real = list(r=0.5, K=1000, B0=600)
catch = 0.25*(real$r*real$K)*runif(T, min=0.2, max=1.8)

As before, a function to simulate data from the parameters (the model) will be needed. The requirement for this function is to have as first argument the parameter vector (or list) par:

run_model = function(par, T, catch) {
  B = numeric(T+1)
  times = seq(0, T)
  B0 = par$B0
  r = par$r
  K = par$K
  B[1] = B0
  for(t in seq_len(T)) {
    b = B[t] + r*B[t]*(1-B[t]/K) - catch[t] # could be negative
    B[t+1] = max(b, 0.01*B[t]) # smooth aproximation to zero
  }
  out = list(biomass=B)
  return(out)
}

And now we can use the run_model() function and the assumed parameters to simulate the model:

observed = run_model(par=real, T=T, catch=catch)
par(mfrow=c(2,1), mar=c(3,3,1,1), oma=c(1,1,1,1))
plot(observed$biomass, type="l", lwd=2, ylab="biomass", xlab="", las=1, ylim=c(0, 1.2*max(observed$biomass)))
mtext("BIOMASS", 3, adj=0.01, line = 0, font=2)
plot(catch, type="h", lwd=2, ylab="catch", xlab="", las=1, ylim=c(0, 1.2*max(catch)))
mtext("CATCH", 3, adj=0.01, line = 0, font=2)

In order to carry out the optimization, we need the objective function to be defined, in this case, using a simple residual squares sum:

objfn = function(par, T, catch, observed) {
  simulated = run_model(par=par, T=T, catch=catch)
  value = sum((observed$biomass-simulated$biomass)^2, na.rm=TRUE)
  return(value)
}

Finally, we need to define a starting point for the search,

start = list(r=0.1, K=1.5*max(observed$biomass), B0=observed$biomass[1])

and we are ready to try to estimate the parameters using several algorithms:

set.seed(880820) # for reproducibility
opt0 = calibrate(par=start, fn = objfn, method='LBFGSB3', T=T, catch=catch, observed=observed)
#> Using optimization method 'LBFGSB3'.
#> Elapsed time: 0.05s
#> Function value: 34239.4
#> Parameter values: 0.476 1.04e+03 535
#> 
#> Status: Maximum number of iterations reached
opt1 = calibrate(par=start, fn = objfn, method='Rvmmin', T=T, catch=catch, observed=observed)
#> Using optimization method 'Rvmmin'.
#> Elapsed time: 0.02s
#> Function value: 1.34546e+07
#> Parameter values: 2.9 1.14e+03 482
#> 
#> Status: Rvmminu appears to have converged
opt2 = calibrate(par=start, fn = objfn, method='CG', T=T, catch=catch, observed=observed)
#> Using optimization method 'CG'.
#> Elapsed time: 0.08s
#> Function value: 150931
#> Parameter values: 0.402 1.18e+03 600
#> 
#> Status: -
opt3 = calibrate(par=start, fn = objfn, method='AHR-ES', T=T, catch=catch, observed=observed)
#> Using optimization method 'AHR-ES'.
#> Elapsed time: 2.39s
#> Function value: 6.77545e-17
#> Parameter values: 0.5 1e+03 600
#> 
#> Status: Stopping criteria reached in 1590 generations.
opt4 = calibrate(par=start, fn = objfn, method='CMA-ES', T=T, catch=catch, observed=observed)
#> Using optimization method 'CMA-ES'.
#> Elapsed time: 0.19s
#> Function value: 107373
#> Parameter values: 0.446 1.09e+03 689
#> 
#> Status: Covariance matrix 'C' is numerically not positive definite.
opt5 = calibrate(par=start, fn = objfn, method='hjn', T=T, catch=catch, observed=observed)
#> Using optimization method 'hjn'.
#> Elapsed time: 0.75s
#> Function value: 990.8
#> Parameter values: 0.509 988 602
#> 
#> Status: -
opt6 = calibrate(par=start, fn = objfn, method='Nelder-Mead', T=T, catch=catch, observed=observed)
#> Using optimization method 'Nelder-Mead'.
#> Elapsed time: 0.03s
#> Function value: 0.0775804
#> Parameter values: 0.5 1e+03 600
#> 
#> Status: -

The function summary() can be used to compare all the optimization results:

summary(opt0, opt1, opt2, opt3, opt4, opt5, opt6)
#>           method elapsed    value    fn  gr     r    K  B0
#> opt0     LBFGSB3  0.0482 3.42e+04   100 100 0.476 1039 535
#> opt1      Rvmmin  0.0164 1.35e+07   161   8 2.900 1145 482
#> opt2          CG  0.0819 1.51e+05   691 101 0.402 1181 600
#> opt3      AHR-ES  2.3910 6.78e-17 11130   0 0.500 1000 600
#> opt4      CMA-ES  0.1955 1.07e+05  1085  NA 0.446 1090 689
#> opt5         hjn  0.7526 9.91e+02  6000  NA 0.509  988 602
#> opt6 Nelder-Mead  0.0268 7.76e-02   221  NA 0.500 1000 600

For a better comparison, we can simulate the results for all the parameters found:

sim0 = run_model(par=coef(opt0), T=T, catch=catch)
sim1 = run_model(par=coef(opt1), T=T, catch=catch)
sim2 = run_model(par=coef(opt2), T=T, catch=catch)
sim3 = run_model(par=coef(opt3), T=T, catch=catch)
sim4 = run_model(par=coef(opt4), T=T, catch=catch)
sim5 = run_model(par=coef(opt5), T=T, catch=catch)

And plot some of the best results obtained (L-BFGS-B 3.0, CG and AHR-ES):

par(mar=c(3,4,1,1))
plot(observed$biomass, type="n", ylab="BIOMASS", xlab="", las=1, ylim=c(0, 1.2*max(observed$biomass)))
lines(sim0$biomass, col=1, lwd=2)
lines(sim2$biomass, col=2, lwd=2)
lines(sim3$biomass, col=3, lwd=2)
points(observed$biomass)
mtext(c('LBFGSB3', 'CG', 'AHR-ES'), 1, adj=0.05, col=1:3, line=-(4:2), font=2)

So far, we have used all algorithms with their default arguments. Most algorithms provide control arguments that allow to improve its performance for a particular problem. For example, looking back to the results from the L-BFGS-B 3.0 method, we can see as status ‘Maximum number of iterations reached’, meaning the algorithm did not converge but stopped after the maximum number of 100 iterations allowed by default. This can be modified here (and for several other methods) by changing the maxit control argument:

optx = calibrate(par=start, fn = objfn, method='LBFGSB3', T=T, catch=catch, observed=observed, control=list(maxit=20000))
#> Using optimization method 'LBFGSB3'.
#> Elapsed time: 12.74s
#> Function value: 0.342868
#> Parameter values: 0.5 1e+03 600
#> 
#> Status: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH

And we can see that with this setup, the algorithm converges to the right solution.

We also have the possibility to set up a calibration in multiple phases, meaning we will solve several sequential optimizations with a progressively higher number of parameters. The purpose of this is to improve the initial search point for a final optimization with all the parameters active. This heuristic may help to achieve find the solution for some problems. For example, the Rvmmin algorithm has a status ‘Rvmminu appears to have converged’ but was not able to converge to the original parameter values. So, we will try again by fixing some of the parameters (the initial biomass) and trying a two phases parameter estimation:

calibrate(par=start, fn = objfn, method='Rvmmin', T=T, catch=catch, observed=observed, phases = c(1,1,2))
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 3 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 1 finished (0.02s)
#>  Function value: 1.8303e-08
#>  Parameter values: 0.5 1e+03
#> 
#> - Phase 2: 3 of 3 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 2 finished (0.00s)
#>  Function value: 1.8303e-08
#>  Parameter values: 0.5 1e+03 600
#> 
#> Status: Rvmminu appears to have converged
#> Optimization using 'Rvmmin' algorithm.
#> Function value: 1.830304e-08 
#> Status: Rvmminu appears to have converged 
#> Parameters:
#>     r     K    B0 
#> 5e-01 1e+03 6e+02 
#> Computation:
#> function gradient 
#>       18        1

And with two phases, now we also find the solution using the ‘Rvmmin’ method.

Fitting an autoregressive Poisson model

As a third example, we will estimate the parameters for a Poisson Autoregressive Mixed model for the dynamics of a population in different sites:

\[log(\mu_{i, t+1}) = log(\mu_{i, t}) + \alpha + \beta X_{i, t} + \gamma_t\]

where \(\mu_{i, t}\) is the size of the population in site \(i\) at year \(t\), \(X_{i, t}\) is the value of an environmental variable in site \(i\) at year \(t\). The parameters to estimate were \(\alpha\), \(\beta\), and \(\gamma_t\), the random effects for each year, \(\gamma_t \sim N(0,\sigma^2)\), and the initial population at each site \(\mu_{i, 0}\). We assumed that the observations \(N_{i,t}\) follow a Poisson distribution with mean \(\mu_{i, t}\). We could also create the data for this model using the function calibrar_demo(), with the additional arguments L=5 (five sites) and T=100 (one hundred years):

path = NULL # NULL to use the current directory
ARPM = calibrar_demo(path=path, model="PoissonMixedModel", L=5, T=100) 
#> Creating observed data list for calibration...
#> Loaded observed data for variables: 'site_1', 'site_2', 'site_3', 'site_4', 'site_5'.
setup = calibration_setup(file=ARPM$setup)
observed = calibration_data(setup=setup, path=ARPM$path)
#> Creating observed data list for calibration...
#> 
#> Loaded observed data for variables: 'site_1', 'site_2', 'site_3', 'site_4', 'site_5'.
forcing = as.matrix(read.csv(file.path(ARPM$path, "master", "environment.csv"), row.names=1))
control = list(maxit=20000, eps=sqrt(.Machine$double.eps), factr=sqrt(.Machine$double.eps))

Here, we also added a control list to increase the maximum number of iterations for the algorithms and the tolerance for the convergence. Now we can specify the run_model() function so we can simulate the model from a parameter set and define the objective function using the calibration_objFn() function:

run_model = function(par, forcing) {
  output = calibrar:::.PoissonMixedModel(par=par, forcing=forcing)
  output = c(output, list(gammas=par$gamma)) # adding gamma parameters for penalties
  return(output)
}
obj = calibration_objFn(model=run_model, setup=setup, observed=observed, forcing=forcing, aggregate=TRUE)

With these we can proceed to the parameter estimation. Here, we will compare the performance of three BFGS type algorithms:

# real parameters
coef(ARPM)
#> $alpha
#> [1] 0.4
#> 
#> $beta
#> [1] -0.4
#> 
#> $gamma
#>  [1] -0.1252736456  0.0962670651  0.3390542168 -0.3522452588  0.0396026030
#>  [6]  0.0794698198  0.0058450990  0.5120546777  0.2514255423 -0.1069075371
#> [11] -0.1250454857  0.1827697374  0.2014399069  0.1438583647 -0.1209423322
#> [16]  0.1078108813 -0.0153661771  0.3699839121 -0.1709815103  0.0065274590
#> [21] -0.2050118962 -0.1964498151  0.0008203914 -0.0466854356 -0.0997776438
#> [26]  0.3099425926  0.0174993833  0.2637402261 -0.1962448238 -0.0491245175
#> [31] -0.2807867674  0.2881786295 -0.1962719982  0.2948489808 -0.1982394491
#> [36] -0.0188994689 -0.5750283368 -0.0493732202  0.0029488980 -0.3838175407
#> [41] -0.0575627487 -0.0693274891 -0.3679177169  0.1797177882 -0.2425710022
#> [46] -0.0437928463  0.1128536321 -0.1050868751  0.1488748450  0.0257963506
#> [51]  0.2976548514 -0.1325363902 -0.2321310003  0.0717548469 -0.0389692768
#> [56] -0.0590564016  0.0993280847  0.0969825576  0.0037569001  0.1269549129
#> [61]  0.1508888175  0.1667178070  0.1931522592  0.2587759936 -0.0273102042
#> [66] -0.0880277376 -0.2454567829 -0.0475306139 -0.1853716313  0.0822470712
#> [71] -0.0397729154 -0.1114899279 -0.1954314245  0.0121470497 -0.1194458959
#> [76] -0.2517897395 -0.2820094403  0.2202608159 -0.1354484053 -0.1524347015
#> [81] -0.0583497204 -0.1150377059 -0.0887883736 -0.0625140888 -0.1206008853
#> [86] -0.2187869440  0.1429412383 -0.0217624526 -0.2887595871  0.1612246527
#> [91] -0.3479670157 -0.0802640619 -0.0575164978 -0.1876814800  0.0575334278
#> [96] -0.3010802249  0.3038594027  0.0734818712  0.3399724818
#> 
#> $sd
#> [1] 0.2
#> 
#> $mu_ini
#> [1] 5.141664 4.158883 3.433987 4.430817 4.934474
lbfgsb1 = calibrate(par=ARPM$guess, fn=obj, method='L-BFGS-B', lower=ARPM$lower, upper=ARPM$upper, phases=ARPM$phase, control=control)
#> Using optimization method 'L-BFGS-B'.
#> Elapsed time: 1m 30.0s
#> Function value: -186093
#> Parameter values: 0.43 -0.415 -0.109 0.103 0.224 -0.306 0.0191 0.0445 0.0534 0.432 0.199 -0.0786 -0.128 0.121 0.275 0.0471 -0.101 0.0981 -0.0389 0.371 -0.213 0.036 -0.237 -0.254 0.0572 -0.0642 -0.178 0.294 5.54e-05 0.268 -0.212 -0.0516 -0.325 0.253 -0.195 0.291 -0.243 -0.0235 -0.532 -0.0742 -0.0616 -0.297 -0.115 -0.167 -0.323 0.0585 -0.185 -0.0309 0.0992 -0.0813 0.0103 0.161 0.266 -0.103 -0.368 0.0792 -0.133 0.0369 0.0815 -0.000515 0.0957 -0.0619 0.287 0.185 0.134 0.162 0.0492 -0.143 -0.124 -0.163 -0.277 0.0741 -0.0474 -0.0123 -0.229 -0.0587 -0.17 -0.183 -0.226 -0.0318 -0.0141 -0.21 -0.0744 -0.1 -0.185 -0.137 -0.0275 -0.164 0.181 -0.2 -0.243 0.152 -0.284 -0.352 -0.0418 -0.188 0.0203 -0.0106 0.197 -0.0425 0.37
#> 
#> Status: CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH
lbfgsb2 = calibrate(par=ARPM$guess, fn=obj, method='Rvmmin', lower=ARPM$lower, upper=ARPM$upper, phases=ARPM$phase, control=control)
#> Using optimization method 'Rvmmin'.
#> Elapsed time: 19.96s
#> Function value: -186095
#> Parameter values: 0.397 -0.415 -0.0755 0.135 0.261 -0.276 0.0524 0.0757 0.085 0.467 0.231 -0.0459 -0.0946 0.155 0.308 0.0794 -0.0678 0.131 -0.00842 0.405 -0.181 0.0701 -0.205 -0.221 0.0894 -0.0332 -0.145 0.326 0.0332 0.301 -0.179 -0.0193 -0.291 0.284 -0.161 0.323 -0.209 0.00885 -0.5 -0.0401 -0.0301 -0.27 -0.0754 -0.135 -0.295 0.0923 -0.154 0.00403 0.137 -0.0503 0.0357 0.194 0.307 -0.0752 -0.339 0.117 -0.101 0.0691 0.114 0.0343 0.129 -0.0325 0.325 0.217 0.164 0.197 0.0826 -0.113 -0.0906 -0.128 -0.25 0.111 -0.015 0.0211 -0.201 -0.0202 -0.134 -0.154 -0.195 0.0029 0.0188 -0.179 -0.0423 -0.0657 -0.151 -0.104 0.00175 -0.13 0.209 -0.167 -0.206 0.187 -0.246 -0.32 -0.00722 -0.145 3.35e-05 0.0373 0.242 0.00104 0.408
#> 
#> Status: Rvmminb appears to have converged
lbfgsb3 = calibrate(par=ARPM$guess, fn=obj, method='LBFGSB3', lower=ARPM$lower, upper=ARPM$upper, phases=ARPM$phase, control=control)
#> Using optimization method 'LBFGSB3'.
#> Elapsed time: 36.10s
#> Function value: -182467
#> Parameter values: 0.378 -0.16 -0.188 -0.183 -0.181 -0.201 -0.162 -0.145 -0.144 -0.129 -0.124 -0.145 -0.145 -0.144 -0.122 -0.145 -0.154 -0.156 -0.174 -0.164 -0.254 -0.26 -0.276 -0.286 -0.276 -0.235 -0.217 -0.19 -0.188 -0.18 -0.246 -0.254 -0.27 -0.222 -0.269 -0.264 -0.324 -0.331 -0.337 -0.337 -0.337 -0.337 -0.335 -0.329 -0.325 -0.342 -0.342 -0.342 -0.248 -0.236 -0.219 -0.213 -0.215 -0.203 -0.216 -0.194 -0.193 -0.14 -0.165 -0.152 -0.15 -0.149 -0.146 -0.146 -0.146 -0.149 -0.164 -0.101 -0.399 -0.26 -0.296 -0.304 -0.278 -0.294 -0.315 -0.291 -0.312 -0.384 -0.328 -0.34 -0.341 -0.296 -0.327 -0.283 -0.284 -0.28 -0.3 -0.224 -0.253 -0.284 -0.319 -0.293 -0.337 -0.338 -0.337 -0.291 -0.331 -0.125 -0.0377 -0.195 -0.157
#> 
#> Status: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH
summary(ARPM, lbfgsb1, lbfgsb2, lbfgsb3, show_par = 1:3)
#>           method elapsed   value   fn   gr alpha   beta  gamma1
#> ARPM        data      NA -186178   NA   NA 0.400 -0.400 -0.1253
#> lbfgsb1 L-BFGS-B    90.0 -186093 2082 2082 0.430 -0.415 -0.1085
#> lbfgsb2   Rvmmin    20.0 -186095 2701  425 0.397 -0.415 -0.0755
#> lbfgsb3  LBFGSB3    36.1 -182467 1131 1131 0.378 -0.160 -0.1883

In this case, the best solution was found using the ‘Rvmmin’ algorithm, which was also the faster (12.2s). Now, we can try to carry out the parameter estimation in two phases:

phases = ARPM$phase
phases$gamma[] = 2

And re-do every optimization:

lbfgsb1p = calibrate(par=ARPM$guess, fn=obj, method='L-BFGS-B', lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'L-BFGS-B'.
#>  Phase 1 finished (0.08s)
#>  Function value: -169005
#>  Parameter values: 0.292 -0.295
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'L-BFGS-B'.
#>  Phase 2 finished (1m 17.5s)
#>  Function value: -186095
#>  Parameter values: 0.402 -0.414 -0.0807 0.13 0.256 -0.282 0.0487 0.0714 0.0787 0.462 0.226 -0.051 -0.0995 0.15 0.303 0.0746 -0.0727 0.126 -0.0115 0.398 -0.185 0.0649 -0.21 -0.226 0.0837 -0.0368 -0.15 0.32 0.029 0.295 -0.184 -0.0241 -0.296 0.28 -0.166 0.319 -0.212 0.000427 -0.505 -0.0438 -0.0344 -0.275 -0.0804 -0.139 -0.302 0.091 -0.161 -0.0019 0.134 -0.0566 0.0311 0.19 0.303 -0.0796 -0.347 0.116 -0.109 0.0654 0.11 0.0279 0.125 -0.0395 0.321 0.212 0.159 0.192 0.0779 -0.118 -0.0954 -0.133 -0.256 0.107 -0.0206 0.0175 -0.206 -0.0245 -0.14 -0.158 -0.202 0.00014 0.0158 -0.185 -0.0462 -0.07 -0.158 -0.11 -0.00274 -0.134 0.205 -0.174 -0.21 0.182 -0.252 -0.324 -0.0247 -0.16 0.0434 0.0196 0.224 0.0019 0.4
#> 
#> Status: CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH
lbfgsb2p = calibrate(par=ARPM$guess, fn=obj, method='Rvmmin', lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 1 finished (0.04s)
#>  Function value: -169005
#>  Parameter values: 0.292 -0.295
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 2 finished (16.12s)
#>  Function value: -186095
#>  Parameter values: 0.396 -0.415 -0.0743 0.136 0.262 -0.274 0.0536 0.0769 0.0863 0.468 0.232 -0.0446 -0.0934 0.156 0.309 0.0806 -0.0666 0.133 -0.0072 0.406 -0.179 0.0713 -0.204 -0.22 0.0907 -0.0319 -0.143 0.327 0.0345 0.302 -0.177 -0.018 -0.29 0.285 -0.16 0.324 -0.208 0.0101 -0.499 -0.0388 -0.0289 -0.268 -0.0741 -0.134 -0.293 0.0936 -0.152 0.00322 0.139 -0.049 0.0369 0.196 0.308 -0.074 -0.338 0.119 -0.1 0.0704 0.115 0.0355 0.13 -0.0313 0.326 0.219 0.166 0.198 0.0839 -0.111 -0.0894 -0.127 -0.249 0.112 -0.0137 0.0224 -0.2 -0.019 -0.133 -0.152 -0.194 0.00318 0.0207 -0.178 -0.041 -0.0644 -0.15 -0.104 0.00367 -0.129 0.21 -0.165 -0.204 0.188 -0.247 -0.324 0.000263 -0.167 0.0532 0.0194 0.239 -0.00296 0.41
#> 
#> Status: Rvmminb appears to have converged
lbfgsb3p = calibrate(par=ARPM$guess, fn=obj, method='LBFGSB3', lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'LBFGSB3'.
#>  Phase 1 finished (37.43s)
#>  Function value: -169005
#>  Parameter values: 0.295 -0.298
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'LBFGSB3'.
#>  Phase 2 finished (1m 1.5s)
#>  Function value: -185064
#>  Parameter values: 0.304 -0.307 0.0233 0.0429 0.0495 0.0137 0.0515 0.0838 0.109 0.108 0.11 0.0873 0.0845 0.0942 0.1 0.0798 0.0588 0.0735 0.0701 0.0779 -0.0545 -0.0593 -0.0548 -0.0543 -0.0455 -0.0321 0.00338 0.0661 0.05 0.07 0.000428 -0.0352 -0.0667 -0.0251 -0.0384 -0.0379 -0.112 -0.114 -0.116 -0.116 -0.115 -0.115 -0.114 -0.127 -0.111 -0.109 -0.101 -0.0863 -0.0276 -0.0152 0.0156 0.0474 0.0354 0.044 0.00469 0.0399 0.0138 0.045 0.0565 0.0666 0.0677 0.0677 0.0677 0.0677 0.0677 0.0677 0.0562 0.00464 -0.0632 -0.0827 -0.0873 0.109 -0.114 -0.0975 -0.118 -0.103 -0.156 -0.104 -0.128 -0.106 -0.101 -0.0944 -0.0855 -0.0806 -0.0918 -0.0728 -0.0384 -0.0839 -0.0173 -0.0522 -0.102 -0.0172 -0.161 -0.185 -0.0937 -0.076 -0.0238 -0.0193 0.0545 0.00427 0.198
#> 
#> Status: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH
summary(ARPM, lbfgsb1, lbfgsb1p, lbfgsb2, lbfgsb2p, lbfgsb3, lbfgsb3p, show_par = 1:3)
#>            method elapsed   value   fn   gr alpha   beta  gamma1
#> ARPM         data      NA -186178   NA   NA 0.400 -0.400 -0.1253
#> lbfgsb1  L-BFGS-B    90.0 -186093 2082 2082 0.430 -0.415 -0.1085
#> lbfgsb1p L-BFGS-B    77.6 -186095 1998 1998 0.402 -0.414 -0.0807
#> lbfgsb2    Rvmmin    20.0 -186095 2701  425 0.397 -0.415 -0.0755
#> lbfgsb2p   Rvmmin    16.2 -186095 2080  329 0.396 -0.415 -0.0743
#> lbfgsb3   LBFGSB3    36.1 -182467 1131 1131 0.378 -0.160 -0.1883
#> lbfgsb3p  LBFGSB3    98.9 -185064 1389 1389 0.304 -0.307  0.0233

For all the algorithms, we can see and improvement in the solution found and even a speed up in the time needed for the optimization for the first two methods (‘L-BFGS-B’, ‘Rvmmin’). Finally, we can try to carry out the optimization in two phases, but using different algorithms for each phase. In principle, some algorithms may be faster or find a better initial starting point for the final search.

mix1 = calibrate(par=ARPM$guess, fn=obj, method=c('hjn', 'Rvmmin'), lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'hjn'.
#>  Phase 1 finished (1.87s)
#>  Function value: -169005
#>  Parameter values: 0.294 -0.298
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 2 finished (29.21s)
#>  Function value: -186095
#>  Parameter values: 0.396 -0.415 -0.0739 0.136 0.262 -0.274 0.054 0.0773 0.0866 0.469 0.232 -0.0443 -0.093 0.156 0.309 0.081 -0.0663 0.133 -0.00675 0.406 -0.179 0.0717 -0.204 -0.22 0.0911 -0.0316 -0.143 0.327 0.0348 0.302 -0.177 -0.0177 -0.289 0.286 -0.159 0.325 -0.208 0.0106 -0.499 -0.0385 -0.0285 -0.268 -0.0737 -0.134 -0.293 0.0938 -0.153 0.00605 0.138 -0.0487 0.0374 0.196 0.308 -0.0736 -0.337 0.119 -0.0999 0.0708 0.116 0.036 0.13 -0.0312 0.326 0.219 0.166 0.198 0.0843 -0.111 -0.089 -0.127 -0.249 0.113 -0.0129 0.0226 -0.199 -0.0183 -0.132 -0.152 -0.192 -0.000484 0.0229 -0.177 -0.0406 -0.064 -0.15 -0.104 0.00688 -0.13 0.21 -0.165 -0.204 0.188 -0.246 -0.324 0.00128 -0.167 0.0528 0.0208 0.24 -0.00361 0.411
#> 
#> Status: Rvmminb appears to have converged
mix2 = calibrate(par=ARPM$guess, fn=obj, method=c('Nelder-Mead', 'Rvmmin'), lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'Nelder-Mead'.
#>  Phase 1 finished (0.01s)
#>  Function value: -124445
#>  Parameter values: 0.308 -0.358
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 2 finished (33.78s)
#>  Function value: -186095
#>  Parameter values: 0.396 -0.415 -0.074 0.136 0.262 -0.274 0.0539 0.0772 0.0866 0.468 0.232 -0.0444 -0.0931 0.156 0.309 0.0809 -0.0663 0.133 -0.00686 0.406 -0.179 0.0716 -0.204 -0.22 0.0909 -0.0316 -0.143 0.327 0.0348 0.302 -0.177 -0.0178 -0.289 0.286 -0.159 0.324 -0.208 0.0105 -0.499 -0.0386 -0.0287 -0.268 -0.0738 -0.134 -0.293 0.0939 -0.152 0.0051 0.138 -0.0488 0.0372 0.196 0.308 -0.0737 -0.337 0.119 -0.0999 0.0706 0.116 0.0359 0.13 -0.031 0.326 0.219 0.166 0.198 0.0842 -0.111 -0.0891 -0.127 -0.249 0.113 -0.0132 0.0226 -0.199 -0.0186 -0.132 -0.152 -0.192 -0.00097 0.0229 -0.177 -0.0407 -0.0642 -0.15 -0.104 0.00515 -0.129 0.21 -0.165 -0.204 0.188 -0.246 -0.324 0.000538 -0.167 0.0529 0.0204 0.238 -8.15e-05 0.409
#> 
#> Status: Rvmminb appears to have converged
mix3 = calibrate(par=ARPM$guess, fn=obj, method=c('CG', 'Rvmmin'), lower=ARPM$lower, upper=ARPM$upper, phases=phases, control=control)
#> Parameter estimation in two phases.
#> 
#> - Phase 1: 2 of 107 parameters active.
#>  Using optimization method 'CG'.
#>  Phase 1 finished (0.02s)
#>  Function value: -1824.73
#>  Parameter values: 2.33e+03 2.36e+03
#> 
#> - Phase 2: 101 of 107 parameters active.
#>  Using optimization method 'Rvmmin'.
#>  Phase 2 finished (9.82s)
#>  Function value: -186095
#>  Parameter values: 0.396 -0.415 -0.0746 0.136 0.262 -0.275 0.0533 0.0765 0.086 0.468 0.232 -0.045 -0.0937 0.156 0.309 0.0803 -0.0669 0.132 -0.0076 0.406 -0.18 0.071 -0.204 -0.22 0.0903 -0.0322 -0.144 0.327 0.0341 0.302 -0.178 -0.0184 -0.29 0.285 -0.16 0.324 -0.208 0.00983 -0.5 -0.0391 -0.0293 -0.269 -0.0744 -0.134 -0.294 0.0933 -0.153 0.00378 0.138 -0.0493 0.0366 0.195 0.308 -0.0743 -0.338 0.118 -0.1 0.07 0.115 0.0352 0.13 -0.0316 0.325 0.218 0.165 0.198 0.0836 -0.112 -0.0897 -0.127 -0.249 0.112 -0.014 0.022 -0.2 -0.0196 -0.133 -0.153 -0.194 0.0032 0.0203 -0.178 -0.0414 -0.0648 -0.15 -0.102 -0.000385 -0.128 0.21 -0.166 -0.205 0.188 -0.246 -0.321 -0.0101 -0.164 0.0538 0.0198 0.239 -0.00341 0.41
#> 
#> Status: Rvmminb appears to have converged
summary(ARPM, lbfgsb2, lbfgsb2p, mix1, mix2, mix3, show_par = 1:3)
#>          method elapsed   value   fn  gr alpha   beta  gamma1
#> ARPM       data      NA -186178   NA  NA 0.400 -0.400 -0.1253
#> lbfgsb2  Rvmmin   19.96 -186095 2701 425 0.397 -0.415 -0.0755
#> lbfgsb2p Rvmmin   16.16 -186095 2080 329 0.396 -0.415 -0.0743
#> mix1     Rvmmin   31.09 -186095 4011 590 0.396 -0.415 -0.0739
#> mix2     Rvmmin   33.79 -186095 4011 693 0.396 -0.415 -0.0740
#> mix3     Rvmmin    9.85 -186095  729 212 0.396 -0.415 -0.0746

Here, we can see that every combination find essentially the same solution, but the combination using the ‘CG’ (conjugated gradient) first required less function and gradient evaluations, being faster.

Please, refer to vignette(package="calibrar") for additional vignettes or to the calibrar website for more details.