Skip to content

nls function

3 messages · nerak13, David Winsemius, Peter Dalgaard

#
Hi,

I've got the following data:

x<-c(1,3,5,7)
y<-c(37.98,11.68,3.65,3.93)
penetrationks28<-dataframe(x=x,y=y)

now I need to fit a non linear function so I did:

fit <- nls(y ~ I(a+b*exp(1)^(-c * x)), data = penetrationks28, start =
list(a=0,b = 1,c=1), trace = T)

The error message I get is:
Error in nls(y ~ I(a + b * exp(1)^(-c * x)), data = penetrationks28, start =
list(a = 0,  : 
  singular gradient

I've tried to change the startervalues but it always gives the same error

I've also tried the following adjustment hoping that the c value would be
negative:

fit <- nls(y ~ I(a+b*exp(1)^(c * x)), data = penetrationks28, start = list(a
= 1,b = 1,c=1), trace = T)

but then the error message is: 
Error in nls(y ~ I(a + b * exp(1)^(c * x)), data = penetrationks28, start =
list(a = 1,  : 
  number of iterations exceeded maximum of 50

What can I do ?

Thanks in advance

--
View this message in context: http://r.789695.n4.nabble.com/nls-function-tp4546791p4546791.html
Sent from the R help mailing list archive at Nabble.com.
#
On Apr 10, 2012, at 4:03 PM, nerak13 wrote:

            
?nls

"Warning:
Do not use nls on artificial "zero-residual" data."

Get more data. (with 3 coefficients and 4 data points you have created  
a zero-residual situation even if it's not "artificial".)
#
On Apr 10, 2012, at 22:03 , nerak13 wrote:

            
That's the second time you have been posting code with that weird sort of formula. 

Please: 
y ~ a + b * exp(-c * x)

I() is only needed for linear models where arithmetic operators have special meaning, and exp(1)^x for exp(x) just hurts our eyes.

Apart from that, you just need better starting values, it seems:
+ list(a=3,b = 15,c=1), trace = T)
932.0747 :   3 15  1 
310.2288 :   2.9756409 25.5127564  0.3610715 
137.811 :   5.6501434 42.5276986  0.6921207 
2.187083 :   2.6843590 71.7142051  0.7180404 
1.9709 :   2.6657517 71.6213474  0.7058412 
1.970713 :   2.6726912 71.6839169  0.7069178 
1.970712 :   2.6719547 71.6797621  0.7068432 
1.970712 :   2.6720049 71.6800584  0.7068484
Formula: y ~ a + b * exp(-c * x)

Parameters:
  Estimate Std. Error t value Pr(>|t|)  
a   2.6720     1.4758   1.811   0.3212  
b  71.6801     7.7101   9.297   0.0682 .
c   0.7068     0.1207   5.856   0.1077  
---
Signif. codes:  0 ?***? 0.001 ?**? 0.01 ?*? 0.05 ?.? 0.1 ? ? 1 

Residual standard error: 1.404 on 1 degrees of freedom

Number of iterations to convergence: 7 
Achieved convergence tolerance: 3.067e-06
[1] 38.024329 11.271188  4.763691  3.180792
attr(,"label")
[1] "Fitted values"
 
..........
As David points out, three parameters to 4 data values is a bit absurd. Although not technically infeasible, I would not trust those 1 df t-tests at all.

Concerning the starting values, finding them is a bit of an art, but you clearly need something better than grabbing values out of thin air. Various techniques for finding starting values can be extracted by looking at the code for the self-start routines that come with nls() (the ones with names starting with SS). 

In the present case, you might try guessing a as the asymptote for large x so a value somewhat lower than the last value of y should do, say a=3. Subtract a from both sides and you get y-a = b*exp(-c*x) which you can make linear as log(y-a) = log(b) - c*x. So fit this using
Call:
lm(formula = log(y - 3) ~ x, data = penetrationks28)

Coefficients:
(Intercept)            x  
     3.9979      -0.6737  

which suggests that a=3, b=exp(4), c=.67 might work, and it does, even though the starting values aren't exactly spot on:
+ list(a=3,b = exp(4),c=.67), trace = T)
53.23186 :   3.00000 54.59815  0.67000 
2.188135 :   2.7131685 71.6770898  0.7187123 
1.970939 :   2.6654559 71.6169034  0.7057594 
...