Title: | Non-Linear Regression with Brute Force |
---|---|
Description: | Adds brute force and multiple starting values to nls. |
Authors: | G. Grothendieck, R Core Team (nls) |
Maintainer: | G. Grothendieck <[email protected]> |
License: | GPL-2 |
Version: | 0.3-4 |
Built: | 2024-11-11 04:29:12 UTC |
Source: | https://github.com/ggrothendieck/nls2 |
Determine the nonlinear least-squares estimates of the parameters of a nonlinear model.
nls2(formula, data = parent.frame(), start, control = nls.control(), algorithm = c("default", "plinear", "port", "brute-force", "grid-search", "random-search", "lhs", "CPoptim", "plinear-brute-force", "plinear-random", "plinear-lhs"), trace = FALSE, weights, subset, ..., all = FALSE)
nls2(formula, data = parent.frame(), start, control = nls.control(), algorithm = c("default", "plinear", "port", "brute-force", "grid-search", "random-search", "lhs", "CPoptim", "plinear-brute-force", "plinear-random", "plinear-lhs"), trace = FALSE, weights, subset, ..., all = FALSE)
formula |
same as |
data |
same as |
start |
same as |
control |
same as |
algorithm |
same as |
trace |
If |
weights |
For weighted regression. |
subset |
Subset argument as in |
... |
other arguments passed to |
all |
if |
Similar to nls
except that start
and algorithm
have expanded values and there is a new all
argument.
nls2
generates a grid or random set of starting values
and then optionally performs an nls
optimization starting
at each one.
If algorithm
is "brute-force"
(or its
synonym "grid-search"
) then (1) if start
is a two row data frame
then a grid is created from the rectangle defined by the two rows such that
the grid has at most maxiter
points with the
residuals sum of squares being calculated at each generated
point. (2) If start
is a data frame with more than two rows
then the residual sum of squares is evaluated at each row.
If algorithm
is "random-search"
then (1) if start
is a two row data frame then maxiter
points are uniformly sampled
from the rectangle it defines or (2) if start
is a data frame with
more than two rows then the "maxiter"
rows are sampled without
replacement.
"plinear-brute"
and "plinear-random"
are like
"brute-force"
and "random-search"
except that the formula
is a plinear
-style formula and only starting values for the non-linear
parameters are given.
If algorithm is neither of the above two values then if start has more than
one row a two phase procedure is undertaken. (1) if start
is a two row data frame then
a random set of points is generated and then the optimization is carried out
starting from each of those points.
(2) If start
is a data frame with more than two rows then the
optimization is carried out starting from each row.
In any of the above cases
if all=FALSE
, the default, then an "nls"
object at the
value with the least residual sum of squares returned; otherwise, if
all=TRUE
then a list of "nls"
objects is returned with one
component per starting value.
If the starting value is an "nls"
object then
the coef
of that object will be used as the
starting value.
If the algorithm
argument is "CPoptim"
then the convex
partition algorithm from the CPoptim
package
is used. In that case start
must be a 2 row data frame with the first
row being the lower bounds and second row the upper bounds and the column
names must be the names of the corresponding parameters. The maximum
number of function evaluations (FEmax
) defaults to 5000 times the
number of parameters and the sample size (sampleSize
defaults to
1000. Other values can be passed via the control
list but normally
the defaults should be adequate.
Since nls
is used to produce starting values rather than the final
estimates confint
cannot be used on objects produced by nls
.
nls
.
y <- c(44,36,31,39,38,26,37,33,34,48,25,22,44,5,9,13,17,15,21,10,16,22, 13,20,9,15,14,21,23,23,32,29,20,26,31,4,20,25,24,32,23,33,34,23,28,30,10,29, 40,10,8,12,13,14,56,47,44,37,27,17,32,31,26,23,31,34,37,32,26,37,28,38,35,27, 34,35,32,27,22,23,13,28,13,22,45,33,46,37,21,28,38,21,18,21,18,24,18,23,22, 38,40,52,31,38,15,21) x <- c(26.22,20.45,128.68,117.24,19.61,295.21,31.83,30.36,13.57,60.47, 205.30,40.21,7.99,1.18,5.40,13.37,4.51,36.61,7.56,10.30,7.29,9.54,6.93,12.60, 2.43,18.89,15.03,14.49,28.46,36.03,38.52,45.16,58.27,67.13,92.33,1.17, 29.52,84.38,87.57,109.08,72.28,66.15,142.27,76.41,105.76,73.47,1.71,305.75, 325.78,3.71,6.48,19.26,3.69,6.27,1689.67,95.23,13.47,8.60,96.00,436.97, 472.78,441.01,467.24,1169.11,1309.10,1905.16,135.92,438.25,526.68,88.88,31.43, 21.22,640.88,14.09,28.91,103.38,178.99,120.76,161.15,137.38,158.31,179.36, 214.36,187.05,140.92,258.42,85.86,47.70,44.09,18.04,127.84,1694.32,34.27, 75.19,54.39,79.88,63.84,82.24,88.23,202.66,148.93,641.76,20.45,145.31, 27.52,30.70) ## Example 1 ## brute force followed by nls optimization fo <- y ~ Const + B * (x ^ A) # pass our own set of starting values # returning result of brute force search as nls object st1 <- expand.grid(Const = seq(-100, 100, len = 4), B = seq(-100, 100, len = 4), A = seq(-1, 1, len = 4)) mod1 <- nls2(fo, start = st1, algorithm = "brute-force") mod1 # use nls object mod1 just calculated as starting value for # nls optimization. Same as: nls(fo, start = coef(mod1)) nls2(fo, start = mod1) ## Example 2 # pass a 2-row data frame and let nls2 calculate grid st2 <- data.frame(Const = c(-100, 100), B = c(-100, 100), A = c(-1, 1)) mod2 <- nls2(fo, start = st2, algorithm = "brute-force") mod2 # use nls object mod1 just calculated as starting value for # nls optimization. Same as: nls(fo, start = coef(mod2)) nls2(fo, start = mod2) ## Example 3 # Create same starting values as in Example 2 # running an nls optimization from each one and picking best. # This one does an nls optimization for every random point # generated whereas Example 2 only does a single nls optimization nls2(fo, start = st2, control = nls.control(warnOnly = TRUE)) ## Example 4 # Investigate singular jacobian at the start value # Note that this cannot be done with nls since the singular jacobian at # the initial conditions would stop it with an error. DF1 <- data.frame(y=1:9, one=rep(1,9)) xx <- nls2(y~(a+2*b)*one, DF1, start = c(a=1, b=1), algorithm = "brute-force") svd(xx$m$Rmat())[-2] ## Example 5 # plinear-lhs example # Thanks to John Nash for suggesting this truncation of the # Ratkowsky2 dataset. Full dataset: data(Ratkowsky2, package = "NISTnls") # Use plinear-lhs to get starting values and then run nls via nls2 for # final answer. pastured <- data.frame( time=c(9, 14, 21, 28, 42, 57, 63, 70, 79), yield= c(8.93, 10.8, 18.59, 22.33, 39.35, 56.11, 61.73, 64.62, 67.08)) fo <- yield ~ cbind(1, - exp(-exp(t3+t4*log(time)))) gstart <- data.frame(t3 = c(-10, 10), t4 = c(1, 8)) set.seed(123) junk <- capture.output(fm0 <- nls2(fo, data = pastured, start = gstart, alg = "plinear-lhs", control = nls.control(maxiter = 1000)), type = "message") nls2(fo, pastured, start = fm0, alg = "plinear") ## Example 6 # CPoptim example nls2(demand ~ a + b * Time, data = BOD, start = data.frame(a = c(-10, 10), b = c(-10, 10)), alg = "CPoptim")
y <- c(44,36,31,39,38,26,37,33,34,48,25,22,44,5,9,13,17,15,21,10,16,22, 13,20,9,15,14,21,23,23,32,29,20,26,31,4,20,25,24,32,23,33,34,23,28,30,10,29, 40,10,8,12,13,14,56,47,44,37,27,17,32,31,26,23,31,34,37,32,26,37,28,38,35,27, 34,35,32,27,22,23,13,28,13,22,45,33,46,37,21,28,38,21,18,21,18,24,18,23,22, 38,40,52,31,38,15,21) x <- c(26.22,20.45,128.68,117.24,19.61,295.21,31.83,30.36,13.57,60.47, 205.30,40.21,7.99,1.18,5.40,13.37,4.51,36.61,7.56,10.30,7.29,9.54,6.93,12.60, 2.43,18.89,15.03,14.49,28.46,36.03,38.52,45.16,58.27,67.13,92.33,1.17, 29.52,84.38,87.57,109.08,72.28,66.15,142.27,76.41,105.76,73.47,1.71,305.75, 325.78,3.71,6.48,19.26,3.69,6.27,1689.67,95.23,13.47,8.60,96.00,436.97, 472.78,441.01,467.24,1169.11,1309.10,1905.16,135.92,438.25,526.68,88.88,31.43, 21.22,640.88,14.09,28.91,103.38,178.99,120.76,161.15,137.38,158.31,179.36, 214.36,187.05,140.92,258.42,85.86,47.70,44.09,18.04,127.84,1694.32,34.27, 75.19,54.39,79.88,63.84,82.24,88.23,202.66,148.93,641.76,20.45,145.31, 27.52,30.70) ## Example 1 ## brute force followed by nls optimization fo <- y ~ Const + B * (x ^ A) # pass our own set of starting values # returning result of brute force search as nls object st1 <- expand.grid(Const = seq(-100, 100, len = 4), B = seq(-100, 100, len = 4), A = seq(-1, 1, len = 4)) mod1 <- nls2(fo, start = st1, algorithm = "brute-force") mod1 # use nls object mod1 just calculated as starting value for # nls optimization. Same as: nls(fo, start = coef(mod1)) nls2(fo, start = mod1) ## Example 2 # pass a 2-row data frame and let nls2 calculate grid st2 <- data.frame(Const = c(-100, 100), B = c(-100, 100), A = c(-1, 1)) mod2 <- nls2(fo, start = st2, algorithm = "brute-force") mod2 # use nls object mod1 just calculated as starting value for # nls optimization. Same as: nls(fo, start = coef(mod2)) nls2(fo, start = mod2) ## Example 3 # Create same starting values as in Example 2 # running an nls optimization from each one and picking best. # This one does an nls optimization for every random point # generated whereas Example 2 only does a single nls optimization nls2(fo, start = st2, control = nls.control(warnOnly = TRUE)) ## Example 4 # Investigate singular jacobian at the start value # Note that this cannot be done with nls since the singular jacobian at # the initial conditions would stop it with an error. DF1 <- data.frame(y=1:9, one=rep(1,9)) xx <- nls2(y~(a+2*b)*one, DF1, start = c(a=1, b=1), algorithm = "brute-force") svd(xx$m$Rmat())[-2] ## Example 5 # plinear-lhs example # Thanks to John Nash for suggesting this truncation of the # Ratkowsky2 dataset. Full dataset: data(Ratkowsky2, package = "NISTnls") # Use plinear-lhs to get starting values and then run nls via nls2 for # final answer. pastured <- data.frame( time=c(9, 14, 21, 28, 42, 57, 63, 70, 79), yield= c(8.93, 10.8, 18.59, 22.33, 39.35, 56.11, 61.73, 64.62, 67.08)) fo <- yield ~ cbind(1, - exp(-exp(t3+t4*log(time)))) gstart <- data.frame(t3 = c(-10, 10), t4 = c(1, 8)) set.seed(123) junk <- capture.output(fm0 <- nls2(fo, data = pastured, start = gstart, alg = "plinear-lhs", control = nls.control(maxiter = 1000)), type = "message") nls2(fo, pastured, start = fm0, alg = "plinear") ## Example 6 # CPoptim example nls2(demand ~ a + b * Time, data = BOD, start = data.frame(a = c(-10, 10), b = c(-10, 10)), alg = "CPoptim")