Working in R, I am trying to use nls()
to fit some data to the following model:
y ~ c - a * exp(-b * x)
My data:
x <- c(8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 16, 16, 16, 18, 18, 20, 20, 20, 22, 22, 22, 24, 24, 24, 26, 26, 26, 28, 28, 30, 30, 30, 32, 32, 34, 36, 36, 38, 38, 40, 42)
y <- c(0.49, 0.49, 0.48, 0.47, 0.48, 0.47, 0.46, 0.46, 0.45, 0.43, 0.45, 0.43, 0.43, 0.44, 0.43, 0.43, 0.46, 0.45, 0.42, 0.42, 0.43, 0.41, 0.41, 0.40, 0.42, 0.40, 0.40, 0.41, 0.40, 0.41, 0.41, 0.40, 0.40, 0.40, 0.38, 0.41, 0.40, 0.40, 0.41, 0.38, 0.40, 0.40, 0.39, 0.39)
data <- data.frame(x, y)
Check to see if data fits the form of the model:
The book I'm working with says the coefficient estimates should be: c=0.3896, a=-0.2194, b=0.992.
My attempt using the given values, based on this thread 2, returns a singular gradient error:
m <- nls(y ~ I(c-a*exp(-b*x)), data=data, start=list(a=-.2194, b=1, c=0.3), trace=T)
I get acceptable values when I try to fit y ~ a * exp(-b * x)
and y ~ exp(-b * x)
, but when I add the "c" term, I get the singular gradient error. I've also tried using nlsLM, which had the same issue, so I think it has to do with how I'm adding in that intercept term. Any advice is appreciated, thank you.
Use the plinear algorithm in which case starting values are not needed for the parameters that enter linearly. In that case the right hand side should be a matrix such that each column multiplies one of the parameters that enters linearly.
fm <- nls(y ~ cbind(c = 1, a = -exp(-b*x)), data,
start = list(b = 1), alg = "plinear")
fm
giving:
Nonlinear regression model
model: y ~ cbind(c = 1, a = -exp(-b * x))
data: data
b .lin.c .lin.a
0.09916 0.38963 -0.21940
residual sum-of-squares: 0.004997
Number of iterations to convergence: 6
Achieved convergence tolerance: 3.075e-07
We can examine the fit visually:
plot(y ~ x, data)
lines(fitted(fm) ~ x, data, col = "red")