# NonlinearModelFit does not find a good fit

I am trying to fit my data to the following function,

$$\frac{a b t \left(\log \left(\frac{-a d t+a t-1}{a d t}\right)-2\right)}{4 (a t-1)}-c$$

data = {
{0.275, 23.85}, {0.275, 22.03}, {0.2613, 21.13}, {0.2888, 20.77}, {0.3438, 18.71},
{0.2475, 17.7}, {0.3301, 17.65}, {0.3163, 16.79}, {0.3713, 17.09}, {0.3851, 14.92},
{0.4126, 14.37}, {0.4401, 12}, {0.3851, 11.7}, {0.4813, 11.14}, {0.4538, 10.64},
{0.4676, 10.08}, {0.4951, 9.63}, {0.4951, 8.975}, {0.5639, 8.42}, {0.6601, 8.571},
{0.5914, 7.311}, {0.5088, 7.613}, {0.5088, 7.361}, {0.5776, 6.756}, {0.7564, 6.807},
{0.6464, 6.303}, {0.7426, 5.597}, {0.7014, 5.496}, {0.6189, 5.395}, {0.6464, 4.992},
{0.7289, 4.891}, {0.7426, 4.437}, {0.8802, 4.689}, {0.8664, 4.235}, {0.7976, 3.933},
{0.9077, 3.58}, {0.8664, 2.975}, {0.9627, 3.076}, {0.9352, 2.672}, {1.073, 2.773},
{1.018, 2.269}, {1.073, 1.966}, {1.155, 2.218}, {1.169, 1.714}, {1.293, 1.866},
{1.279, 1.613}, {1.306, 1.361}, {1.458, 1.563}, {1.458, 1.008}, {1.54, 1.059},
{1.623, 1.261}, {1.788, 1.059}, {1.719, 1.16}, {1.802, 0.9076}, {2.008, 0.7563},
{2.09, 0.8571}, {2.159, 1.008}, {2.242, 0.605}, {2.31, 0.6555}, {2.407, 0.8067},
{2.544, 0.8067}, {2.599, 0.6555}, {2.682, 0.4538}, {2.792, 0.7563}, {2.888, 0.4034},
{2.929, 0.7563}, {3.246, 0.5546}, {3.356, 0.4538}, {3.479, 0.4538}, {3.906, 0.4034},
{4.029, 0.4538}, {4.181, 0.3529}, {4.332, 0.2521}, {4.621, 0.2521}, {4.855, 0.2521},
{5.088, 0.3025}, {5.185, 0.3025}, {5.804, 0.3025}, {6.546, 0.3025}
};


using the following code:

nlm = NonlinearModelFit[
data,
{-c+(a b t (-2+Log[(-1+a t-a d t)/(a d t)]))/(4 (-1+a t)),a>0,b>0,c>0,d>0},
{{a,10},{b,20},{c,36},{d,0.0001}},
t
]


It gives me following fit which is obviously not correct,

$$\frac{50. t \left(\log \left(\frac{100. (9.99 t-1)}{t}\right)-2\right)}{10. t-1}-36.$$

I tried manually varying parameters and I can come up with the following fit,

With parameters $a=10$, $b=20$, $c=36.5$, $d=0.0001$.

But I want to do it using Mathematica and find the right parameters for a proper fit and not just do it by trial and error.

-
Your model seems to very sensitive the initial search value of parameter d. I get a much better fit starting with d = 1/200. –  m_goldberg Mar 2 '14 at 18:17
@m_goldberg that reduces the correlations between the parameters significantly and hence produces a result with far smaller errors. However, the end result is still not very good. –  Oleksandr R. Mar 2 '14 at 19:05

I think as much discussion as can reasonably be had on this issue has already taken place on this site, although the solution might not be readily apparent without the benefit of experience. This is not in any way meant as a criticism of the question (which is well-posed and relates to a commonly-encountered, important issue), but rather will be my excuse for presenting a synthesis of two of my existing answers without very much accompanying discussion. If anything is unclear after reviewing the previous posts, please point it out and I will try to clarify matters.

You might already have found the question entitled Problem with NonlinearModelFit, and more specifically my answer in which I advocate using differential evolution when obtaining reasonable values for the parameters proves too difficult otherwise. This is especially important when performing constrained fits, for which the nonlinear interior point method is used by default. This normally has great difficulty in locating global minima simply on account of being constrained strictly to the feasible region.

The advice is equally valid in this case, but unfortunately leads immediately to problems due to the particular form of your model, which produces a complex result for certain values of the parameters. To avoid that, we may use the TransformedFit/ComplexFit package. I still have to update that answer with the latest changes, but in the mean time you can get the latest version of the notebook (not the package file, which also has yet to be updated) from the git repository.

Run the package as it appears in the notebook. Then, after defining data as in your question:

fit = ComplexFit[data,
{
model = -c + (a b t (-2 + Log[(-1 + a t - a d t)/(a d t)]))/(4 (-1 + a t)),
TransformedParameter[Re, a] > 0, TransformedParameter[Re, b] > 0,
TransformedParameter[Re, c] > 0, TransformedParameter[Re, d] > 0
}, {a, b, c, d}, t,
"CoordinateSystem" -> "Real",
Method -> {NMinimize,
Method -> {"DifferentialEvolution",
"SearchPoints" -> 40, "ScalingFactor" -> 0.95, "CrossProbability" -> 0.05,
"PostProcess" -> {FindMinimum, Method -> "QuasiNewton"}
}
}
]

(* -> {a -> 5.49939, b -> 30.6601, c -> 25.1868, d -> 0.00556649} *)


You can give initial guesses for the parameters if you like, but I found that it didn't really help. The result seems reasonable:

Show[{
ListPlot[data, PlotStyle -> Red],
Plot[model /. fit, {t, Min@data[[All, 1]], Max@data[[All, 1]]}, PlotRange -> All]
}]


The errors are rather large, but I suppose this is an issue you can probably deal with on your own:

(To get the NonlinearModelFit result, just specify the option "FitFunction" -> NonlinearModelFit in the ComplexFit call. The default is FindFit. The above table is the result of asking for the "ParameterConfidenceIntervalTable" property.)

Finally the correlation matrix, which will hopefully give you an idea why the errors are as they are:

-
Was just looking at your answer. A heck of a lot easier to give you +1 rather than optimizing Methods of Methods of Methods... –  bobthechemist Mar 2 '14 at 19:36
FWIW paying close attention to what is causing the generation of complex numbers allows this problem to be solved with NonlinearModelFit. Setting the constraints to {a > 4.2, b > 0, c > 0, d > 0, d < .02} keeps the Log term positive for the given values of t. Then your DifferentialEvolution parameters work well in NonlinearModelFit. –  bobthechemist Mar 2 '14 at 19:53
it works for me. thanks a lot. –  nitin Mar 2 '14 at 21:39