Sine Wave Curve Fitting in Java

妖精的绣舞 提交于 2019-12-24 13:14:35

问题


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?


回答1:


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.




回答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:

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]:

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.

来源:https://stackoverflow.com/questions/20951640/sine-wave-curve-fitting-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!