2

I'm using the Apache Commons Math package and I've got the following Sine Wave...

  0.90, 0.85, 0.80, 0.83, 0.89
  0.90, 0.85, 0.80, 0.83, 0.89
  0.90, 0.85, 0.80, 0.83, 0.89
  0.90, 0.85, 0.80, 0.83, 0.89

from the above data you can see that the wave has the following attributes...

  • Amplitude = .05
  • Phase = 0
  • Frequency = 5

However, when I add my sine wave to a HarmonicFitter like so...

HarmonicFitter fitter = new HarmonicFitter(new LevenbergMarquardtOptimizer());

fitter.addObservedPoint(0, 0.90);
fitter.addObservedPoint(1, 0.85);
fitter.addObservedPoint(2, 0.80);
fitter.addObservedPoint(3, 0.83);
fitter.addObservedPoint(4, 0.89);

fitter.addObservedPoint(5, 0.90);
fitter.addObservedPoint(6, 0.85);
fitter.addObservedPoint(7, 0.80);
fitter.addObservedPoint(8, 0.83);
fitter.addObservedPoint(9, 0.89);

fitter.addObservedPoint(10, 0.90);
fitter.addObservedPoint(11, 0.85);
fitter.addObservedPoint(12, 0.80);
fitter.addObservedPoint(13, 0.83);
fitter.addObservedPoint(14, 0.89);

fitter.addObservedPoint(15, 0.90);
fitter.addObservedPoint(16, 0.85);
fitter.addObservedPoint(17, 0.80);
fitter.addObservedPoint(18, 0.83);
fitter.addObservedPoint(19, 0.89);

double[] vals = fitter.fit();

return vals;

The values returned are more like...

Amplitude: 5.19813329138371
Frequency: 4.69209750375546E-5
Phase: 1.405312649084833

Why has the curve fitting resulted in such drastically different attributes for a sinewave with 4 identical frequencies?

Skizit
  • 43,506
  • 91
  • 209
  • 269
  • Could it be simply because your data points are not precise enough? – LordOfThePigs Jan 06 '14 at 14:06
  • Are you sure that you print these values correctly? Your amplitude seems to have the value of frequency, frequency of phase and so on – lejlot Jan 06 '14 at 14:07
  • @lejlot I would think so, Amplitude = vals[0] according to the Javadoc. – Skizit Jan 06 '14 at 14:08
  • 2
    +1; this is the most complete, well formatted, grammatically correct question I have seen in a few days. – The Guy with The Hat Jan 06 '14 at 14:08
  • @LordOfThePigs I'm not quite sure what you mean by your comment? – Skizit Jan 06 '14 at 14:11
  • 2
    Also, I find it weird that your observed points are periodical on a cycle of 5, given that you say the frequency is 5, shouldn't the periodicity of your samples be PI/5? – LordOfThePigs Jan 06 '14 at 14:12
  • 1
    What you have is not a sine wave, it is a superposition of a sine wave on a constant, where the constant is much more dominant. Is your math API expected to compensate for that? – Marko Topolnik Jan 06 '14 at 14:12
  • @Skizit: you give each of you datapoint to 2 digits precision. Is this really the exact value at that point, or are there actually more decimals? Couldn't it be that the fitter finds a much weirder looking sine that passes exactly through the points you specified (with 2 digits decimals) instead of the points you intended to specify (which actually have more decimals than that). – LordOfThePigs Jan 06 '14 at 14:14
  • @MarkoTopolnik: Seems the fitter tries to fit the following function: φ: f (t) = a cos (ω t + φ) So that would be no. – LordOfThePigs Jan 06 '14 at 14:15
  • 1
    @LordOfThePigs Well, that is surely the most prominent issue, then. – Marko Topolnik Jan 06 '14 at 14:16

2 Answers2

2

You seem to be mixing up order of the output and not mapping it correctly to labels (fitreturns an array).

The values that you obtained really reflect your inputs:

Try to draw your values on paper and put a sinewave on them -- your assertions of 0.5 for amplitude and 5 for frequency are incorrect. The phase is Ok, which is confirmed by 4.69e-5. Your frequency is well above 5. The amplitude of 0.5 is what you want, not what the data shows, 1.4: because there are no points on the downslope of the sine the optimiser actuyally thinks that points 0.8, 0.83 and 0.89 all belong to the upslope of the sinewave with a much larger amplitude -- this reduces the error.

All in all, you are overfitting by trying to fit 3 values with essentially 5 points.

Oleg Sklyar
  • 9,834
  • 6
  • 39
  • 62
2

@Marko Topolnik has the problem. The Fitter is expecting a simple harmonic (i.e., a single cosine or sine), which has mean zero. So subtract 0.854 (the mean) from everything, and add that constant back to your resulting sine wave.

As things are, the tiny frequency is giving a flat sine wave, so the other numbers are irrelevant. Try plotting everything (including the resulting function).


Edit: Here are two plots. The first has your points along with three functions: your desired y=.05*cos(2πx/5), the same function plus .0854 (it appears your phase won't be zero), and the package's best fit function: picture of best fits But you can't distinguish the package's best fit function until you zoom way out to a window of [-1e5,1e5]x[-8,8]: same picture, dramatically scaled out horizontally This also means that the package's best fit function is wildly unstable. A small change in your points will cause a large change in the output.

Teepeemm
  • 4,331
  • 5
  • 35
  • 58