What to give as "real column vector of initial parameters" to nonlin_curvefit?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

What to give as "real column vector of initial parameters" to nonlin_curvefit?

Doron Behar
Hey dear octaves,

So today I wanted to fit a curve to a set of x and y data and I reached
the nonlin_curvefit function. Docs:
https://octave.sourceforge.io/optim/function/nonlin_curvefit.html

What am I supposed to give the 2nd argument? It seems like a necessary
argument according to the signature. The docs don't explain much about
it and I haven't found much in the mailing list's archives.

I tried to take the example and fiddle with the values they give there
and I haven't noticed any change in the final plots of the data vs the
fit...

Thanks.


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Dmitri A. Sergatskov


On Thu, Jun 11, 2020 at 9:04 AM Doron Behar <[hidden email]> wrote:
Hey dear octaves,

So today I wanted to fit a curve to a set of x and y data and I reached
the nonlin_curvefit function. Docs:
https://octave.sourceforge.io/optim/function/nonlin_curvefit.html

What am I supposed to give the 2nd argument? It seems like a necessary
argument according to the signature. The docs don't explain much about
it and I haven't found much in the mailing list's archives.

I tried to take the example and fiddle with the values they give there
and I haven't noticed any change in the final plots of the data vs the
fit...

Thanks.

Initial guess for the fit parameters. E.g. if you are fitting to say a*sin(x) + b*cos(x), then pin is  [a0, b0].
If you do not know what a0 and b0 could be,  set them to 1.

Dmitri.
--


 


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

phofman
In reply to this post by Doron Behar

Dne 11. 06. 20 v 14:50 Doron Behar napsal(a):
>
> What am I supposed to give the 2nd argument? It seems like a necessary
> argument according to the signature. The docs don't explain much about
> it and I haven't found much in the mailing list's archives.

Initial values of the searched-for parameters to start with, typically
some estimate.

## initial values:
init = [.25; .25];  <------
## linear constraints, A.' * parametervector + B >= 0
A = [1; -1]; B = 0; # p(1) >= p(2);
settings = optimset ("inequc", {A, B});

## start optimization
[p, model_values, cvg, outp] = nonlin_curvefit (f, init, indep, obs, <--
  settings)

The definition says
Function File: [p, fy, cvg, outp] = nonlin_curvefit (f, pin, x, y)

where pin means p_initial or p_input
>
> I tried to take the example and fiddle with the values they give there
> and I haven't noticed any change in the final plots of the data vs the
> fit...

That is because all your fitting runs converged from the different
initial values to the same optimal result. The best proof the method
works :-)

Best regards,

Pavel.


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Doron Behar
On Thu, Jun 11, 2020 at 04:09:03PM +0200, Pavel Hofman wrote:
OK I think I understand.

I think it should be possible to explain this better just as both of you
did here, but in the docs... But thanks anyway :+1:.

Since I'm already here, perhaps you could help me a bit further:

I set this parametric function:

    harmonic_param_func = @(p, t) p(1) * exp(-t/(2 * p(2))) * cos(p(3)*t + p(4))

And I call nonlin_curvefit like this:

    [p, fy, cvg, outp] = nonlin_curvefit( ...
        harmonic_param_func, [ ...
            guessed_max_amplitude; ...
            guessed_tau; ...
            guessed_period; ...
            guessed_phase
        ], ...
        counts, times ...
    );

Where the variables guessed_* are corresponding values I think may be a
good starting guess for the fitting algorithm. But I get this error when
I call it as so:

    error: NA: invalid class name
    error: called from
        __nonlin_residmin__ at line 212 column 21
        nonlin_curvefit at line 83 column 22
        ./harmonic-oscillator.m at line 50 column 21

And if I use `,` instead of `;` I get the error:

    error: initial parameters must be either a structure or a column vector
    error: called from
        __nonlin_residmin__ at line 101 column 7
        nonlin_curvefit at line 83 column 22
        ./harmonic-oscillator.m at line 50 column 21

Maybe I'm just not fluent yet in octave's / matlab's data types. But,
the 2nd error intrigued me more: Is it possible to use a struct where my
`p` is, in the fitting function? If so that's sound like another
undocumented detail of the function?

Doron.

On Thu, Jun 11, 2020 at 04:09:03PM +0200, Pavel Hofman wrote:

