Solved – Singular gradient erros, NLS in R

errornlsoptimizationrregression

I'm trying to fit nls(Mound~ a*kg.bag.collar^b + c, start = list(a = 83, b = -.5, c=100), data=test) using the dataset here. I've fit it without trouble without the c term with no problem. But adding the c term gives "Error in nls(mToMound.stand ~ a * as.numeric(kg.bag.collar)^b + c, start = list(a = 83, :
singular gradient."
I know the error can mean that poor starting values are given, but I've tried a wide range, and more to the point, a and be here are very close to the estimates that come from the fit without "c" included.
The subject-matter dictates that I need the c term to allow the possibility of a concave up decreasing function that doesn't go through the origin.

What are my options here? Thanks!

enter image description here

Best Answer

You can get successful convergence by using the Golub-Pereyra algorithm for partially linear least-squares models (which is a more sophisticated way of doing what @whuber suggested):

fit <- nls(mound~ cbind(1, kg.bag.collar^b), start = list(b = -.5),
             data=test, algorithm = "plinear")
plot(mound ~ kg.bag.collar, data = test)
curve(predict(fit, newdata = data.frame(kg.bag.collar = x)), add = TRUE)

resulting plot

That looks somewhat reasonable but summary output shows that none of the parameters is significant (note that .lin1 is the parameter c and .lin2 is a).

summary(fit)
#Formula: mound ~ cbind(1, kg.bag.collar^b)
#
#Parameters:
#      Estimate Std. Error t value Pr(>|t|)  
#b       0.7857     1.1344   0.693   0.4915  
#.lin1  18.7878    10.5973   1.773   0.0819 .
#.lin2  -0.2737     1.7254  -0.159   0.8745  
#---
#Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#
#Residual standard error: 5.402 on 54 degrees of freedom
#
#Number of iterations to convergence: 11 
#Achieved convergence tolerance: 9.472e-06

If you use starting values close to this solution, the default Gauss-Newton algorithm also converges.

You have strong collinearity, which means there are more parameters in your model than your data supports:

vcov(fit)
#               b     .lin1      .lin2
#b       1.286925 -11.82171   1.956174
#.lin1 -11.821714 112.30234 -18.076169
#.lin2   1.956174 -18.07617   2.977021

You should try and collect more and better data if you need to fit this model (but that might not be possible).