# FindFit returns worse result when putting constraints on parameters

I want to fit some data to a model of exponential decay using the FindFit function:

data = {{0, 78}, {24, 64.5}, {48, 70.5}, {96, 54}, {144, 64.5}, {216, 3}, {336, 0}, {696, 0}};
model = data[[1, 2]]*Exp[-k1*t];

fit1 = FindFit[data, model, k1, t]
fit2 = FindFit[data, {model, k1 > 0}, k1, t]

modelf1 = Function[{t}, Evaluate[model /. fit1]];
modelf2 = Function[{t}, Evaluate[model /. fit2]];

Plot[#[t], {t, 0, 696}, Epilog -> Map[Point, data], PlotRange -> All] & /@ {modelf1, modelf2}


Interestingly, the model with no specified constraint on k1 finds a much better solution than the constrained model, but the solution of the unconstrained problem falls within the range of the constrained one. Here is the output:

{k1 -> 0.00512571}
{k1 -> 1.01979} Why isn't the solution to the constrained problem at least as good as the solution of the unconstrained one?

• I think the reason is that different methods are used for constrained and unconstrained problems. – Ajasja Aug 23 '12 at 13:10
• Have you tried: fit2 = FindFit[data, {model, k1 > 0}, k1, t, Method -> NMinimize] – P. Fonseca Aug 23 '12 at 13:13

## 2 Answers

It is because your constraint forces the path chosen for finding a local extrema. You could verify it by doing:

data ={{0, 78}, {24, 64.5}, {48, 70.5}, {96, 54}, {144, 64.5}, {216, 3}, {336, 0}, {696, 0}};
model = data[[1, 2]]*Exp[-k1*t];
l = {}; l1 = {};
fit1 = FindFit[data,  model, k1,          t, EvaluationMonitor :> AppendTo[l, k1]]
fit2 = FindFit[data, {model, k1 > 0}, k1, t, EvaluationMonitor :> AppendTo[l1, k1]]

Show[ListLinePlot[{l1,l}],
ListPlot[{l1,l},PlotStyle ->{{Blue,PointSize[Large]}, {Red,PointSize[Medium]}}]] Edit

As for why some methods fail, you can see your extrema is very sharp:

f[k1_] := Total[(data[[1, 2]]*Exp[-k1*#[]] - #[])^2 & /@ data];
Plot[{f[k1], Evaluate[D[f[k2], k2] /. k2 -> k1]}, {k1, -1, 1},
PlotRange -> {{-.1, .4}, {0, 16500}}, Axes -> {True, False}, Frame -> True] • But it does not explain why the Automatic option for the constrained problem uses another path then the constrained "NMinimize" option? Just add l2={} and fit3 = FindFit[data, {model,k1>0}, k1, t, Method->"NMinimize",EvaluationMonitor :> AppendTo[l2, k1]] to your code. – Frederik Ziebell Aug 23 '12 at 15:17
• @FrederikZiebell as far as I can see, you are not asking that in your question – Dr. belisarius Aug 23 '12 at 15:33
• You should start another career as function counselor and help all those solutions come to terms with their shyness (or aichmophobia) – Yves Klett Aug 19 '13 at 8:33
• @YvesKlett Function shyness is deeply studied by psycho-math-analysts, including real and imaginary shyness problems – Dr. belisarius Aug 19 '13 at 10:54
• @belisarius If you are only interested in values for a fit parameter for a given range, say 0 to 1, is it possible to allow FindFit to look or start outside of that range, say at 1.1, but ignore all results outside of that range? I'm currently facing this problem because I want to fit a parameter within a specified range, but NMinimize fails if I try to impose that range and Method->Automatic leads to fit parameters that do not appear to be as good as NMinimize. If I open the range wider, FindFit only finds the result outside of the range I really care about. What do you suggest? – iwantmyphd Mar 26 '15 at 17:02

Different methods are used for constrained and unconstrained problems.
Compare for example

data = {{0, 78}, {24, 64.5}, {48, 70.5}, {96, 54}, {144, 64.5}, {216,
3}, {336, 0}, {696, 0}};
model = data[[1, 2]]*Exp[-k1*t];
methods = {Automatic, "ConjugateGradient", "Gradient",
"LevenbergMarquardt", "Newton", "QuasiNewton",
{"NMinimize", Method -> "NelderMead"},
{"NMinimize", Method -> "DifferentialEvolution"},
{"NMinimize", Method -> "SimulatedAnnealing"},
{"NMinimize", Method -> "RandomSearch"} };

fit1 = FindFit[data, model, k1, t, Method -> #] & /@ methods;
fit2 = (FindFit[data, {model, k1 > 0}, k1, t, Method -> #] & /@ methods) \
/. FindFit[__] -> "NA";

TableForm[Transpose@{fit1, fit2}, TableAlignments -> Left,
TableHeadings -> {methods, {"Unconstrained", "Constrained"}}] Note the warnings of the type Method -> XXX can only be used for unconstrained problems.

We see that NMinimize was the only method suitable for this constrained problem. For the unconstrained problem the "Gradient" method was probably used.

Oh, and if you want the table LeftAlignment to actually work, check out this great answer.

• Add the option "Automatic" to your methods variable and you see the thing that makes me wonder: Why does the Automatic method for the unconstrained problem find the value k1 -> 1.01979 when "NMinimize" is the only method available? – Frederik Ziebell Aug 23 '12 at 13:49
• @FrederikZiebell I always thought "Automatic" just means that mma chooses the method for you. But in this case it seems something more is happening. No idea for now. – Ajasja Aug 23 '12 at 13:50
• Didn't see this answer until now. +1. Two methods are missing: "InteriorPoint" and {"NMinimize", Method -> "NonlinearInteriorPoint"}. FindFit does not like to use these and spits out a lot of errors, but does return a result in both cases. Anyway, it shows that Automatic corresponds to "InteriorPoint" for the constrained problem in this case (and, I think, actually in general as well). – Oleksandr R. Nov 25 '13 at 21:58