>
> Dne 11. 06. 20 v 14:50 Doron Behar napsal(a):
> >
> > What am I supposed to give the 2nd argument? It seems like a necessary
> > argument according to the signature. The docs don't explain much about
> > it and I haven't found much in the mailing list's archives.
>
> Initial values of the searched-for parameters to start with, typically
> some estimate.
>
> ## initial values:
> init = [.25; .25];  <------
> ## linear constraints, A.' * parametervector + B >= 0
> A = [1; -1]; B = 0; # p(1) >= p(2);
> settings = optimset ("inequc", {A, B});
>
> ## start optimization
> [p, model_values, cvg, outp] = nonlin_curvefit (f, init, indep, obs, <--
>   settings)
>
> The definition says
> Function File: [p, fy, cvg, outp] = nonlin_curvefit (f, pin, x, y)
>
> where pin means p_initial or p_input
> >
> > I tried to take the example and fiddle with the values they give there
> > and I haven't noticed any change in the final plots of the data vs the
> > fit...
>
> That is because all your fitting runs converged from the different
> initial values to the same optimal result. The best proof the method
> works :-)
>
> Best regards,
>
> Pavel.


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

siko1056
On 6/12/20 2:20 AM, Doron Behar wrote:> [...]
> Since I'm already here, perhaps you could help me a bit further:
>
> I set this parametric function:
>
>     harmonic_param_func = @(p, t) p(1) * exp(-t/(2 * p(2))) *
cos(p(3)*t + p(4))

>
> And I call nonlin_curvefit like this:
>
>     [p, fy, cvg, outp] = nonlin_curvefit( ...
>         harmonic_param_func, [ ...
>             guessed_max_amplitude; ...
>             guessed_tau; ...
>             guessed_period; ...
>             guessed_phase
>         ], ...
>         counts, times ...
>     );
>
> Where the variables guessed_* are corresponding values I think may be a
> good starting guess for the fitting algorithm. But I get this error when
> I call it as so:
>
>     error: NA: invalid class name
>     error: called from
>         __nonlin_residmin__ at line 212 column 21
>         nonlin_curvefit at line 83 column 22
>         ./harmonic-oscillator.m at line 50 column 21
>
> And if I use `,` instead of `;` I get the error:
>
>     error: initial parameters must be either a structure or a column
vector

>     error: called from
>         __nonlin_residmin__ at line 101 column 7
>         nonlin_curvefit at line 83 column 22
>         ./harmonic-oscillator.m at line 50 column 21
>
> Maybe I'm just not fluent yet in octave's / matlab's data types. But,
> the 2nd error intrigued me more: Is it possible to use a struct where my
> `p` is, in the fitting function? If so that's sound like another
> undocumented detail of the function?
>
> Doron.

You function call does not look that wrong, but the devil is in the
detail.  Can you sent us a minimal working example containing all
"guessed_*" values and "counts", "times"?

Kai


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Doron Behar
On Fri, Jun 12, 2020 at 02:27:18PM +0900, Kai Torben Ohlhus wrote:
>
> You function call does not look that wrong, but the devil is in the
> detail.  Can you sent us a minimal working example containing all
> "guessed_*" values and "counts", "times"?
>
> Kai

Sure, I've attached 2 files to this email that should reproduce the
issue:

- `nomag-50-500.txt` contains the measurements I'm trying to fit the
  data to.
- `MWE.m` reads the measurements from the file, plots the data as is and
  then calls nonlin_curvefit in two different ways. Please see the %%
  comments I wrote in it.

Doron.



