方法
- 获取实验数据x, y
- 利用
scipy.optimize.curve_fit()
进行三角函数拟合。- curve_fit本质是提供一个目标函数和初值,通过优化算法去搜索出最佳的拟合参数。
- 在这里目标函数定义为: a 0 sin ( a 1 x + a 2 ) + a 3 a_0\sin(a_1x+a_2)+a_3 a0sin(a1x+a2)+a3
- 需要给出一个初值[a0, a1, a2, a3]。主要是频率参数a1,可通过傅里叶变换fft得到一个初值。
注:对于大部分简单的数据,scipy.optimize.curve_fit()
即使不给其提供初值,也能较好的拟合出曲线。
- 得到拟合出的系数,进行后续的数据处理。比如周期,频率,峰峰值等
实例
已知一组sin/cos型数据,要求拟合出该曲线。
注:本例中给出一组估算的初值进行curve_fit拟合。由于数据简单,不提供初值其实也能拟合出来。
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as optimize
pi = np.pi
# 模拟生成一组实验数据
x = np.arange(0, 10, 0.2)
y = -0.5 * np.cos(1.1 * x) + 0.5
noise = np.random.uniform(0, 0.1, len(x))
y += noise
fig, ax = plt.subplots()
ax.plot(x, y, 'b--')
def target_func(x, a0, a1, a2, a3):
return a0 * np.sin(a1 * x + a2) + a3
# 拟合sin曲线
fs = np.fft.fftfreq(len(x), x[1] - x[0])
Y = abs(np.fft.fft(y))
freq = abs(fs[np.argmax(Y[1:]) + 1])
a0 = max(y) - min(y)
a1 = 2 * pi * freq
a2 = 0
a3 = np.mean(y)
p0 = [a0, a1, a2, a3]
para, _ = optimize.curve_fit(target_func, x, y, p0=p0)
print(para)
y_fit = [target_func(a, *para) for a in x]
ax.plot(x, y_fit, 'g')
plt.show()