Numpy 使用Scipy curve_fit进行分段函数拟合
在本文中,我们将介绍使用Numpy和Scipy库进行分段函数拟合的方法。分段函数拟合是一种数据拟合技术,使用分段函数可以更好地逼近非连续、不光滑或其他具有显著特征的数据集。我们将使用Scipy中的curve_fit函数来拟合具有斜率或曲率不连续变化的分段函数。
阅读更多:Numpy 教程
什么是分段函数?
分段函数是指在不同区间内使用不同的函数表达式的函数。这些函数表达式被称为分段函数的“分段”。例如,一个分段线性函数可以被写成如下形式:
f(x)={a1x+b1a2x+b2x≤x1x>x1
其中,a1,b1,a2,b2是要拟合的系数,x1是分段点。
分段函数可以更好地逼近一些非线性或不连续的数据。例如下图中的脉冲信号就可以用分段线性函数进行拟合。
使用curve_fit拟合分段函数
使用Python进行分段函数拟合的常用工具是Scipy库中的curve_fit函数。该函数需要传入一个自定义的拟合函数和需要拟合的数据。
下面的例子中,我们将使用以下分段二次函数来拟合一组带有噪声的数据:
f(x)=⎩⎨⎧a1x2+b1x+c1a2x2+b2x+c2a3x2+b3x+c3x≤x1x≤x2x>x2
由于该函数具有三个不同区间,我们需要传入三个不同区间的系数。
import numpy as np
from scipy.optimize import curve_fit
def piecewise_quad(x, x0, x1, a0, b0, c0, a1, b1, c1, a2, b2, c2):
return np.piecewise(x, [x <= x0, (x > x0) & (x <= x1), x > x1],
[lambda x:a0*x**2 + b0*x + c0,
lambda x:a1*x**2 + b1*x + c1,
lambda x:a2*x**2 + b2*x + c2])
xdata = np.linspace(0, 2.5, 200)
y = piecewise_quad(xdata, 0.8, 1.6, 2.5, -6, 5, 4, -6, 1, 4, 2, 3)
np.random.seed(2021)
y_noise = 0.2 * np.random.normal(size=xdata.size)
ydata = y + y_noise
popt, pcov = curve_fit(piecewise_quad, xdata, ydata)
import matplotlib.pyplot as plt
plt.figure()
plt.plot(xdata, ydata, 'b-', label='data')
plt.plot(xdata, piecewise_quad(xdata, *popt), 'r-', label='fit')
plt.legend()
plt.show()
拟合过程中,我们需要传入xdata作为自变量,ydata作为因变量。最后,我们使用curve_fit函数进行拟合。拟合结果存储在popt和pcov两个变量中,其中popt是拟合函数的系数,pcov是系数的协方差矩阵。
总结
使用Numpy和Scipy库中的curve_fit函数可以方便地拟合分段函数,能够更好地逼近非线性或不连续的数据。在拟合过程中,需要注意传入自定义的分段函数以及每个分段的系数。对于复杂的分段函数,代码可能会有些冗长,但是只需要针对具体问题进行修改即可。