前言
curve_fit是使用非线性最小二乘法将函数f进行拟合,寻找到最优曲线.
Scipy是一个用于数学、科学、工程领域的常用软件包,可以处理插值、积分、优化、图像处理、常微分方程数值解的求解、信号处理等问题。它用于有效计算Numpy矩阵,使Numpy和Scipy协同工作,高效解决问题。
scipy.optimize
中有curve_fit
方法可以拟合自定义的曲线,如指数函数拟合,幂指函数拟合和多项式拟合
语法:
scipy.optimize.curve_fit(f,xdata,ydata,p0=None,sigma=None,absolute_sigma=False,check_finite=True,bounds=(-inf,inf),method=None,jac=None,**kwargs)
f:
函数形式xdata:
自变量 x,一般为数组或者向量ydata:
因变量 y,一般为一维数组p0:
参数的初始猜测(长度为N)。如果没有,那么初始值将全部为1(如果可以用自省法确定函数的参数数,否则将引发ValueError)。bounds:
参数的范围设置method:
用于优化的方法。更多细节见最小二乘法。对于无约束的问题,默认为’lm’
,如果提供了约束,则为’trf’
。当观测值的数量少于变量的数量时,‘lm’
方法将不起作用,在这种情况下使用’trf’
或’dogbox’
。
返回值解析
popt:
数组,参数的最佳值,以使的平方残差之和最小。拟合后的各项的系数通过popt[0], popt[1]...
获取pcov:
二维阵列,popt的估计协方差。对角线提供参数估计的方差。
例子
例子一:拟合直线
# 引用库函数
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize as op
# 需要拟合的数据组
x_group = np.array([3, 6.1, 9.1, 11.9, 14.9])
y_group = np.array([0.0221, 0.0491, 0.0711, 0.0971, 0.1238])
# 需要拟合的函数
def f_1(x, A, B):
return A * x + B
# 得到返回的A,B值
A, B = op.curve_fit(f_1, x_group, y_group)[0]
# 数据点与原先的进行画图比较
plt.scatter(x_group, y_group, marker='o',label='real')
x = np.arange(0, 15, 0.01)
y = A * x + B
plt.plot(x, y,color='red',label='curve_fit')
plt.legend()
plt.title('%.5fx%.5f=y' % (A, B))
plt.show()

例子2:官方例子
# 自定义函数,curve_fit支持自定义函数的形式进行拟合,这里定义的是指数函数的形式
# 包括自变量x和a,b,c三个参数
def func(x, a, b, c):
return a * np.exp(-b * x) + c
# 产生数据
xdata = np.linspace(0, 4, 50) # x从0到4取50个点
y = func(xdata, 2.5, 1.3, 0.5) # 在x取xdata,a,b,c分别取2.5, 1.3, 0.5条件下,运用自定义函数计算y的值
# 在y上产生一些扰动模拟真实数据
np.random.seed(1729)
# 产生均值为0,标准差为1,维度为xdata大小的正态分布随机抽样0.2倍的扰动
y_noise = 0.2 * np.random.normal(size=xdata.size)
ydata = y + y_noise
plt.plot(xdata, ydata, 'b-', label='data')
# 利用“真实”数据进行曲线拟合
popt, pcov = curve_fit(func, xdata, ydata) # 拟合方程,参数包括func,xdata,ydata,
# 有popt和pcov两个个参数,其中popt参数为a,b,c,pcov为拟合参数的协方差
# plot出拟合曲线,其中的y使用拟合方程和xdata求出
plt.plot(xdata, func(xdata, *popt), 'r-',
label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
# 如果参数本身有范围,则可以设置参数的范围,如 0 <= a <= 3,
# 0 <= b <= 1 and 0 <= c <= 0.5:
popt, pcov = curve_fit(func, xdata, ydata, bounds=(0, [3., 1., 0.5])) # bounds为限定a,b,c参数的范围
plt.plot(xdata, func(xdata, *popt), 'g--',
label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

References
[1] scipy.optimize.curve_fit函数用法解析
[2] scipy.optimize.curve_fit-曲线拟合
[3] 官方文档