How to fit function with data?

I have


lambdaValue = 633;
n = 1.52;

tN = {1.86, 1.95, 2.02, 2.11, 2.2, 2.3, 2.36, 2.48, 2.54, 2.66, 2.74,
2.85, 2.94, 3.04, 3.2, 3.21, 3.35, 3.46, 3.54, 3.64, 3.75, 3.86, 4,
4.09, 4.23, 4.30, 4.45, 4.57, 4.68, 4.81, 4.9, 5.07, 5.14, 5.31,
5.43, 5.57, 5.68, 5.85, 5.96, 6.11, 6.25, 6.38, 6.52, 6.65, 6.78,
6.92, 7.10, 7.24, 7.4, 7.57, 7.7, 7.89, 8, 8.19, 8.36, 8.52, 8.68,
8.87, 9.02, 9.22, 9.4, 9.63, 9.79, 10, 10.18, 10.41, 10.64, 10.85,
11.08, 11.33, 11.56, 11.83, 12.14, 12.44, 12.75, 13.05, 13.46,
13.83, 14.3, 14.69, 15.41, 15.89, 17.03};

dH = Table[i*lambdaValue/(4*n), {i, 1, Length[tN]}];


and i would like to fit it with a function a^2b(x-1.86)/(1+abx) so i do

fitFunction[a_, b_, x_] := (a^2 b (x - 1.86))/(1 + b a x)

fit = NonlinearModelFit[Transpose[{tN, dH}],
fitFunction[a, b, x], {a, b}, x]

Show[ListPlot[Transpose[{tN, dH}], PlotMarkers -> {Automatic, 5},
PlotLegends -> {"data"},
Plot[fit[x], {x, Min[tN], Max[tN]}, PlotStyle -> Red]]


but i have

how to get better results?

• fit = NonlinearModelFit[Transpose[{tN, dH}], fitFunction[a, b, x], {a, b}, x, Method -> "Newton"] Nov 19, 2023 at 2:24
• Both answers below give (theoretically) the exact same appropriate fit given your model as (a==c/d and b==d^2/c). But if you plot the residuals against Tn, you'll find that the model leaves a lot of structure that could be incorporated into a better model. Alternatively, that still-to-be-explained structure/model deviation might be associated with some (important?) un-measured variable.
– JimB
Nov 20, 2023 at 0:02

Provide initial estimates for a and b

\$Version

(* "13.3.1 for Mac OS X ARM (64-bit) (July 24, 2023)" *)

Clear["Global*"]

lambdaValue = 633;
n = 1.52 // Rationalize;

tN = {1.86, 1.95, 2.02, 2.11, 2.2, 2.3, 2.36, 2.48, 2.54, 2.66, 2.74, 2.85,
2.94, 3.04, 3.2, 3.21, 3.35, 3.46, 3.54, 3.64, 3.75, 3.86, 4, 4.09, 4.23,
4.30, 4.45, 4.57, 4.68, 4.81, 4.9, 5.07, 5.14, 5.31, 5.43, 5.57, 5.68,
5.85, 5.96, 6.11, 6.25, 6.38, 6.52, 6.65, 6.78, 6.92, 7.10, 7.24, 7.4,
7.57, 7.7, 7.89, 8, 8.19, 8.36, 8.52, 8.68, 8.87, 9.02, 9.22, 9.4, 9.63,
9.79, 10, 10.18, 10.41, 10.64, 10.85, 11.08, 11.33, 11.56, 11.83, 12.14,
12.44, 12.75, 13.05, 13.46, 13.83, 14.3, 14.69, 15.41, 15.89, 17.03} //
Rationalize;

dH = Table[i*lambdaValue/(4*n), {i, 1, Length[tN]}];

fitFunction[a_, b_, x_] := (a^2 b (x - 186/100))/(1 + b a x)


Develop estimates for a and b to be used in the NonlinearModelFit

(est = SolveValues[{fitFunction[a, b, tN[[2]]] == dH[[2]],
fitFunction[a, b, tN[[-1]]] == dH[[-1]]}, {a, b}][[1]]) // N

(* {11395.8, 0.0000294909} *)

(fit = NonlinearModelFit[Transpose[{tN, dH}], fitFunction[a, b, x],
Transpose[{{a, b}, est}], x]) // Normal

(* (1591.32 (-(93/50) + x))/(1 + 0.0974045 x) *)

Show[
ListPlot[Transpose[{tN, dH}],
PlotMarkers -> {Automatic, 5},
PlotLegends -> {"data"}],
Plot[fit[x], {x, Min[tN], Max[tN]},
PlotStyle -> Red,
PlotLegends -> {"fit"}]]


NonlinearModelFit default settings work ok with simpler model and thena and b can be derived, e.g.

data = Transpose[{tN, dH}];
f[x_, c_, d_] := c (x - 1.86)/(1 + d x)
nlm = NonlinearModelFit[data, f[x, c, d], {c, d}, x]
Plot[nlm[x], {x, 2, 20}, Epilog -> Point[data]]
par = {c, d} /. nlm["BestFitParameters"]
sol = Solve[{a ^2 b, a b} == par, {a, b}] // Quiet
{a^2 b, a b} /. sol[[1]]


Use a better search method:

fit = NonlinearModelFit[Transpose[{tN, dH}],
fitFunction[a, b, x], {a, b}, x,
Method -> {"Newton",
"StepControl" -> {"LineSearch", Method -> "Brent"}},
MaxIterations -> 2000]

Show[ListPlot[Transpose[{tN, dH}], PlotMarkers -> {Automatic, 5},
PlotLegends -> {"data"}],
Plot[fit[x], {x, Min[tN], Max[tN]}, PlotStyle -> Red]]
`