Python - 曲线拟合产生不正确的拟合

Python - curve fit producing incorrect fit

我正在尝试拟合此数据分布的正弦波曲线,但由于某种原因,拟合不正确:

import matplotlib.pyplot as plt
import numpy as np
import scipy as sp
from scipy.optimize import curve_fit





#=======================
#====== Analysis =======
#=======================

# sine curve fit
def fit_Sin(t, A, b, C):
    return A* np.sin(t*b) + C

## The Data extraciton
t,y,y1 = np.loadtxt("new10_CoCore_5to20_BL.txt", unpack=True)

xdata = t
popt, pcov = curve_fit(fit_Sin, t, y)
print "A = %s , b = %s, C = %s" % (popt[0], popt[1], popt[2])



#=======================
#====== Plotting =======
#=======================

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)

ax1.plot(t, y, ".")
ax1.plot(t, fit_Sin(t, *popt))


plt.show()

其中这种拟合对数据进行了极度低估。任何想法为什么会这样?

此处提供的数据如下:https://www.dropbox.com/sh/72jnpkkk0jf3sjg/AAAb17JSPbqhQOWnI68xK7sMa?dl=0

知道为什么会产生这个吗?

如果您的频率猜测错误,则正弦波极难拟合。这是因为在数据中有足够数量的周期时,猜测将与一半的数据异相,而与一半的数据同相,即使是很小的频率误差。在这一点上,直线比不同频率的正弦波更适合。这就是傅立叶变换的工作方式。

我可以想到三种方法来充分估计频率以允许非线性最小二乘算法接管:

  1. 观察一下。在 GUI 甚至命令行中减去两个峰的 x-values。如果你有非常低的噪音数据,你可以很容易地自动化这个过程。
  2. 使用离散傅里叶变换。如果您的数据是一个分量的正弦波,第一个 non-constant 峰值将为您提供频率。我发现这需要一些额外的调整,因为采样频率通常不是正弦波频率的倍数。在这种情况下,对峰周围三个点(包括峰在内的三个点)进行抛物线拟合会有所帮助。
  3. 找出您的数据在何处与垂直偏移相交。这与 #1 类似,但对于相对 non-noisy 的数据更容易实现自动化。波长是一对交叉点之间距离的两倍。

使用#1,我可以清楚地看到你的波长是50。因此b的初始猜测应该是2*np.pi/50。另外,不要忘记添加相移参数以允许拟合水平滑动:A*sin(b*t + d) + C.

您需要通过 p0 参数将初始猜测传递给 curve_fit。一个好的眼球估计是 p0=(0.55, np.pi/25, 0.0, -np.pi/25*12.5)。您的数据中的相移似乎是向右四分之一周期,因此是 12.5。

我目前正在编写一种算法,用于用单个频率分量拟合嘈杂的正弦波,我将提交给 SciPy。我完成后会更新。