使用Scipy将三角函数拟合到数据上

3
我正在尝试使用 scipy.optimize.curve_fit 来拟合一些数据。我已经 阅读了文档,并且看过 这篇StackOverflow文章,但是两者都没有回答我的问题。
我有一些简单的二维数据,大致呈三角函数形状。我希望使用 scipy 中的通用三角函数来拟合它。
我的方法如下:
from __future__ import division
import numpy as np
from scipy.optimize import curve_fit



#Load the data
data = np.loadtxt('example_data.txt')
t = data[:,0]
y = data[:,1]


#define the function to fit
def func_cos(t,A,omega,dphi,C):
    # A is the amplitude, omega the frequency, dphi and C the horizontal/vertical shifts
    return A*np.cos(omega*t + dphi) + C

#do a scipy fit
popt, pcov = curve_fit(func_cos, t,y)

#Plot fit data and original data
fig = plt.figure(figsize=(14,10))
ax1 = plt.subplot2grid((1,1), (0,0))

ax1.plot(t,y)
ax1.plot(t,func_cos(t,*popt))

这将输出:

enter image description here

蓝色代表数据,橙色代表拟合结果。显然我做错了什么。有什么指点吗?


请上传名为 'example_data.txt' 的样本数据,否则很难进行复制。 - a_guest
1
它可以通过 some_data 超链接访问。 - user1887919
1个回答

5
如果没有为参数提供初始猜测值,则假定每个参数的值为1。从文档中可以看到:

p0:array_like,可选 参数的初始猜测(长度为N)。如果为None,则将所有初始值设置为1(如果可以使用内省确定函数的参数数量,否则会引发ValueError)。

因为您的数据具有非常大的x值和非常小的y值,所以初始猜测值1远离实际解决方案,因此优化器不会收敛。您可以通过提供适当的初始参数值来帮助优化器,这些值可以从数据中推测/近似得出:
幅度:A =(y.max() - y.min())/ 2 偏移量:C =(y.max()+ y.min())/ 2 频率:在这里,我们可以通过将连续的y值相乘并检查哪些产品小于零来估计零交叉的数量。除以总x范围即可得出频率,并且为了以单位pi的形式获得该数字,我们可以将该数字乘以piy_shifted = y-offset; oemga = np.pi * np.sum(y_shifted[:-1] * y_shifted[1:] < 0) / (t.max() - t.min()) 相移:可以设置为零,dphi = 0 所以总结一下,可以使用以下初始参数猜测值:
offset = (y.max() + y.min()) / 2
y_shifted = y - offset
p0 = (
    (y.max() - y.min()) / 2,
    np.pi * np.sum(y_shifted[:-1] * y_shifted[1:] < 0) / (t.max() - t.min()),
    0,
    offset
)
popt, pcov = curve_fit(func_cos, t, y, p0=p0)

这给了我以下拟合函数:

拟合曲线


太好了,谢谢!是我自己的问题还是感觉适合有点垂直位移? - user1887919
2
@user1887919 看起来是这个版本最小化了两个函数之间的差异。在峰值周围,拟合函数似乎被移动了,但这样做的好处是斜率非常一致。考虑到峰值只占 x 范围的一小部分,而斜率占据了大部分,所以这种方式可以最小化差异。您可以尝试将偏移量的初始猜测设为 "振幅 + 偏移量",但它仍会收敛到这个解决方案。 - a_guest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接