# NonlinearModelFit on functions with NIntegrate doesn't give the right parameters

I have read some of the threads in the forum and tried to fit my data using nonlinearmodelfit, but the fitting result doesn't match the data at all. I set the initial fitting parameter values according to the experimental data, however, the fitting parameters were too off, especiall tm, which should be way much smaller than 1. I am posting the function below and my codes, and would really appreciate anyone who can help me solve this.

The function is:

where is a Lorentzian distribution. Here is my code

ClearAll["Global*"]
data = {{9.72762*10^-8, 0.27573624}, {1.9357175*10^-7,0.35856727}, {3.0400054*10^-7, 0.42113978}, {3.851921*10^-7,0.4413983}, {4.675645*10^-7, 0.45245874}, {7.664082*10^-7,0.529744}, {9.5011717*10^-7, 0.5628668}, {1.8910378*10^-6,0.6365067}, {2.9057892*10^-6, 0.7101052}, {6.445126*10^-6,0.75986505}, {0.000011039828, 0.796716}, {0.000057973855,0.8705107}, {0.000103733146, 0.8834713}, {0.00045879057, 0.9223119}, {0.0015340322, 0.93537235}, {0.007241259, 0.9540027}};
f[tm_?NumericQ, gamma_?NumericQ, t_?NumericQ] := Simplify[NIntegrate[(1 - Exp[-(t/tsw)^2])/tsw*PDF[CauchyDistribution[Log[tm], gamma], Log[tsw]], {tsw, 10^-20,Infinity},WorkingPrecision -> 16,MaxRecursion -> 500]]
nlm = NonlinearModelFit[data, {f[tm, gamma, t],tm > 0 && gamma > 0}, {{tm, 10^-5}, {gamma, 1}}, t]
nlm["BestFitParameters"]
Show[ListLogLinearPlot[data],LogLinearPlot[nlm[t], {t, 10^-7, 0.01}, PlotStyle -> Orange]]


The result is posted here as well.

• As an update, I tried to add more constraints to the fitting parameters, but ended up with many errors: nlm = NonlinearModelFit[data, {f[tm, gamma, t], 1 > tm > 0 && gamma > 0}, {{tm, 10^-5}, {gamma, 1}}, t]. – fermiano Jun 24 '20 at 11:01
• These are the errors: CauchyDistribution::realprm: Parameter -18.4207+3.14159 I at position 1 in CauchyDistribution[-18.4207+3.14159 I,12.9138] is expected to be real. NIntegrate::inumr: The integrand ((1-E^(-(<<23>>/tsw^2))) PDF[CauchyDistribution[-18.4207+3.14159 I,12.9138],<<1>>])/tsw has evaluated to non-numerical values for all sampling points in the region with boundaries {{1.000000000000000,1.000000000000000*10^-20}}. – fermiano Jun 24 '20 at 11:02

There are three modifications that I would suggest:

1. Use better starting values
2. Fit using logtm rather than tm.
3. Add in the option Method-> NMinimize, Method->"DifferentialEvolution"} to NonlinearModelFit.

Good starting values can make all the difference in the world. When there is lack of convergence or you get a really bad fit as you did, then exploring with ContourPlot when you have just two parameters can be helpful.

When parameters have a very wide range of scales, then including some scaling can be helpful. For example, if one parameter p1 has a value around 3 and another p2 has a value around 4000000, then reparameterize with 10^6 p2. Then p2 will have a value around 4. Sometimes (as in this case) replacing Log[tm] with a variable named logtm is a simple modification.

Using Method = NMinimize is many times more stable than the default method.

ClearAll["Global*"]
data = {{9.72762*10^-8, 0.27573624}, {1.9357175*10^-7,
0.35856727}, {3.0400054*10^-7, 0.42113978}, {3.851921*10^-7,
0.4413983}, {4.675645*10^-7, 0.45245874}, {7.664082*10^-7,
0.529744}, {9.5011717*10^-7, 0.5628668}, {1.8910378*10^-6,
0.6365067}, {2.9057892*10^-6, 0.7101052}, {6.445126*10^-6,
0.75986505}, {0.000011039828, 0.796716}, {0.000057973855,
0.8705107}, {0.000103733146, 0.8834713}, {0.00045879057,
0.9223119}, {0.0015340322, 0.93537235}, {0.007241259, 0.9540027}};

f[logtm_?NumericQ, gamma_?NumericQ, t_?NumericQ] :=
NIntegrate[(1 - Exp[-(t/tsw)^2])/tsw*PDF[CauchyDistribution[logtm, gamma], Log[tsw]], {tsw, 10^-20, Infinity}, WorkingPrecision -> 16, MaxRecursion -> 500]
nlm = NonlinearModelFit[data, {f[logtm, gamma, t], gamma > 0}, {{logtm, -14}, {gamma, 1.9}}, t,
Method -> {NMinimize, Method -> "DifferentialEvolution"}];

nlm["BestFitParameters"]
(* {logtm -> -14.2019, gamma -> 1.90857} *)

Show[ListLogLinearPlot[data],
LogLinearPlot[nlm[t], {t, 10^-7, 0.01}, PlotStyle -> Orange]]


NonlinearModelFit took many minutes. Don't know how long. I got tired of waiting and went to breakfast. It was finished when I got back.

• thanks a lot for your suggestions. It finally worked, and really took a long time, with these error-like messages "NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small." I know this fitting function is quite complicated, and maybe that's why it took ages to finish. Do you know any method to speed it up? – fermiano Jun 25 '20 at 3:05
• I would have to imagine the slowdown is with the NIntegrate portion. If it's a difficult integral, then you should ask that as a separate question where someone much more knowledgeable about such things than me could answer that. – JimB Jun 25 '20 at 3:14