MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: NonlinearRegress and numerical functions...

  • To: mathgroup at smc.vnet.net
  • Subject: [mg20212] Re: [mg20197] Re: [mg20161] NonlinearRegress and numerical functions...
  • From: "Carl K.Woll" <carlw at fermi.phys.washington.edu>
  • Date: Wed, 6 Oct 1999 21:06:30 -0400
  • Organization: Department of Physics
  • References: <199910040107.VAA17261@smc.vnet.net.> <199910050804.EAA22807@smc.vnet.net.>
  • Sender: owner-wri-mathgroup at wolfram.com

Daniel,

There is a way to get NonlinearFit to work even when using NDSolve in your
model. One way, which is essentially identical to what you did, is to use
Method->FindMinimum and give NonlinearFit two starting values. However,
suppose you wanted to include gradient information. One way to do this is to
use the Gradient option of NDSolve, but I prefer a different method. Teach
Mathematica how to take derivatives of your model! In your example, we had

Clear[f]
f[a_?NumberQ, b_?NumberQ, t_?NumberQ] :=
        (y[t1] /. First[NDSolve[{y'[t1]==-a*y[t1], y[0]==b}, y[t1],
        {t1,0,100}, AccuracyGoal->150, MaxSteps->2000]]) /. t1->t

Now, we need to figure out what the derivative of f[a,b,t] with respect to a
is.

fa[a_?NumberQ, b_?NumberQ, t_?NumberQ] :=
  ya[t] /. First[
      NDSolve[{ya'[t1] == -a ya[t1] - y[t1], y'[t1] == -a y[t1], ya[0] == 0,
          y[0] == b}, {y, ya}, {t1, 0, 100}, AccuracyGoal -> 150,
        MaxSteps -> 2000]]

Here I just differentiated the ODE with respect to a to obtain a new system of
ODEs. Next, we need to teach Mathematica what this derivative is

Derivative[1, 0, 0][f][a_, b_, t_] := fa[a, b, t]

Now we can use NonlinearFit

In[25]:=
NonlinearFit[data, f[a, 6, t], t, {a, 1}]

Out[25]=
f[3., 6, t]

An extension of this idea should work for Lars' problem.

Carl Woll
Physics Dept
U of Washington

Daniel Lichtblau wrote:

> Lars Ragnarsson wrote:
> >
> > Hi
> >
> > I've got a big problem making Mathematica realize that my function is
> > numerical. The following problem illustrates it in a rather simplified
> > way:
> >
> > g[t1_] := y[t] /. DSolve[{y'[t] == -y[t] 3, y[0] == 6}, y[t], t][[1]] /.
> >
> > t -> t1
> >
> > data = {0, 10, 20, 100};
> >
> > fit = Transpose[{data, g[data]}];
> >
> > f[t1_, a_,b_] := (y[t] /.NDSolve[{y'[t] == -y[t] a, y[0] == b}, y[t],
> > {t, 0, 100}][[1]]) /.t -> t1
> >
> > NonlinearRegress[data, f[t, a, 6], {t}, {a, {2.9, 3.2}, 2, 4}]
> >
> > It should be  rather straightforward to solve this, but NonlinearRegress
> >
> > seem to evaluate the function 'f' first and the results:
> >
> > NDSolve::"ndnum": "Encountered non-numerical value for a derivative at \
> >
> > \!\(t\) == \!\(2.680466916142905`*^-274\)."
> >
> > etc....
> >
> > I've tried to use Unevaluated and Hold but nothing works!
> >
> > Any help would be greatly appreciated!
> >
> > Regards
> >
> > Larske Ragnarsson
> >
> > _________________________________________________
> > Larske Ragnarsson
> > Phone: +46 (0)31 7721867
> > Fax:   +46 (0)31 7723622
> > Chalmers University of Technology
> > Solid State Electronics Laboratory
> > Department of Microelectronics ED
> > S-412 96 Guteborg, SWEDEN
> > _________________________________________________
>
> I'll change the notation just a bit. To start we define our function,
> create a bunch of data points, and show, with NonlinearFit, that we can
> recover the function.
>
> g[a_, b_, t_] := (y[t1] /.
>         First[DSolve[{y'[t1]==-a*y[t1], y[0]==b}, y[t1], t1]]) /. t1->t
> pnts = {0, 10, 20, 100};
> data = {#, g[3,6,t] /. t->#}&  /@ pnts
> <<Statistics`
>
> In[5]:= NonlinearFit[data, g[a,6,t], t, {a,1}]
>           6
> Out[5]= -----
>          3. t
>         E
>
> Now suppose instead that we have a function defined by (numerical)
> solutions to a differential equation. I assume the example given was for
> purposes of comparison to a known solution though of course in general
> we do not have this recourse. Let me point out some issues, at least one
> of which is substantial.
>
> First, your numeric differential equation solution is not very accurate;
> to obtain a result similar to the exact solution for x as large as 100
> you need to fiddle with the NDSolve options (maybe this numeric error
> was intentional?).
>
> Clear[f]
> f[a_?NumberQ, b_?NumberQ, t_?NumberQ] :=
>         (y[t1] /. First[NDSolve[{y'[t1]==-a*y[t1], y[0]==b}, y[t1],
>         {t1,0,100}, AccuracyGoal->150, MaxSteps->2000]]) /. t1->t
>
> Let us check the relative errors at our data points.
>
> In[9]:= Map[(f[3,6,#]-g[3,6,#])/g[3,6,#]&, pnts]
> Out[9]= {0., -0.0000162022, -0.0000385361, -0.000219838}
>
> Not bad.
>
> Now for a more serious issue. You want to do a nonlinear function fit to
> a model that is, in effect, defined by a program. While this is a
> reasonable thing to want, I am not certain it can be done directly in
> Mathematica (I confess to no great expertise with NonlinearFit/Regress,
> so I may be mistaken). Anyway, you can instead formulate this as a
> minimization problem and use FindMinimum to solve for the parameter
> value. We do this explicitly below. Again, some option fiddling is
> helpful in order to get a good result.
>
> In[15]:= objfunc = Apply[Plus, Map[(f[a, 6, #[[1]]] - #[[2]])^2 &,
> data]];
>
> In[16]:= FindMinimum[objfunc, {a,2,2.1}, AccuracyGoal->50,
>         MaxIterations->200, WorkingPrecision->100]
>                     -53
> Out[16]= {3.79385 10   , {a -> 2.99999837977173152356769137355}}
>
> Given the disparities between f and g at the data points, this is likely
> about as accurate a solution as can be obtained; to do better one would
> have to get more accurate results from the model function f and perhaps
> also use/request higher accuracy/precision in FindMinimum.
>
> Daniel Lichtblau
> Wolfram Research



  • Prev by Date: Re: adjusting frame size in plot
  • Next by Date: Replacing Part of a Matrix
  • Previous by thread: Re: NonlinearRegress and numerical functions...
  • Next by thread: Re: NonlinearRegress and numerical functions...