[R] Finding starting values for the parameters using nls() or nls2()

dave fournier davef at otter-rsch.com
Mon Oct 24 19:49:30 CEST 2016


I've spent quite a bit of time trying to convince people on various 
lists that the solution to these kinds of
problems lies in the stable parameterization of the model.  I write the 
solutions in AD Model Builder because it
is easy.  But R people are generally stuck in R (or mired) so the 
message somehow always gets lost.

  I thought I would bite the bullet and figure out how to do this in R. 
It turns out that one can fit this model
  with only 6 function evaluations using nls2.   I apologize in advance 
for my execrable R code. But it does do
the job.

The data were fit using 3 calls to nls2. For the first call only the 
parameter th was estimated. This converged
in 4 function evaluations. For the second call all three of the 
parameters were estimated
(but the other 2 parameters are different from b0, b1) .This converged 
to the solution in four function evaluations.

The final call to nls2 uses the converged values to calculate b0,b1 and 
theta and starts from there.
As you can see the model is already converged. This final call to nls2 
is used to get the standard error
estimates for the parameters.

 >  nls.m1
Nonlinear regression model
   model: Retention ~ expFct1(Area, y1, yn, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
     th
0.9862
  residual sum-of-squares: 730

Number of iterations to convergence: 2
Achieved convergence tolerance: 1.616e-06

 >  nls.m2
Nonlinear regression model
   model: Retention ~ expFct2(Area, y1, yn, c, d, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
      c      d     th
0.9716 1.1010 0.9118
  residual sum-of-squares: 686.8

Number of iterations to convergence: 4
Achieved convergence tolerance: 2.398e-06

 >  nls.m
Nonlinear regression model
   model: Retention ~ expFct(Area, b0, b1, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
         b0         b1         th
  5.2104452 -0.0004672  0.9118040
  residual sum-of-squares: 686.8

Number of iterations to convergence: 0
Achieved convergence tolerance: 1.384e-06

Parameters:
      Estimate Std. Error t value Pr(>|t|)
b0  5.2104452  0.4999594  10.422 2.29e-07 ***
b1 -0.0004672  0.0013527  -0.345   0.7358
th  0.9118040  0.3583575   2.544   0.0257 *

So what is the stable parameterization for this model.  To simplify let 
x be the independent variable and y be the
  dependent variable and write t instead of th  So the model is

             y = exp(b0*exp(b1*x^t) (1)

Now it would be nice to reorder the x's so that they are monotone 
increasing or decreasing, but in this case the
first x is almost the largest and the last x is almost the smallest 
(slight reach) so they will do. Call them x1 and xn.
The new parameters of the model are the predicted y's for x1 and xn.  
Call them y1 and yn.  Note that y1 and yn
are parameters, not observations.


The data were fit using 3 calls to nls2. For the first call only the 
parameter th was estimated. this converged
in 4 function evaluestions. for the second call all three of the 
parameters were estimated
(but the other 2 parameters are different from b0, b1) .This converged 
to the solution in four function evaluations.

The final call to nls2 uses the converged values to calculate b0,b1 and 
theta and starts from there.
as you can see the model is already converged. this final call to nls2 
is used to get the standard error
estimates for the parameters.

 >  nls.m1
Nonlinear regression model
   model: Retention ~ expFct1(Area, y1, yn, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
     th
0.9862
  residual sum-of-squares: 730

Number of iterations to convergence: 2
Achieved convergence tolerance: 1.616e-06

 >  nls.m2
Nonlinear regression model
   model: Retention ~ expFct2(Area, y1, yn, c, d, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
      c      d     th
0.9716 1.1010 0.9118
  residual sum-of-squares: 686.8

Number of iterations to convergence: 4
Achieved convergence tolerance: 2.398e-06

 >  nls.m
Nonlinear regression model
   model: Retention ~ expFct(Area, b0, b1, th)
    data: structure(list(Area = c(521.5, 689.78, 1284.71, 2018.8, 
2560.46, 524.91, 989.05, 1646.32, 2239.65, 2972.96, 478.54, 875.52, 
1432.5, 2144.74, 2629.2), Retention = c(95.3, 87.18, 44.94, 26.36, 
18.12, 84.68, 37.24, 33.04, 23.46, 9.72, 97.92, 71.44, 44.52, 24.44, 
15.26)), .Names = c("Area", "Retention"), row.names = c(NA, -15L), class 
= "data.frame")
         b0         b1         th
  5.2104452 -0.0004672  0.9118040
  residual sum-of-squares: 686.8

Number of iterations to convergence: 0
Achieved convergence tolerance: 1.384e-06

Parameters:
      Estimate Std. Error t value Pr(>|t|)
b0  5.2104452  0.4999594  10.422 2.29e-07 ***
b1 -0.0004672  0.0013527  -0.345   0.7358
th  0.9118040  0.3583575   2.544   0.0257 *

So what is the stable parameterization for this model.  To simplify letx 
be the independent variable and y be the
  dependent variable and write t insted of th  So the model is

             y = exp(b0*exp(b1*x^t) (1)

Now it would be nice to reorder the x's so that they are monotone 
increasing or decreasing, but in this case the
first x is almost the largest and the last x is almost the smallest 
(slight reach) so they will do. Call them x1 and xn.
The new parameters of the model are the predicted y's for x1 and xn.  
Call them y1 and yn.  Note that y1 and yn
are parameters, not observations.

              y1 = exp(b0*exp(b1*x1^t)
(2)
              yn = exp(b0*exp(b1*xn^t)

One can solve for b1 and b0 in terms of y1 and yn.

             b1=log(log(y1)/log(yn))/(x1^t-xn^t);
(3)
             b0=log(y1)*exp(-b1*x1^t);


To use this  we do the fitting of the model in two stages. In the first 
stage we use the obvious
  estimates of y[1] for y1 and y[n] for yn and fix these values and 
estimate t using the obvious
starting value of 1 for t.

In the second stage we set

                y1=c*y[1]

                yn=d*y[n]

and estimate   c, d, and t using the obvious starting values of 1 for c 
and d.
That's it. this converges as stated in 6 function evaluations.  This 
technique works for
may curves such as 3,4,5 parameter logistic double exponential 
vonBertalanffy
(where Schnute and I first discovered it in the early 1980's before 
anyone was born).

One caveat  is that usually not all values of y1 and yn are 
permissible.  For example in this case if b>0
then y1 and yn are both >1. To make this routine bulletproof one needs 
to impose these kinds of
constraints.  But this was not needed here.

Here is my  R code for this model.

library("nls2")
cl=data.frame(Area=c(521.5, 689.78, 1284.71, 2018.8, 2560.46, 524.91, 
989.05,
1646.32, 2239.65, 2972.96, 478.54, 875.52, 1432.5, 2144.74, 2629.2), 
Retention=c (95.3, 87.18, 44.94, 26.36, 18.12, 84.68, 37.24, 33.04, 23.46,
9.72, 97.92, 71.44, 44.52, 24.44, 15.26) )

  y1 <<- cl$Retention[1];
  yn <<- cl$Retention[length(cl$Retention)]

  expFct1 <- function(x, y1, yn,th)
  {
   x1=x[1]
   xn=x[length(x)]
   b1=log(log(y1)/log(yn))/(x1^th-xn^th)
   b0=log(y1)*exp(-b1*x1^th)
   exp(b0*exp(b1*x^th));
  }

  expFct2 <- function(x, y_1,y_n,c,d,th)
  {
   x1=x[1]
   xn=x[length(x)]
   y1=c*y_1
   yn=d*y_n
   b1=log(log(y1)/log(yn))/(x1^th-xn^th)
   b0=log(y1)*exp(-b1*x1^th)
   exp(b0*exp(b1*x^th));
  }

  expFct <- function(x, b0, b1,th)
  {
    exp(b0*exp(b1*x^th))
  }


  nls.m1<- nls2(Retention ~ expFct1(Area, y1, yn, th), data = cl,
     start = list(th = 1))

  th_start=coef(nls.m1)


  nls.m2<- nls2(Retention ~ expFct2(Area, y1, yn, c, d,  th), data = cl,
     start = list(c=1, d=1, th = th_start))

  x=cl$Area
  x1=x[1]
  xn=x[length(x)]
  th_start=coef(nls.m2)[3]
  cy1=coef(nls.m2)[1]*y1

dyn=coef(nls.m2)[2]*yn
  b1_start=log(log(cy1)/log(dyn))/(x1^th_start-xn^th_start)
  b0_start=log(cy1)*exp(-b1_start*x1^th_start)

  th_start
  b1_start
  b0_start
  nls.m<- nls2(Retention ~ expFct(Area, b0, b1, th), data = cl,
     start = list(b0 = b0_start, b1 = b1_start, th = th_start))

  nls.m1
  nls.m2
  nls.m



More information about the R-help mailing list