Curve fitting by running through hundreds of models and return the one with best fit

In the past, I used to solve a lot of my regression analysis (curve fitting) problems with a program called DataFit which runs on Windows. It has hundreds of regression models which it runs through in in order to get the best fit. - Now this is extremely convenient for the lazy engineer with little time at hand.

However, I shifted OS and I now got my beloved Mathematica which has a lot of curve fitting functions who all require a great deal of manual tinkering and guessing.

So the question is: Are there any functions/packages that automatically run through an abundance of models and return the one with best fit? Or do I have to write it myself?

EDIT: Here is an example of a rather clean set of data I often encounter:

data = {{0, 0}, {1.5, 10.47}, {4.8, 16.31}, {9, 20.75}, {14.1,
23.81}, {22.6, 26.28}, {32.1, 27.96}, {41.3, 29.94}, {53.8,
34.68}, {64.8, 40.22}, {75, 47.04}, {82, 53.48}, {87.8,
60.15}, {91.8, 67.75}, {95.1, 76.09}, {97, 83.97}, {98, 90}, {99,
100}}

And some interpolating function would be suitable for this, but the problem remains how to extract the interpolating functions and use them in other programs.

• What is the point to find a fit with a random function that is not theoretically meaningful? If you just need a smooth line you can use a BSplineFunction or a LowpassFilter. – rhermans Nov 15 '14 at 11:51
• @rhermans That sounds reasonable, but for me, the theoretical background of the data it is not always known beforehand. Do the functions you mentioned return models that can be intered in other programs? – MathLind Nov 15 '14 at 12:08
• Well the data is the best model of itself, if the theory behind is unknown. Probably what you are after is to have a sparse representation of your data? i.e any function as long as it has with the minimum number of parameters? Hard to do without defining (implicit or explicitly) what is signal and what is noise. Can you give examples of your data and of good and bad fits? Its not clear to me what you really need. – rhermans Nov 15 '14 at 12:15
• @rhermans Thanks for your comment. I added some simple data above. – MathLind Nov 15 '14 at 12:42

vars = {w, x, y, z};
terms = MonomialList[(Plus @@ vars)^3] /. _Integer x_ :> x;
cols = Join @@ {vars, terms}
(* {w,x,y,z,w^3,w^2 x,w^2 y,w^2 z,w x^2,w x y,w x z,w y^2,
w y z,w z^2,x^3,x^2 y,x^2 z,x y^2,x y z,x z^2,y^3,y^2 z,y z^2,z^3} *)

For the data

dt = Table[Join[RandomInteger[10, 4], {RandomReal[]}], {100}];

evaluate all models with up to three covariates from the set cols and get the goodness-of-fit-measures "AIC", "BIC", "AdjustedRSquared", "AICc", "RSquared" for each model:

models = Table[Join[{j}, LinearModelFit[dt, j, vars][{"AIC", "BIC",
{j, Subsets[cols, 3]}];
Length@models
(* 2325 *)

Display the top 10:

Grid[{{"Model", "BestFit", "AIC", "BIC", "AdjustedRSquared", "AICc",
"RSquared"}, ## & @@ SortBy[models, #[] &][[;; 10]]},
Dividers -> All] See also: LogitFitModel >> Scope >> Properties >> Goodness-of-Fit Measures for a great example.

Update: A single function combining the necessary steps:

modelsF = Table[Join[{j}, LinearModelFit[#, j, #2][{"BestFit", "AIC",
"BIC", "AdjustedRSquared", "AICc", "RSquared"}]], {j, Subsets[#3, #4]}] &;

and another function for showing the results:

resultsF = Grid[{{"BestFit", "Model", "AIC", "BIC",
## & @@ SortBy[#, #[] &][[;; #2]]}, Dividers -> All] &;

Using the OP's example data to find the best 10 models with 3 covariates:

data = {{0, 0}, {1.5, 10.47}, {4.8, 16.31}, {9, 20.75}, {14.1, 23.81}, {22.6, 26.28},
{32.1, 27.96}, {41.3, 29.94}, {53.8, 34.68}, {64.8, 40.22},
{75, 47.04}, {82, 53.48}, {87.8, 60.15}, {91.8, 67.75}, {95.1, 76.09},
{97, 83.97}, {98, 90}, {99, 100}};
cols = {1, x, x^2, x^3, x^4, Sin[x], Cos[x], 1/(.001 + x), 1/(.001 + x^2),
1/(.001 + x^3), IntegerPart[x], PrimePi[Round[x]]};

models = modelsF[data, {x}, cols, {3}];
resultsF[models, 10] Note: a better way to generate a richer set of covariates would be

cols = MonomialList[(1 + Plus @@ vars)^3] /. _Integer x_ :> x; (*thanks: @BobHanlon *)

Another note: All the above is essentially a brute-force approach. More rigorous and and smarter methods must exist for model selection.

• Awesome and pedagogical answer: My heart jump with joy. Is this the level of knowledge that awaits me after a few more years with Mathematica. – MathLind Nov 15 '14 at 12:58
• @MathLind, great to know this made you so happy:) – kglr Nov 15 '14 at 12:59
• You will get more models and a better fit with cols = MonomialList[(1 + Plus @@ vars)^3] /. _Integer x_ :> x; – Bob Hanlon Nov 15 '14 at 15:50
• @Bob, good point. I just wanted to get some list of covariates for illustration assuming that the user knows the specific covariates he would like to use. – kglr Nov 15 '14 at 16:06
• @MathLind, thank you for the accept. Re "many others," great to know that there are quite a few of us "lazy engineers":) – kglr Nov 17 '14 at 11:28

In version 10.2 there is a new experimental function which might be what you are looking for: FindFormula.

I suspect that a genetic programming algorithm (symbolic regression) is behind this new feature.

See also my question here: What is behind experimental function: FindFormula?

• Thanks, I will look in to that after moving to 10.2. – MathLind Jul 17 '15 at 17:13
• Installed and tested. This has the potential of being truly useful. – MathLind Jul 17 '15 at 19:34