Re: NonlinearFit for specific data
- To: mathgroup at smc.vnet.net
- Subject: [mg117820] Re: NonlinearFit for specific data
- From: Darren Glosemeyer <darreng at wolfram.com>
- Date: Fri, 1 Apr 2011 02:31:13 -0500 (EST)
On 3/31/2011 4:01 AM, Alexandre Souza wrote:
> Dear Group,
> I have the following data :
> data2 = { {0, 773.59},{30, 2351.12},{60, 4205.8}, {90, 4222.69},{120,
> 4222.69},{150, 704.328},
> {180, 1388.28},{210, 1388.28},{240, 1821.23},{270, 1821.23},{300,
> 754.109},{330, 773.59},{360, 773.59}};
> I want the following curve fit :
> NonlinearFit[data2, Exp[ a + b x + c x^2], x, {a, b, c}]
> Unfortunatelly I get some "FindFit::sszero
> FindMinimum::sszero" message, and the given result is ackward.
> I also tried FindFit and NonlinearRegress without success.
> Any comment would be very welcome.
> Alex
>
In nonlinear optimization, choosing good starting values can make a big
difference. These nonlinear optimization functions will start all
parameters at 1 if no starting values are given, and 1 will not be very
good for any of the parameters in this particular example. Some
knowledge of what the parameters are expected to be can be very useful
in choosing them. Without that knowledge, I typically resort to a
mathematical bag of tricks I've built up over the years. Here are two
approaches that will work in this case.
One is to look at limiting behaviors for the model function and use data
points at or near those limits to solve for starting values for some
parameters. In this model for x==0, the model would be Exp[a] and as x
gets large the model should go to Exp[c*x^2], so we could use the first
and last data points to solve for starting values for a and c.
In[1]:= data2 = {{0, 773.59}, {30, 2351.12}, {60, 4205.8}, {90,
4222.69}, {120, 4222.69}, {150, 704.328}, {180, 1388.28},
{210,
1388.28}, {240, 1821.23}, {270, 1821.23}, {300, 754.109},
{330,
773.59}, {360, 773.59}};
In[2]:= astart = Log[data2[[1, 2]]]
Out[2]= 6.65104
In[3]:= cstart = Log[data2[[-1, 2]]]/data2[[-1, 1]]^2
Out[3]= 0.0000513198
Now we could use another data point and those starting values to get a
starting value for b from another data point.
In[4]:= bstart =
With[{x = data2[[2, 1]]},
b /. Solve[(Exp[a + b x + c x^2] /. {a -> astart, c ->
cstart}) ==
data2[[2, 2]], b, Reals][[1]]]
Solve::ratnz: Solve was unable to solve the system with inexact
coefficients. The
answer was obtained by solving a corresponding exact system and
numericizing
the result.
Out[4]= 0.0355139
We can now use these as starting values for the optimization:
In[5]:= FindFit[data2, Exp[a + b x + c x^2],
Transpose[{{a, b, c}, {astart, bstart, cstart}}], x,
MaxIterations -> 1000]
Out[5]= {a -> 6.97238, b -> 0.0332337, c -> -0.000192787}
Another possibility in this case is to take advantage of the fact that
Log of the model is a linear model, so we could take the Log of the y
values, fit the linear model, and use the estimates from that
linearization as starting values.
In[6]:= logdata = data2;
In[7]:= logdata[[All, 2]] = Log[logdata[[All, 2]]];
In[8]:= start2 = CoefficientList[Fit[logdata, {1, x, x^2}, x], x]
Out[8]= {7.45656, 0.00453122, -0.0000207059}
In[9]:= FindFit[data2, Exp[a + b x + c x^2], Transpose[{{a, b, c}, start2}],
x]
Out[9]= {a -> 6.97238, b -> 0.0332337, c -> -0.000192787}
Darren Glosemeyer
Wolfram Research