Search code examples
rcurve-fittingnonlinear-optimizationnon-linear-regressionmodel-fitting

Fitting parameters of a nonlinear equation to match experimental data


I tried modifing code that I found here using the nls function for this simpler equation, but have been unsuccessful so far.

Equation

new_f <- function(a, t, t1, dt, m){
  1-exp(-a*((x-t1)/dt)^(m+1))
}

fit_d <- nls(y~new_f(a, t, -30, dt, m), start=list(a=1, dt=46, m=1))

Error in nlsModel(formula, mf, start, wts) : 
  singular gradient matrix at initial parameter estimates

Can someone help with this with a step by step guide for dummies? Any suggestion would be greatly appreciated!.

My data: t=θ and y=Y(θ)

t <- c(-30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89)

y <- c(0.0000, -0.0013, -0.0027, -0.0041, -0.0055, -0.0069, -0.0085, -0.0101, -0.0119, -0.0137, -0.0155, -0.0173, -0.0192, -0.0212, -0.0234, -0.0258, -0.0285, -0.0291, -0.0250, -0.0224, -0.0268, -0.0298, -0.0297, -0.0324, -0.0347, -0.0353, -0.0377, -0.0392, -0.0392, -0.0383, -0.0309, -0.0166, 0.0006, 0.0233, 0.0521, 0.0843, 0.1200, 0.1597, 0.1997, 0.2381, 0.2762, 0.3137, 0.3501, 0.3864, 0.4229, 0.4590, 0.4951, 0.5312, 0.5655, 0.5967, 0.6245, 0.6494, 0.6726, 0.6939, 0.7132, 0.7316, 0.7487, 0.7641, 0.7784, 0.7917, 0.8037, 0.8146, 0.8248, 0.8343, 0.8432, 0.8516, 0.8596, 0.8671, 0.8740, 0.8805, 0.8868, 0.8931, 0.8992, 0.9050, 0.9105, 0.9155, 0.9202, 0.9247, 0.9290, 0.9330, 0.9369, 0.9405, 0.9439, 0.9470, 0.9501, 0.9529, 0.9557, 0.9583, 0.9608, 0.9633, 0.9658, 0.9682, 0.9704, 0.9726, 0.9747, 0.9768, 0.9788, 0.9808, 0.9827, 0.9844, 0.9858, 0.9869, 0.9880, 0.9890, 0.9899, 0.9909, 0.9918, 0.9927, 0.9938, 0.9947, 0.9956, 0.9964, 0.9970, 0.9975, 0.9980, 0.9985, 0.9989, 0.9993, 0.9997, 1.0000)

Solution

  • There are several problems:

    • the x in new_f should be t
    • the problem is overparameterized so that the parameters are not identifiable. There are an infinite number of parameter combinations that satisfy the problem. In particular, a / dt^(m+1) can be replaced with a single parameter. To fix that remove dt, say, from the starting values and fix it at 46.

    With those changes the code produces a result.

    new_f <- function(a, t, t1, dt, m){
      1-exp(-a*((t-t1)/dt)^(m+1))
    }
    
    dt <- 46
    fit_d <- nls(y~new_f(a, t, -30, dt, m), start = list(a = 1, m = 1))
    fit_d
    ## Nonlinear regression model
    ##   model: y ~ new_f(a, t, -30, dt, m)
    ##    data: parent.frame()
    ##     a     m 
    ## 0.560 3.315 
    ## residual sum-of-squares: 0.3099
    ##
    ## Number of iterations to convergence: 13 
    ## Achieved convergence tolerance: 4.165e-06
    
    plot(y ~ t)
    lines(fitted(fit_d) ~ t, col = "red")
    

    screenshot