Search code examples
rnls

Working with nls function produces a singular gradient


I want to fit a nonlinear least-squares model to my data using the nls function, but I get an error:

My data are:

y=c(0.3,1.5,4.1,10.1,21.9,39,4,58.2,77,89.6,95,98.3,100)

x=c(30,35,40,45,50,55,60,65,70,75,80,85,90)

I have used the following R command:

fit<-nls(y~a/(1+exp(-b*(x-c))), start=list(a=1,b=0.5,c=25))

It seems that something went wrong in start, but not sure.


Solution

  • Here are several approaches:

    1) nls Better starting values are needed. First take the reciprocal of both sides and use the "plinear" algorithm which does not require starting values for linear parameters, in this case a. Then use that as starting values for your fit.

    fit0 <- nls(1/y ~ 1 + exp(-b*(x-c)), start = list(b = .5, c = 25), alg = "plinear")
    fit <- nls(y~1/(1+exp(-b*(x-c))),start=coef(fit0)[1:2], alg = "plinear")
    
    plot(y ~ x)
    lines(fitted(fit) ~ x)
    fit
    

    giving:

    Nonlinear regression model
      model: y ~ 1/(1 + exp(-b * (x - c)))
       data: parent.frame()
           b        c     .lin 
      0.1355  64.9761 106.7095 
     residual sum-of-squares: 1516
    
    Number of iterations to convergence: 13 
    Achieved convergence tolerance: 6.85e-06
    

    screenshot

    2) nls/SSlogis R provides the SSlogis self starting model. No starting values are needed. Note that it is parameterized such that b = 1/B.

    nls(y ~ SSlogis(x, a, c, B))
    

    giving:

    Nonlinear regression model
      model: y ~ SSlogis(x, a, c, B)
       data: parent.frame()
         a      c      B 
    106.71  64.98   7.38 
     residual sum-of-squares: 1516
    
    Number of iterations to convergence: 2 
    Achieved convergence tolerance: 4.087e-06
    

    3) drc The drc package can also fit this and provides its own starting values. The parameter names are different with b, d and e below corresponding to -b, a and c in the question.

    library(drc)
    
    fm <- drm(y ~ x, fct = L.3())
    plot(fm)
    fm
    

    giving:

    A 'drc' model.
    
    Call:
    drm(formula = y ~ x, fct = L.3())
    
    Coefficients:
    b:(Intercept)  d:(Intercept)  e:(Intercept)  
          -0.1355       106.7093        64.9761