2
$\begingroup$

I have a typical nonlinear least square problem and it seems very similar to the example provided in the section on parameter fitting at the Wolfram website. Unfortunately I always get some error messages.

My code is as follows - could anyone help get rid of the error messages?

fitdata = {{1962, 0}, {1963, 0.9}, {1964, 2.4}, {1965, 6.2}, {1966, 11.3}, 
           {1967, 17.1}, {1968, 22.95}, {1969, 28.85}, {1970, 33.55}};

pfun = ParametricNDSolveValue[
           { Derivative[1][x][t] == m (a (1 - x[t]) + b (1 - x[t]) x[t]^h), 
             x[0] == 0}, 
            x, {t, 0, 10}, {a , b, h, m}];

fit = FindFit[ fitdata, 
               pfun[a, b, h, m][t], 
               {{a, 0.02}, {b, 0.5}, {h, 0.8}, {m, 42}}, t]
$\endgroup$
2
  • 1
    $\begingroup$ Hi Said, and welcome to Mathematica.SE! I edited your question's formatting - there's a relevant section in faq that tells you how you can do it yourself. I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the faq! 3) 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. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$
    – gpap
    Sep 17, 2013 at 11:29
  • 1
    $\begingroup$ The m is a redundant parameter here! $\endgroup$ Sep 17, 2013 at 12:37

1 Answer 1

7
$\begingroup$

This is an old (and possibly abandoned) question; however, its solution involves a number of issues related to NonlinearModelFit and ParametricNDSolveValue that show up on this site and it's perhaps constructive to look at this problem as a case study.

Rescaling the fit data

We wish to fit the following data:

fitdata = {{1962, 0}, {1963, 0.9}, {1964, 2.4}, {1965, 6.2}, {1966, 
    11.3}, {1967, 17.1}, {1968, 22.95}, {1969, 28.85}, {1970, 33.55}};

The first issue is one of scaling, since the model we want to use to fit the data has bounds (pardon me, Mathematicians) on y from 0 to 1. Additionally, it is practical to shift the x-data such that the first point is 0. This latter issue is easily addressed, but since we do not know the upper limit of fitdata[[All,2]] we run in to a problem. I attempt to solve this problem by introducing another adjustable parameter, ymax:

rsfitdata = fitdata;
rsfitdata[[All, 1]] = fitdata[[All, 1]] - 1962;
rsfitdata[[All, 2]] = Rescale[fitdata[[All, 2]], {0, ymax}, {0, 1}]

The re-scaled fitdata (rsfitdata) is now ready for the linear regression, so long as we have a good approximate value for ymax.

Model shape

I find it instructive to look at the model to make sure there is some hope of fitting the data to this model. We do this with a manual approach using Manipulate:

pfun = ParametricNDSolveValue[{Derivative[1][x][
      t] == (a (1 - x[t]) + b (1 - x[t]) x[t]^h), x[0] == 0}, 
   x, {t, 0, 10}, {a, b, h}];

Manipulate[
 Plot[pfun[a, b, h][t], {t, 0, 10}, 
  Epilog -> {Red, Point@(rsfitdata /. ymax -> ymax1)}, 
  PlotRange -> {0, 1}], {{a, 0.02}, 0, 1}, {{b, 0.544}, 0, 
  1}, {{h, 0.93}, 0, 1}, {{ymax1, 40.8}, 1, 100}]

Mathematica graphics

The results here are promising, and a manual approach, using the approximate values provided by the OP, yields a model that looks like it could fit the data satisfactorily.

Using NonlinearModelFit with ParametricNDSolveValue

First, it is beneficial to ensure that the model is using numerical values. One approach is to create a model wrapper such as:

model[a_, b_, h_, y_][t_] := 
 y pfun[a, b, h][t] /; And @@ NumericQ /@ {a, b, h, y, t}

Here, I will move ymax from the data and use it as another adjustable parameter in the model. Finally, when we execute the nonlinear regression, we need to make sure that the appropriate constraints are applied to the parameters; in this case, a, b, and h must all be > 0 and y must be > 1. (Technically >=, but this works.)

nlm = NonlinearModelFit[
  rsfitdata /. ymax -> 1, {model[a, b, h, y][t], a > 0, b > 0, h > 0, 
   y > 1}, {{a, 0.02}, {b, 0.544}, {h, 0.93}, {y, 40.8}}, t]

This command takes a few minutes on my machine, and the algorithm does not converge in 500 iterations; however we do obtain results which are reasonable:

nlm["BestFitParameters"]
(* {a -> 0.0067278, b -> 0.458518, h -> 0.7424, y -> 43.6642} *)
Plot[model[a, b, h, y][t - 1962] /. nlm["BestFitParameters"], {t, 
  1962, 1972}, Epilog -> {Red, Point@fitdata}]

Mathematica graphics

Note in the last plot I am overlaying the original fitdata.

Summary

When trying to perform sophisticated fits of this nature, I suggest the following general approach:

  • Ensure that your data are scaled appropriately
  • Spend time manually finding suitable starting values
  • Use some technique to ensure numeric values will be passed to NonlinearModelFit
  • Verify the results of your fit with the original data

Appendix

Thanks to Oleksandr R. for pointing this out: using Method -> {"NMinimize", Method->"NelderMead"} results in convergence of the model fit providing parameters very close to what is obtained above:

nlm["BestFitParameters"] (* With NMinimize/NelderMead method *)
(* {a -> 0.00670292, b -> 0.440683, h -> 0.731268, y -> 44.5793} *)
$\endgroup$
1
  • 3
    $\begingroup$ Very nice tutorial, +1. The nonlinear interior point method often has some trouble with convergence, so perhaps a better approach is to use NMinimize with Method -> "NelderMead". This way the NLIP method is used only in conjunction with another method to ensure that the constraints are obeyed in the final result, rather than all the way through the optimization (if this is allowable). If constraints are needed only to avoid the possibility of complex values appearing, it can be better just to transform the model to remove that possibility rather than to add the constraints. $\endgroup$ Jan 14, 2014 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.