Group Abstract Group Abstract

Message Boards Message Boards

1
|
502 Views
|
6 Replies
|
2 Total Likes
View groups...
Share
Share this post:

FindFit dependent on irrelevant changes

Posted 24 days ago

After finding a fitting curve with FindFit with three parameters, I liked to find a fit after setting one of the parameters to the value in the solution. But then the other values are not found anymore. Also when I multiply this parameter with a small value which should be irrelevant for finding a solution, FindFit doesn’t find the solution anymore. Is there some work around for this?

6 Replies

Jim Baldwin's remark about the signs of the parameters suggests trying the following:

NonlinearModelFit[data,{temp2[t],a>0&&k2>0},{a,k2},t]["BestFitParameters"]
(*  {a->866.073,k2->0.0300234}  *)

Other ways to find starting values

[I'd worked out the following before trying the above.]

In this case, because of the model and the data, one can solve for the parameters that give the model a maximum where the data has a maximum. For noisier data, one might use FindPeaks[data, σ], with an appropriate smoothing parameter σ; or one could estimate the maximum by eye, if it's there are too many cases to deal with. The parameter values for the approximate initial model are obtained by solving, not by fitting, and equations are constructed for the particular model at hand. The solutions should make good starting values for FindFit or NonlinearModelFit.

kInit=k2/.First@NSolve[temp2''[t]<-Sqrt@$MachineEpsilon&&temp2'[t]==0/.t->First[dmax]/.a->1,k2]
aInit=a/.First@NSolve[temp2[t]==Last[dmax]/.k2->kInit/.t->First[dmax],a]
FindFit[data,temp2[t],{{a,aInit},{k2,kInit}},t]
(*
0.0278868
954.695
{a->866.073,k2->0.0300234}
*)

Also, some thought makes it clear (if I was thinking clearly) that k2 should be greater, but not too much greater, than the other exponential coefficient, 0.01376208490662561.

FindFit[data,temp2[t],{a,{k2,2*0.01376208490662561}},t]
(*  {a->866.073,k2->0.0300234}  *)

Or:

FindFit[data,{temp2[t],k2>0.01376208490662561},{a,k2},t]
(*  {a->866.073,k2->0.0300234}  *)

Spelunking

Sometimes I want to be sure I know what's going on inside. I don't know a direct way to obtain the function that NonlinearModelFit[] minimizes. Here is an indirect way:

(* returns an Experimental`NumericFunction[] *)
nf = Head@Trace[
 NonlinearModelFit[data,temp2[t],{a,k2},t,Method->"NMinimize"],
 HoldPattern[NMinimize[obj_,___]]:>Return[obj,Trace],
 TraceInternal->True];

obj=nf["FunctionExpression"] (* gets the (long) expression for the function *)
FindMinimum[{obj,a>0&&k2>0},{a,k2}]
(*  {146.814, {a->866.073,k2->0.0300234}}  *)

I assume the objective function is the same no matter what Method is used to minimize it.

POSTED BY: Michael Rogers

What about:

In[47]:= NonlinearModelFit[data, {temp2[t], a <= 0 || a > 0}, {a, k2},  t]["BestFitParameters"]
Out[47]= {a -> 866.073, k2 -> 0.0300234}

Edit:

In[30]:= NonlinearModelFit[data, {temp2[t], 1 > 0}, {a, k2}, t]["BestFitParameters"]
Out[30]= {a -> 866.073, k2 -> 0.0300234}
In[31]:= NonlinearModelFit[data, {temp2[t], True}, {a, k2}, t]["BestFitParameters"]
Out[31]= {a -> 866.073, k2 -> 0.0300234}
In[32]:= NonlinearModelFit[data, {temp2[t]}, {a, k2}, t]["BestFitParameters"]
Out[32]= {a -> 339.024, k2 -> 9129.04}

What about:

obj=nf["FunctionExpression"];
FindMinimum[{obj,a>0&&k2>0},{a,k2}]
FindMinimum[{obj,True},{a,k2}]
FindMinimum[obj,{a,k2}]
(*
Out[24]= {146.814,{a->866.073,k2->0.0300234}}
Out[25]= {146.814,{a->866.073,k2->0.0300234}}
Out[26]= {47749.3,{a->339.024,k2->5.03971}}
*)
POSTED BY: Michael Rogers

Thanks. I should have tried starting values. So it was only a lucky accident that I found a good fit in all cases, using different data sets, were also k1 was a free parameter?

Posted 24 days ago

Not a lucky accident. FindFit and NonlinearModelFit usually do a pretty good job with the default starting values. But because of various combinations of data and models, both sometimes need a little help. Having a starting value with the right sign is sometimes all that is needed.

POSTED BY: Jim Baldwin
Posted 24 days ago

There are 2 issues:

(1) FindFit should be avoided as it doesn't have any capabilities to provide diagnostic measures (such as standard errors, confidence bands, residuals, etc.). NonlinearModelFit should be used instead.

(2) You need better starting values than the defaults that FindFit uses (although this applies also to NonlinearModelFit). Consider the following:

temp2[t_] := a*(Exp[-0.01376208490662561*t] - Exp[-k2*t])
FindFit[data, temp2[t], {{a, 860}, {k2, 0.03}}, t]
(* {a -> 866.073, k2 -> 0.0300234} *)

You get exactly what you had before. Good starting values are your best friends in an iterative procedure.

POSTED BY: Jim Baldwin
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard