正弦曲线拟合问题:振幅和频率太低
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
一组初始参数,因此 a
、b
、c
和 d
的初始启动都将设置为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 .)
我有一些时间序列数据,它对应于图像中的黑线(它是滚动平均值)。我试图用正弦曲线拟合它但没有成功;浅蓝色,几乎是直线是当前结果。 (深蓝色的是多项式拟合,暂且忽略)
我试的是这个。我从 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
一组初始参数,因此 a
、b
、c
和 d
的初始启动都将设置为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 .)