# Find fit does not find the best fit [duplicate]

Here is my data

{{1.25, 1.80901*10^-7}, {1.29, 2.09306*10^-7}, {1.31,
2.26933*10^-7}, {1.33, 2.30064*10^-7}, {1.43, 3.15002*10^-7}, {1.47,
3.63006*10^-7}, {1.51, 4.31649*10^-7}, {1.535, 4.73*10^-7}, {1.57,
5.42432*10^-7}, {1.61, 6.19763*10^-7}, {0.14, 8.4686*10^-7}, {0.23,
6.45612*10^-7}, {0.27, 5.65504*10^-7}, {0.305, 5.12656*10^-7}}


and I use the function of

f[zr_, z0_, x_] := l*zr/Pi (1 + ((x + z0)/zr )^2)


And usding Find fit I tried to estimate the paramter z0 and zr

z = FindFit[data, f[zr, z0, x], {zr, z0}, x]


But the problem is it does not give me the best fitting!

If I use just half of the data after 1.00,

{{1.25, 1.80901*10^-7}, {1.29, 2.09306*10^-7}, {1.31,
2.26933*10^-7}, {1.33, 2.30064*10^-7}, {1.43, 3.15002*10^-7}, {1.47,
3.63006*10^-7}, {1.51, 4.31649*10^-7}, {1.535, 4.73*10^-7}, {1.57,
5.42432*10^-7}, {1.61, 6.19763*10^-7}}


I will get the fitting such like this. It seems to me that the residual is much smaller than previous graph, and making more sense, but why mathmetica is showing me the bad fit for all the data? and how can I solve the problem?

• "how can I solve the problem" - provide better initial estimates. In this case, use the parameter values you got from fitting half the data as starting estimates when fitting the entire set. Commented Jun 6, 2015 at 15:34
• FindFit finds a local minimum of the sum of the squares of the residuals. That is not necessarily the global minimum, as you see. You may get a better answer by choosing starting values for zr and z0. There is no general method that can guarantee the best result in all cases. Commented Jun 6, 2015 at 15:37
• Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory Tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise. Commented Jun 6, 2015 at 15:38
• @JohnDoty Thank you so much... that is the answer I was looking for Commented Jun 8, 2015 at 14:37
• @Guesswhoitis. Thank you!!! Commented Jun 8, 2015 at 14:37

Your function contains an undefined parameter l. If we use it as a variable instead:

f[zr_, z0_, l_, x_] := l zr/Pi (1 + ((x + z0)/zr)^2)


we get

z = FindFit[data, f[zr, z0, l, x], {zr, z0, l}, x]
(* {zr -> 0.175467, z0 -> -0.935304, l -> 6.7936*10^-7} *)

Plot[f[zr, z0, l, x] /. z, {x, 0, 2}, Evaluated -> True,  Epilog -> Point@data]


No problems whatsoever.

• On coming back to spell-check my answer, I just noticed that we posted essentially the same answer at the same time! Great minds and all that... :-) Commented Jun 7, 2015 at 19:38
• I hadn't noticed either, but I see I was 30 secs earlier :) Commented Jun 7, 2015 at 19:40
• Both are really good, but I just picked 30 seconds earlier one! Sorry! Commented Jun 8, 2015 at 20:28

I see a different behavior when I try to evaluate your fit. First, your fitting model also seems to depend on a parameter l that is not included in the fit. I wonder if you had a separate definition for l that you did not include in your question.

Since I don't have that definition, I will simply let the fitting routine find the best fit value for l as well. I will therefore redefine your fitting model function:

f[l_, zr_, z0_, x_] := l*zr/Pi (1 + ((x + z0)/zr)^2)


With that model, one can then execute the fit:

mff = FindFit[data, f[l, zr, z0, x], {zr, z0, l}, x]

(* Out: {zr -> 0.175467, z0 -> -0.935304, l -> 6.7936*10^-7} *)


Plotting this fit together with the experimental points shows excellent agreement:

Plot[f[l, zr, z0, x] /. mff,
{x, 0.95 Min[data[[All, 1]]], 1.05 Max[data[[All, 1]]]},
Epilog -> {PointSize[0.015], Point[data]}, AxesOrigin -> {0, 0}
]


Incidentally, you may find it convenient to use NonlinearModelFit if you need anything more than just the bare fit parameters (documentation). It is essentially a high-level wrapper to FindFit, and it takes exactly the same arguments, but it returns a FittedModel object that contains a lot of information about the fit. See also the comparison made here: Difference between Fitting Algorithms.

nlmf = NonlinearModelFit[data, f[l, zr, z0, x], {zr, z0, l}, x]

You can then use the fitted model object as a function of $x$, e.g. in a plot:
Plot[nlmf[x], {x, 0.95 Min[data[[All, 1]]], 1.05 Max[data[[All, 1]]]}]

nlmf["ParameterTable"]