nomag-50-500.txt (9K) Download Attachment
MWE.m (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Dmitri A. Sergatskov


On Fri, Jun 12, 2020 at 6:06 AM Doron Behar <[hidden email]> wrote:
On Fri, Jun 12, 2020 at 02:27:18PM +0900, Kai Torben Ohlhus wrote:
>
> You function call does not look that wrong, but the devil is in the
> detail.  Can you sent us a minimal working example containing all
> "guessed_*" values and "counts", "times"?
>
> Kai

Sure, I've attached 2 files to this email that should reproduce the
issue:

- `nomag-50-500.txt` contains the measurements I'm trying to fit the
  data to.
- `MWE.m` reads the measurements from the file, plots the data as is and
  then calls nonlin_curvefit in two different ways. Please see the %%
  comments I wrote in it.


There are multiple problems. 

There are errors in the code. You seem to mix up X and Y variables in plots and fits.
You read data as integers(?) -- why? You want doubles.

Octave (and matlab) is primarily an interactive programming/developing environment.
When your program crashes you still can inspect the variables left and see if the values
of those variables give you some hints.
You say "Using `;` instead of `,` doesn't work either", but the error is different!
It should have given you a clue.

I found in general the curve fitting in "optim" package are more finicky than they should be.
Out of those "leasqr" seems to work better for me than "nonlin_curvefit". 

The parameters in the fit function are usually not the same parameters you would use in
human definition of the function. Usually you want to make them be more similar to each other.
You should avoid divisions if possible.
In you case the function becomes:

exp(a*t)*(b*sin(w*t)+c*cos(w*t))
(a,b,c,w -- fit parameters; w = 2*pi*frequency)
It looks to me it fits better if you add a small offset as well.

Having said that, attached are a modified script and the output it produced for me.
 
Doron.


Dmitri.
--



mve_das.m (2K) Download Attachment
data_fit.svg (220K) Download Attachment
error.svg (23K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Doron Behar
Dimitri,

You are a savior.

   -=-
(\  _  /)
( \( )/ )
(       )
 `>   <'
 /     \
 `-._.-'

But I have some questions:

> There are multiple problems.
>
> There are errors in the code. You seem to mix up X and Y variables in plots
> and fits.

It seemed weird to me that they got reversed - I just decided who is X
and who is Y when I plotted the raw data - no idea how I reached that
conclusion...

> You read data as integers(?) -- why? You want doubles.

Hmm OK good to know.

> Octave (and matlab) is primarily an interactive programming/developing
> environment.
> When your program crashes you still can inspect the variables left and see
> if the values

I know and it seemed that guessed_values_arr had the same content when I
used `;` and when I used `,`...

> of those variables give you some hints.
> You say "Using `;` instead of `,` doesn't work either", but the error is
> different!
> It should have given you a clue.

I saw the error was different but I couldn't figure out what to do.

> I found in general the curve fitting in "optim" package are more finicky
> than they should be.
> Out of those "leasqr" seems to work better for me than "nonlin_curvefit".
>
> The parameters in the fit function are usually not the same parameters you
> would use in
> human definition of the function. Usually you want to make them be more
> similar to each other.

What do you mean by similar to each other?

> You should avoid divisions if possible.

You mean division of say x by a parameter right? Like I did with tau?

> In you case the function becomes:
>
> exp(a*t)*(b*sin(w*t)+c*cos(w*t))
>
> (a,b,c,w -- fit parameters; w = 2*pi*frequency)

This is interesting - you chose to use:

b*sin(w*t) + c*cos(w*t)

And not:

j*sin(w*t +k)

While mathematically speaking (IIRC) that for every b and c, there exist
j and k such that both expressions are identical for all t...

Why does it work for the 1st option and not the 2nd?

> It looks to me it fits better if you add a small offset as well.

Hmm I tried without that offset and it seemed pretty much as good. You
are talking about 0.759 here:

> harmonic_param_func = @(t, p) (exp(-t * p(2)) .* (p(1)*sin(2*pi*p(3)*t) + p(4)*cos(2*pi*p(3)*t)) + 0.759);

Right?

> Having said that, attached are a modified script and the output it produced
> for me.

Hmm

Reading your script, I had 1 more question:

Regarding:

> harmonic_param_func = @(t, p) (exp(-t * p(2)) .* (p(1)*sin(2*pi*p(3)*t) + p(4)*cos(2*pi*p(3)*t)) + 0.759);

It made me notice leasqr and nonlin_curvefit expect a function object
with x and p reversed inside @(_, _) - Seems pretty confusing! Right?

Also, is it important to use `.*` and not `*` in this context?

Are there perhaps some "rules of thumb" you'd recommend to remember when
using these fitting functions?

Regards,
Doron.


Reply | Threaded
Open this post in threaded view
|

Re: What to give as "real column vector of initial parameters" to nonlin_curvefit?

Dmitri A. Sergatskov


On Fri, Jun 12, 2020 at 2:17 PM Doron Behar <[hidden email]> wrote:


What do you mean by similar to each other?

I hate typing and it is hard to explain in a few words.
Non-linear fitting is an art...
In your example
M*sin(W*t+phi) vs A*sin(W*t) + B*cos(W*t)

Parameters A and B are more similar than M and phi.
The change in function values wrt A and B are similar.
The change in function values wrt M and phi is vastly different
(one is monotonic, another is periodic). Generally speaking you want your
function of parameters value as linear as possible.

Dmitri.
--