本文共 5725 字,大约阅读时间需要 19 分钟。
scipy官网对该方法介绍是: 最小化一组方程的平方和
x = arg min y ( ∑ ( ( f u n c ( y ) ) 2 , a x i s = 0 ) ) x =\arg \min\limits_{y}(\sum((func(y))^2,axis=0)) x=argymin(∑((func(y))2,axis=0)) 简单介绍一下leastsq的参数:scipy.optimize.leastsq(func,x0,args = (),Dfun = None,full_output = 0,col_deriv = 0,ftol = 1.49012e-08,xtol = 1.49012e-08,gtol = 0.0,maxfev = 0,epsfcn = None,factor = 100,diag = None)
# 参数:func: 所求平方和最小值的函数,一般都用于拟合时传入残差函数,当然也有其他用途,比如求函数的最小等等x0: ndarray 一般为参数的初始值args: 元组,可选,可以传入(x, y)其中x,y都是数组,作为求解传入的参数
# 返回值leastsq的返回值是一个元组,里面包含了很多信息,如果是用作拟合的话,返回值的索引值为0的元素即为我们所求函数参数
有兴趣的读者可以自己看看官网介绍:
比如求 2 ( x − 3 ) 2 + 1 2(x-3)^2+1 2(x−3)2+1的最小值:
from scipy.optimize import leastsqdef func(x): return 2*(x-3)**2+1print(leastsq(func, 0)) # 0为x的初始值,初始值可以由自己定,改成任意一个随机值都可以
结果为:
(array([2.99999999]), 1)
当 x = 2.99999999 ≈ 3 x=2.99999999\approx3 x=2.99999999≈3时,函数最小值为1
为了和上一篇文章形成一个比较,我们这里也进行1-5阶的多项式拟合。
from scipy.optimize import leastsq# 拟合数据集x = [4, 8, 10, 12, 25, 32, 43, 58, 63, 69, 79]y = [20, 33, 50, 56, 42, 31, 33, 46, 65, 75, 78]x_arr = np.array(x)y_arr = np.array(y)def fitting_func(p, x): """ 获得拟合的目标数据数组 :param p: array[int] 多项式各项从高到低的项的系数数组 :param x: array[int] 自变量数组 :return: array[int] 拟合得到的结果数组 """ f = np.poly1d(p) # 获得拟合后得到的多项式 return f(x) # 将自变量数组带入多项式计算得到拟合所得的目标数组如果想要拟合的是其他函数,那只需要将
f = np.poly1d(p)
改为你想要拟合的函数关系式即可。def error_func(p, x, y):"""计算残差:param p: array[int] 多项式各项从高到低的项的系数数组:param x: array[int] 自变量数组:param y: array[int] 原始目标数组(因变量):return: 拟合得到的结果和原始目标的差值"""err = fitting_func(p, x) - yreturn err残差有很多计算方法,这里因为leastsq方法本身就会将我们的残差函数平方,所以这里我们直接相减,在经过leastsq方法的平方后就变为了最小二乘法了。
def n_poly(n, x, y): """ n 次多项式拟合函数 :param n: 多项式的项数(包括常数项),比如n=3的话最高次项为2次项 :return: 最终得到的系数数组 """ p_init = np.random.randn(n) # 生成 n个随机数,作为各项系数的初始值,用于迭代修正 parameters = leastsq(error_func, p_init, args=(np.array(x), np.array(y))) # 三个参数:误差函数、函数参数列表、数据点 return parameters[0] # leastsq返回的是一个元组,元组的第一个元素时多项式系数数组[wn、...、w2、w1、w0]
para_2 = n_poly(2, x_arr, y_arr) # 一阶print("系数为:", para_2)print("多项式为:", np.poly1d(para_2))print("拟合值为:", fitting_func(para_2, x_arr))print("拟合优度为:", goodness_of_fit(fitting_func(para_2, x_arr), y_arr))二、三、四、五阶:
para_3 = n_poly(3, x_arr, y_arr) # 二阶para_4 = n_poly(4, x_arr, y_arr) # 三阶para_5 = n_poly(5, x_arr, y_arr) # 四阶para_6 = n_poly(6, x_arr, y_arr) # 五阶这里解释一下为什么一阶传入n=2,二阶传入n=3…。因为这里的n表示的不是多项式的阶数,而是表示多项式的项数,比如二阶的多项式有 x 2 、 x x^2、x x2、x还有常数项三项,所以传入的n=3。
figure = plt.figure(figsize=(8,6)) plt.plot(x_arr, fitting_func(para_2, x_arr), color="#72CD28", label='一阶拟合曲线') plt.plot(x_arr, fitting_func(para_3, x_arr), color="#EBBD43", label='二阶拟合曲线') plt.plot(x_arr, fitting_func(para_4, x_arr), color="#50BFFB", label='三阶拟合曲线') plt.plot(x_arr, fitting_func(para_5, x_arr), color="gold", label='四阶拟合曲线') plt.plot(x_arr, fitting_func(para_6, x_arr), color="#13EAC9", label='五阶拟合曲线') plt.scatter(x, y, color='#50BFFB', marker="p", label='原始数据') plt.title("leastsq拟合", fontsize=13) plt.xlabel('x', fontsize=13) plt.ylabel('y', fontsize=13) plt.legend(loc=4, fontsize=11) # 指定legend的位置右下角 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 plt.show()这里我只输出了一阶的拟合结果,结果为:
系数为: [ 0.5000123 29.77227653]多项式为: 0.5 x + 29.77拟合值为: [31.77232574 33.77237495 34.77239955 35.77242415 42.27258408 45.77267019 51.27280552 58.77299004 61.27305155 64.27312537 69.27324839]拟合优度为: 0.5207874477394239结果图为:
全部代码为:
from scipy.optimize import leastsq# 拟合数据集x = [4, 8, 10, 12, 25, 32, 43, 58, 63, 69, 79]y = [20, 33, 50, 56, 42, 31, 33, 46, 65, 75, 78]x_arr = np.array(x)y_arr = np.array(y)def fitting_func(p, x): """ 获得拟合的目标数据数组 :param p: array[int] 多项式各项从高到低的项的系数数组 :param x: array[int] 自变量数组 :return: array[int] 拟合得到的结果数组 """ f = np.poly1d(p) # 获得拟合后得到的多项式 return f(x) # 将自变量数组带入多项式计算得到拟合所得的目标数组def error_func(p, x, y): """ 计算残差 :param p: array[int] 多项式各项从高到低的项的系数数组 :param x: array[int] 自变量数组 :param y: array[int] 原始目标数组(因变量) :return: 拟合得到的结果和原始目标的差值 """ err = fitting_func(p, x) - y return errdef n_poly(n, x, y): """ n 次多项式拟合函数 :param n: 多项式的项数(包括常数项),比如n=3的话最高次项为2次项 :return: 最终得到的系数数组 """ p_init = np.random.randn(n) # 生成 n个随机数,作为各项系数的初始值,用于迭代修正 parameters = leastsq(error_func, p_init, args=(np.array(x), np.array(y))) # 三个参数:误差函数、函数参数列表、数据点 return parameters[0] # leastsq返回的是一个元组,元组的第一个元素时多项式系数数组[wn、...、w2、w1、w0]para_2 = n_poly(2, x_arr, y_arr) # 一阶print("系数为:", para_2)print("多项式为:", np.poly1d(para_2))print("拟合值为:", fitting_func(para_2, x_arr))print("拟合优度为:", goodness_of_fit(fitting_func(para_2, x_arr), y_arr))para_3 = n_poly(3, x_arr, y_arr) # 二阶para_4 = n_poly(4, x_arr, y_arr) # 三阶para_5 = n_poly(5, x_arr, y_arr) # 四阶para_6 = n_poly(6, x_arr, y_arr) # 五阶figure2 = plt.figure(figsize=(8,6))plt.plot(x_arr, fitting_func(para_2, x_arr), color="#72CD28", label='一阶拟合曲线')plt.plot(x_arr, fitting_func(para_3, x_arr), color="#EBBD43", label='二阶拟合曲线')plt.plot(x_arr, fitting_func(para_4, x_arr), color="#50BFFB", label='三阶拟合曲线')plt.plot(x_arr, fitting_func(para_5, x_arr), color="gold", label='四阶拟合曲线')plt.plot(x_arr, fitting_func(para_6, x_arr), color="#13EAC9", label='五阶拟合曲线')plt.scatter(x_arr, y_arr, color='#50BFFB', marker="p", label='原始数据')plt.title("leastsq拟合", fontsize=13)plt.xlabel('x', fontsize=13)plt.ylabel('y', fontsize=13)plt.legend(loc=4, fontsize=11) # 指定legend的位置右下角plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号plt.show()
转载地址:http://xfiwi.baihongyu.com/