正弦曲线拟合问题:振幅和频率太低

Problems with sinusoidal curve fitting: amplitude and frequency come out too low

我有一些时间序列数据,它对应于图像中的黑线(它是滚动平均值)。我试图用正弦曲线拟合它但没有成功;浅蓝色,几乎是直线是当前结果。 (深蓝色的是多项式拟合,暂且忽略)

我试的是这个。我从 here.

得到了这个函数的想法
def objective(x, a, b, c, d):
    return a * np.sin(b - x) + c * x**2 + d

[..]

from scipy import optimize

X = X.ravel() # 1D array of ordinal dates
y = y.ravel() # 1D array of temperature values

# Curvefit with the objective function.
params, _ = optimize.curve_fit(objective, X, y)

# Plot the curvefit
plt.plot(X_extended, objective(
    X, params[0], params[1], params[2], params[3]))

即使我添加频率非常低或幅度非常高的猜测,也几乎没有任何变化。

如有任何想法,我们将不胜感激。如有必要,我可以尝试在其他地方重现该问题。


应用答案中给出的 p0 值和函数,图表现在如下所示:

谢谢!

没有数据可以测试,很难准确判断。但是,一个很好的猜测是您的起始参数已关闭,然后广义最小二乘法拟合可能(很容易)失败。您甚至没有给 curve_fit 一组初始参数,因此 abcd 的初始启动都将设置为1.

处理 正弦拟合,对于你的振幅 a,你可能需要 7 左右的值,对于偏移量 d,大约 27。b 更难猜,所以最初可以保留为 0(或 1)。

但是,方程的二次部分会把事情弄得一团糟:x 值很大,所以它会变化得非常快,或者更确切地说,c 应该非常接近于零(关闭,因为在非常小的情况下,1/x^2,所以说 ~ 1e-12,以抵消大二次变化的影响。任何这样小的数字也会有拟合问题:标准化你的公式/参数(有序 1) 事先总是一个好主意。

事实上,我不明白为什么你的函数中有二次方。也许是底层模型需要这样做,但该图本身没有显示任何二次行为的迹象。我会删除它。

最后,虽然您有 x 偏移 b,但您没有周期参数。结果,它会固定在 2π,但事实并非如此。这将是拟合数据的最大障碍,仅次于方程的二次部分。周期看起来大约是 300(或一年?),或大约 50 * 2π。

所以,尝试使用以下函数:

def objective(x, a, b, c, d):
    return a * np.sin(b - c*x/50) + d

起始参数为,非常粗略:

p0 = [7, 0, 1, 27]

看看你得到了什么。

(如果您想知道公式中的 50:在这些数量级上它并不是真正必要的,但它作为将 c 归一化为 1 阶的示例。您可以这样d 相同,将其替​​换为 10*d,然后将其初始猜测设置为 3。或者,如果这样做,您现在可以完全省略 p0,所有参数猜测为 1 .)