4
$\begingroup$

I have a vector of data points:

data = 10 Sin[#/10] + RandomVariate@NormalDistribution[] & /@ 
   Range[200];

And I have model that provides the complete data vector as value

matrix = Table[i (Sin[j/10]), {i, 20}, {j, 200}];
weights[a_] := Table[PDF[NormalDistribution[a, 1], i], {i, Range@20}];
model[a_] := weights[a].matrix;

model[10] is a good approximation of data.

They way I currently determine the fit parameters is by using FindMinimum and explicitly minimize the fit penalty:

FindMinimum[
 Total[(data - model[a])^2],
 {{a, 10}}
 ]

This works nice. But the evaluation of fit statistics like error volumes is very tedious because the underlying matrix and the model function is rather complex. When fitting with NonlinearModelFit instead, a lot of those statistics are readily available. But I have struggled to adapt it accordingly:

Something like

NonlinearModelFit[
 data,
 model[a],
 {{a, 1}},
 var
 ]

Unfortunately, there are problems. Can it be adapted? I dont actually need any variables to fit the expressions.

Kind regards

$\endgroup$
1
  • $\begingroup$ Doesn't NonlinearModelFit[ data, model[a], {{a, 10}}, var, Method -> "NMinimize" ] return the same or a better solution than your FindMinimum? $\endgroup$ Jul 17, 2015 at 19:27

2 Answers 2

4
$\begingroup$

I think using Quantile regression might do what you want. Quantile regression uses a minimization algorithm and if the fitting functions are B-splines you do not need to specify a model.

Similar problem and solution are discussed in more detail in Find Fit for Non-linear data .

If you really want to use the vectors of the matrix then you can use QuantileRegressionFit in the package linked below. (That is not straightforward, though. The matrix have to be converted into a list of functions, by say interpolation. I can work this solution out if it is of interest.)

The following steps apply Quantile regression with B-splines for the data in the question.

First, get the QuantileRegression.m package from MathematicaForPrediction at GitHub:

Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/QuantileRegression.m"]

Do the data generation with the command in the question:

data = 10 Sin[#/10] + RandomVariate@NormalDistribution[] & /@ Range[200];

Add t-axis:

data = Transpose[{Range[Length[data]], data}];

Find the regression quantile using B-splines of 2nd order:

qfunc = Simplify[
   QuantileRegression[data, 12, {0.5}, InterpolationOrder -> 2][[1]]];

Plot the data and the fitted curve:

dGr = ListPlot[data, PlotRange -> All, PlotStyle -> Red];
qfGr = Plot[qfunc[x], {x, Min[data[[All, 1]]], Max[data[[All, 1]]]}];
Show[{dGr, qfGr}, Frame -> True]

enter image description here Here is the fitted function after using PiecewiseExpand and Simplify:

qfunc = Evaluate[Simplify[PiecewiseExpand[qfunc[[1]]]]] &;
qfunc

enter image description here

Here is an example of approximation error statistics:

ListPlot[Map[{#[[1]], (qfunc[#1[[1]]] - #1[[2]])/#1[[2]]} &, data], 
 Filling -> Axis, Frame -> True]

enter image description here

$\endgroup$
0
$\begingroup$

As I understand the question, I think you are making things more difficult then they need be by calculating model fits in matrix. It seems you have already determined that the form of your model is $b \sin[\frac{x}{10}]$ and they you just need to fit $b$. This is exactly what NonlinearModelFit does. So you don't need to calculate out matrix and do your own minimisation function.

All that is needed is the data and the form.

data = 10 Sin[#/10] + RandomVariate@NormalDistribution[] & /@ Range[200];
fm = NonlinearModelFit[data, b Sin[x/10], {b}, x]
fm["BestFitParameters"]
fm["RSquared"]

Since data is a vector then it is fitted against successive x values (1, 2, ...). This is the first type of call listed in NonlinearModelFit's documentation. The fitted values and all the fit statistics are in fm. See the documentation for how to access them. I've tried a few executions and get very close to b -> 10 with perfect r-squared.

Hope this helps.

$\endgroup$
1
  • 1
    $\begingroup$ Thanks for the reply. Unfortunately, the simple case of the example is not present in my real problem. There, the function to be fitted is not a sine wave but the result of a multidimensional convolution integral. Calculating all of those integrals using the explicit form NIntegrate is extremely time consuming. A fast way is to replace all the convolutions by dot products weighing a high-dimensional tensor of possible function values. This tensor is called "matrix" in my example and the individual convolutions are performed by dot-mulitcation by a weighting vector "weights". $\endgroup$
    – tobalt
    Apr 22, 2015 at 20:10

Your Answer

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

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