• 最小二乘拟合


    来自:某小皮

    最优化函数库Optimization

    优化是找到最小值或等式的数值解的问题。scipy.optimization子模块提供函数最小值,曲线拟合和寻找等式的根的有用算法。

    最小二乘拟合

    假设有一组实验数据(xi, yi),事先知道它们之间应该满足某函数关系yi = f(xi),通过这些已知的信息,需要确定函数f的一些参数。例如,如果函数f是线性函数f(x) = kx + b,那么参数k和b就是需要确定的值。

    如果用p表示函数中需要确定的参数,那么目标就是找到一组p,使下面的函数s的值最小:

    这种算法被称作最小二乘拟合(Least-square fitting)。

    使用leastsq()进行最小二乘拟合计算。leastsq()只需要将计算误差的函数待确定参数的初始值传递给它即可。

    leastsq()函数传入误差计算函数和初始值,该初始值将作为误差计算函数的第一个参数传入;

    计算的结果r是一个包含两个元素的元组,第一个元素是一个数组,表示拟合后的参数k,b;第二个元素如果等于1,2,3,4中的其中一个整数,则拟合成功,否则将返回mesg。

    leastsq函数:

    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=0.0, factor=100, diag=None, warning=True) 

    一般我们只要指定前三个参数:

    • func 是我们自己定义的一个计算误差的函数,
    • x0 是计算的初始参数值
    • args 是指定func的其他参数

    注意:传入leastsq函数的参数可以有多个,但必须把参数的初始值p0和其它参数分开放。其它参数应打包到args中。

    最小二乘拟合示例:

    使用最小二乘对带噪声的正弦波数据进行拟合:

    拟合得到的参数虽然和实际的参数有可能完全不同,但是由于正弦函数具有周期性,实际上拟合的结果和实际的函数是一致的。

    import numpy as np
    from scipy.optimize import leastsq
    
    #待拟合的函数,x是变量,p是参数
    def fun(x, p):
        a, b = p
        return a*x + b
    
    #计算真实数据和拟合数据之间的误差,p是待拟合的参数,x和y分别是对应的真实数据
    def residuals(p, x, y):
        return fun(x, p) - y
    
    #一组真实数据,在a=2, b=1的情况下得出
    x1 = np.array([1, 2, 3, 4, 5, 6], dtype=float)
    y1 = np.array([3, 5, 7, 9, 11, 13], dtype=float)
    
    #调用拟合函数,第一个参数是需要拟合的差值函数,第二个是拟合初始值,第三个是传入差值函数的其他参数
    r = leastsq(residuals, [1, 1], args=(x1, y1))
    
    #打印结果,r[0]存储的是拟合的结果,r[1]、r[2]代表其他信息
    print(r[0])

    运行结果:[ 2. 1.]

     1 import numpy as np
     2 import pylab as pl
     3 from scipy.optimize import leastsq
     4 
     5 def func(x, p):
     6     # 数据拟合所用的函数:A*sin(2*pi*k*x + theta)
     7     A, k, theta = p
     8     return A*np.sin(2*np.pi*k*x + theta)
     9 def residuals(p, y, x):
    10     # 真实数据x, y和拟合数据之间的误差,p为待拟合参数
    11     return y - func(x, p)
    12 
    13 x = np.linspace(-2*np.pi, 0, 100)
    14 
    15 A, k, theta = 10, 0.34, np.pi/6        # 真实数据的函数参数
    16 y0 = func(x, [A, k, theta])            # 真实数据
    17 y1 = y0 + 2 * np.random.randn(len(x))  # 加入噪声之后的实验数据
    18 
    19 p0 = [7, 0.2, 0]    # 第一次猜测的函数拟合参数
    20 
    21 # 调用leastsq进行数据拟合,
    22 # residuals为我们自己定义的需要拟合的差值函数
    23 # p0为拟合初始值,
    24 # args为传入差值函数的其他参数
    25 plsq = leastsq(residuals, p0, args = (y1, x))
    26 
    27 """
    28 除了初始值之外,还调用了args参数,用于指定residuals中使用到的其他参数(直线拟合是直接使用X,Y的全局变量),
    29 同样也返回一个元组,第一个元素为拟合后的参数数组;
    30 这里将(y1, x)传递给args参数。Leastsq()会将这两个额外的参数传递给residuals()。
    31 因此residuals()有三个参数,p是正弦函数的参数,y和x是表示真实数据的数组。
    32 """
    33 
    34 print(u"真实参数:", [A, k, theta])
    35 print(u"拟合参数", plsq[0])    # 实验数据拟合后的参数
    36 pl.plot(x, y0, label = u"真实数据")
    37 pl.plot(x, y1, label = u"带噪声的数据")
    38 pl.plot(x, func(x, plsq[0]), label = u"拟合数据")
    39 pl.legend()
    40 pl.show()

     运行结果:

  • 相关阅读:
    [代码]codeforces 150c Smart Cheater
    [存档]Young Tableau
    [转载][毁童年]种太阳
    [转载]教练,我也想再要一个同桌
    静夜
    CodeProject每日精选: Applications
    设计模式 装饰模式(Decorator) 精选经验合集
    槟榔味儿办公室
    盗不盗非常盗
    月末之周末
  • 原文地址:https://www.cnblogs.com/keye/p/8690183.html
Copyright © 2020-2023  润新知