import numpy as np
from scipy.optimize import curve_fit
import pylab as plt
N = 1000 # number of data points
t = np.linspace(0, 4*np.pi, N)
data = 3.0*np.sin(t+0.001) + 0.5 + np.random.randn(N) # create artificial data with noise
guess_freq = 1
guess_amplitude = 3*np.std(data)/(2**0.5)
guess_phase = 0
guess_offset = np.mean(data)
p0=[guess_freq, guess_amplitude,
guess_phase, guess_offset]
# create the function we want to fit
def my_sin(x, freq, amplitude, phase, offset):
return np.sin(x * freq + phase) * amplitude + offset
# now do the fit
fit = curve_fit(my_sin, t, data, p0=p0)
# we'll use this to plot our first estimate. This might already be good enough for you
data_first_guess = my_sin(t, *p0)
# recreate the fitted curve using the optimized parameters
data_fit = my_sin(t, *fit[0])
plt.plot(data, '.')
plt.plot(data_fit, label='after fitting')
plt.plot(data_first_guess, label='first guess')
plt.legend()
plt.show()
import numpy as np
from scipy.optimize import leastsq
import pylab as plt
N = 1000 # number of data points
t = np.linspace(0, 4*np.pi, N)
f = 1.15247 # Optional!! Advised not to use
data = 3.0*np.sin(f*t+0.001) + 0.5 + np.random.randn(N) # create artificial data with noise
guess_mean = np.mean(data)
guess_std = 3*np.std(data)/(2**0.5)/(2**0.5)
guess_phase = 0
guess_freq = 1
guess_amp = 1
# we'll use this to plot our first estimate. This might already be good enough for you
data_first_guess = guess_std*np.sin(t+guess_phase) + guess_mean
# Define the function to optimize, in this case, we want to minimize the difference
# between the actual data and our "guessed" parameters
optimize_func = lambda x: x[0]*np.sin(x[1]*t+x[2]) + x[3] - data
est_amp, est_freq, est_phase, est_mean = leastsq(optimize_func, [guess_amp, guess_freq, guess_phase, guess_mean])[0]
# recreate the fitted curve using the optimized parameters
data_fit = est_amp*np.sin(est_freq*t+est_phase) + est_mean
# recreate the fitted curve using the optimized parameters
fine_t = np.arange(0,max(t),0.1)
data_fit=est_amp*np.sin(est_freq*fine_t+est_phase)+est_mean
plt.plot(t, data, '.')
plt.plot(t, data_first_guess, label='first guess')
plt.plot(fine_t, data_fit, label='after fitting')
plt.legend()
plt.show()
对我们来说更友好的是函数curvefit。这里有一个例子:
这是一个无参数拟合函数
fit_sin()
,不需要手动猜测频率:初始频率猜测由频域中使用FFT的峰值频率给出。假设只有一个主频(零频率峰值除外),则拟合结果几乎完美
即使在高噪声条件下,效果也很好:
您可以使用scipy中的least-square optimization函数将任意函数适配到另一个函数。在拟合正弦函数的情况下,要拟合的3个参数是偏移量('a')、振幅('b')和相位('c')
只要您对参数提供合理的初步猜测,优化应该会很好地收敛。幸运的是,对于正弦函数,其中2个的初步估计很容易:可以通过RMS(3*标准偏差/sqrt(2))获取数据和振幅的平均值来估计偏移量
注:作为以后的编辑,还添加了频率拟合。这不太好用(可能导致极不合身)。因此,根据您的判断,我建议不要使用频率拟合,除非频率误差小于百分之几
这将导致以下代码:
编辑:我假设你知道正弦波的周期数。如果你不这样做,那就更难适应了。您可以通过手动绘图尝试猜测周期数,并尝试将其作为第六个参数进行优化
相关问题 更多 >
编程相关推荐