1

I am trying to use nlsLM to fit experimental data. But for this example, I am using analytical data from another program so that I know the correct values. I am trying to use nls2 to give me starting points that I can use when using nlsLM. I was able to do this successfully with a less complex function, but it is not working with the more complicated function. I get values for nls2, but when I use nlsLM I get the error: "evaluation of fn function returns non-sensible value"., which I cannot figure out because I am either using the coef values from nls2 or the actual values for the parameters I am solving for.

I generated sample data below for time and x so hopefully it is reproducible for someone else. I have results from another program, so the calculations below for Y_ex were used to verify the function was set up correctly to match those results. They are used in the regression analysis for this example. (I am new to r, so sorry about my inefficient code!).

library(nls2)
library(minpack.lm)

## Generate sample data for time and x
time_ex <- seq(from = 0, to = 50, by = 0.02)
strain_ex1 <- time_ex[1:326]*0.0011
strain_ex2 <- time_ex[327:2501]*0+0.0011*6.5
strain_ex <- c(strain_ex1,strain_ex2)
plot(time_ex,strain_ex)
x <- strain_ex 
t <- time_ex

## Generate results with known parameters (eventually use to check results from nls)
Y_ex = c()
K <- 770 #coef(fit1)[1]       # ** Paramter 1 for NLS **
TAU <-  4.5 # coef(fit1)[2]   # ** Paramter 2 for NLS **
dt <- 0.02

for(i in seq(from=1, to=2501, by=1)){
  if (i == 1) {
    yO_ex = 0
    dx_ex = 0
  } else {
    yO_ex = yT_ex
    dx_ex = x[i] - x[i-1] 
  }
  yT_ex = exp(-0.02/TAU)*yO_ex + (K/2) * (1 + exp(-0.02/TAU))*dx_ex
  Y_ex = c(Y_ex,yT_ex)
}

plot(x,Y_ex)
plot(time_ex,Y_ex)

df <- data.frame(t = t, x =  x , y = Y_ex)

I am fitting the parameters k and tau using nls. Since I know the actual values for this example, I tried using close values as the start values. I tried using these as the start values for nlsLM as well and got the same error.

### Define Function for Nonlinear Regression Analysis
Func1 <- function(t, x, k, tau){ 
  for(i in seq(from=1, to=2501, by=1)){
    if (i == 1) {    
      yO = 0 
      dx = 0
      dt = 0
    } else {
      yO = yT       
      dx = x[i] - x[i-1]
      dt = t[i] - t[i-1]
    }
    yT <- exp(-dt/tau)*yO + (k/2) * (1 + exp(-dt/tau))*dx
  } 
return(yT)
}

### Nonlinear Regression Analysis 1
# Start parameters
grd <- data.frame(k=c(0,770),
                  tau=c(0,4.4)
)
## perform nls
set.seed(123)
fit1 <- nls2(
  y ~ Func1(t, x, k, tau),
  data = df,
  start = grd,
  algorithm ="random" 
)
coef(fit1)

## nlsLM with coeff from nls2
fit2 <- nlsLM(
  y ~ Func1(t, x, k, tau),
  data =  df, 
  start = coef(fit1) 
)

This is where I get my error: "Error in nls.lm(par = start, fn = FCT, jac = jac, control = control, lower = lower, : evaluation of fn function returns non-sensible value!"

This error confused me since I am using the parameters from nls2 as the output. If I use the actual known values as the start values (skipping nls2 completely), I get the same error.

Is there a reason why nls2 gives an answer but nlsLM produces an error? I have tried redefining the function after I run nls2 in case it wasn't understanding it, and that did not help either.

Please let me know if you need anything clarified. Any help is greatly appreciated!

Update:

After adding return in the function, I am getting the following error after running nlsLM *Error in qr(.swts * attr(rhs, "gradient")) : dims [product 2] do not match the length of object [2501] In addition: Warning message: In .swts * attr(rhs, "gradient") : longer object length is not a multiple of shorter object length*

I am still getting results for nls.

Ardy
  • 11
  • 2
  • Thanks, I updated the question with my libraries and set.seed. – Ardy May 25 '20 at 16:15
  • Sorry, I forgot to re-define the example t as the t for df. I updated it. – Ardy May 25 '20 at 20:22
  • When does it return NULL? When I run the code above, the only output I get is for the coef(fit1) and the error from nlsLM. – Ardy May 25 '20 at 21:01
  • Look at the code in Func1. It ends in a loop and then does not return anything. Try Func1(t, x, 700, 3.5) as an example. – G. Grothendieck May 25 '20 at 21:24
  • I added "return(yT)" in the function. I now get the error: "Error in qr(.swts * attr(rhs, "gradient")) : dims [product 2] do not match the length of object [2501] In addition: Warning message: In .swts * attr(rhs, "gradient") : longer object length is not a multiple of shorter object length" after I run nlsLM. But I get results for nls2. – Ardy May 26 '20 at 00:42
  • Func1 returns a scalar but should return a vector the same length as the LHS of the formula. – G. Grothendieck May 26 '20 at 04:07
  • Okay, I see what you mean, it is a problem with the basics! I added ``y <- c(y,yT)`` within the for loop and return(y) instead of yT and I think it is working now! Thank you very much for your help and patience! – Ardy May 26 '20 at 18:02

0 Answers0