Search code examples
rstatisticsrscriptnon-linear-regression

Non Linear Regression Error (Single Gradient Matrix)


I've seen a few of these previously for very simple functions, however the function i'm trying to fit is basically a mixture of 3 functions

A gaussian (which dominates at x=0) An exponential (which takes over post gaussian) and a constant which rounds out the values

From the other examples of this error that I have read it seems that the issue is caused by poor initial guesses, but I have no idea how to correct this or if this is even the actual issue given the size of my function.

Here is my code and one sample of the data I'm looking at.:

Value<-c(163301.080,269704.110,334570.550,409536.530,433021.260,418962.060,349554.460,253987.570,124461.710,140750.480,52612.790,54286.427,26150.025,14631.210,15780.244,8053.618,4402.581,2251.137,2743.511,1707.508,1246.894)
Height<-c(400,300,200,0,-200,-400,-600,-800,-1000,-1000,-1200,-1220,-1300,-1400,-1400,-1500,-1600,-1700,-1700,-1800,-1900)

Framed<-data.frame(Value,Height)
i<-nls(Value~a*exp(-Height^2/(2*b^2))+ c*exp(-d*abs(Height)) + e,
                 data=Framed,start = list(a=410000,b=5,c=10000,d=5,e=1200))
plot(Value~Height)
summary(i)

Thanks for your help now i have the same problem again, i've used your technique below (R noob) was using the manipulate plot in mathematica previously and i think i've got a relatively good fit for the data, here is a graph of the data i'm also attempting to fit (Sorry can't upload it, not enough reputation)

https://i.sstatic.net/lfti3.jpg

However i am getting the same issue, is this to do with my fit or the massive amounts of variability at low distances?


Solution

  • You're right about this usually being about bat starting values, and that's (part of) your case. Looking at your data and your guesses, it's clear that something is wrong. But before going into that, note that Framed was not created in the correct order. It should be X Y, or:

    Framed <- data.frame(Height, Value)
    

    With that in mind, try the following:

    Vals2 <- 410000*exp(-Height^2/(2*5^2)) - 10000*exp(-5*abs(Height)) + 1200
    plot(Framed) 
    lines(Height, Vals2) 
    

    You should get

    enter image description here

    This shows how bad your guesses are. Playing around with your function, it can be easily seen that b is far off. Change it to 500, and then:

    enter image description here

    That's much better, but still won't fit. And if you change the other parameters (c, d, and e), you'll notice they don't seem to affect the data too much, or at all. That's probably because a is much bigger and you have Height^2 in the first term. If you simplify your function, and run:

    i<-nls(Value~a*exp(-Height^2/(2*b^2)), start = list(a=410000,b=500))
    

    You'll find a fit. This is probably because non-linear functions get harder to fit as the number of parameter increases, specially if there are covariance between them. Less parameters are fitted much easier. You'll have to decide however if you can work with only a and b.

    But if you plot that, it still doesn't look good. It's clear that your Value does not have its maximum at Height = 0, like it should from your description and from the simulated curve. There seems to be an error with your data, because if you try Height <- Height+200 along with the above changes, you'll get

    enter image description here

    > summary(i)
    
    Formula: Value ~ a * exp(-Height^2/(2 * b^2))
    
    Parameters:
       Estimate Std. Error t value Pr(>|t|)    
    a 449820.71   10236.43   43.94   <2e-16 ***
    b    496.60      12.54   39.59   <2e-16 ***
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 17790 on 19 degrees of freedom
    
    Number of iterations to convergence: 4 
    Achieved convergence tolerance: 2.164e-06
    

    Now that's up to you to check if your data is indeed shifted and if you can simplify the function.