如何在Python中使用scipy.optimize中的leastsq函数对数据集x和y进行直线和二次曲线拟合

12

我如何使用scipy.optimize中的leastsq函数将一条直线和二次曲线拟合到下面的数据集中?我知道如何使用polyfit来完成,但我需要使用leastsq函数。

以下是x和y数据集:

x: 1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7

y: 6.008,15.722,27.130,33.772,5.257,9.549,11.098,28.828

有人能帮我吗?


4
请将您的尝试展示出来。 - aIKid
3
欢迎来到 [SO]! 人们往往更愿意回答那些提出了具体问题并表现出提问者努力的问题。这里有一个关于 leastsq 的不错的教程,你可以尝试按照其中的步骤进行操作,如果遇到困难,请回来编辑这个问题并解释你尝试了哪些方法以及在哪里感到困惑。 - askewchan
4
还有一些示例可以在http://wiki.scipy.org/Cookbook/FittingData和http://wiki.scipy.org/Cookbook/Least_Squares_Circle找到,它们使用`leastsq`进行拟合。 - Warren Weckesser
3个回答

22

leastsq() 方法通过寻找最小化误差函数(yExperimental和yFit之间的差异)的一组参数来进行优化。我使用元组传递参数以及用于线性和二次拟合的Lambda函数。

leastsq()从第一个猜测值(初始参数元组)开始尝试最小化误差函数。如果leastsq()成功,它将返回最适合数据的参数列表。(我打印出来查看)。希望这样可以奏效。 最好的问候

from scipy.optimize import leastsq
import numpy as np
import matplotlib.pyplot as plt


def main():
   # data provided
   x=np.array([1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7])
   y=np.array([6.008,15.722,27.130,33.772,5.257,9.549,11.098,28.828])
   # here, create lambda functions for Line, Quadratic fit
   # tpl is a tuple that contains the parameters of the fit
   funcLine=lambda tpl,x : tpl[0]*x+tpl[1]
   funcQuad=lambda tpl,x : tpl[0]*x**2+tpl[1]*x+tpl[2]
   # func is going to be a placeholder for funcLine,funcQuad or whatever 
   # function we would like to fit
   func=funcLine
   # ErrorFunc is the diference between the func and the y "experimental" data
   ErrorFunc=lambda tpl,x,y: func(tpl,x)-y
   #tplInitial contains the "first guess" of the parameters 
   tplInitial1=(1.0,2.0)
   # leastsq finds the set of parameters in the tuple tpl that minimizes
   # ErrorFunc=yfit-yExperimental
   tplFinal1,success=leastsq(ErrorFunc,tplInitial1[:],args=(x,y))
   print " linear fit ",tplFinal1
   xx1=np.linspace(x.min(),x.max(),50)
   yy1=func(tplFinal1,xx1)
   #------------------------------------------------
   # now the quadratic fit
   #-------------------------------------------------
   func=funcQuad
   tplInitial2=(1.0,2.0,3.0)

   tplFinal2,success=leastsq(ErrorFunc,tplInitial2[:],args=(x,y))
   print "quadratic fit" ,tplFinal2
   xx2=xx1

   yy2=func(tplFinal2,xx2)
   plt.plot(xx1,yy1,'r-',x,y,'bo',xx2,yy2,'g-')
   plt.show()

if __name__=="__main__":
   main()

我今天用R检查了同样的问题,它给出了相似的答案。尽管绘图似乎与结果不符。 - Robert Ribas
谢谢,比我之前找到的scipy示例更加充实(上面评论中的链接对我来说在谷歌上也没有显示出来)。 - Lamar Latrell

2
from scipy.optimize import leastsq
import scipy as sc
import numpy as np
import matplotlib.pyplot as plt

使用optimize.curve_fit,代码更简洁,无需定义残差(误差)函数。
fig, ax = plt.subplots ()
# data
x=np.array([1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7])
y=np.array([6.008,15.722,27.130,33.772,5.257,9.549,11.098,28.828])

# modeling functions
def funcLine(x, a,b):
    return a*x+b
def funcQuad(x, a, b, c):
    return a*x**2+b*x+c

# optimize constants for the linear function
constantsLine, _ = sc.optimize.curve_fit (funcLine, x, y)

X=np.linspace(x.min(),x.max(),50)
Y1=funcLine(X, *constantsLine)

# optimize constants for the quadratic function
constantsQuad, _ = sc.optimize.curve_fit (funcQuad, x, y)

Y2=funcQuad(X,*constantsQuad)
plt.plot(X,Y1,'r-',label='linear approximation')
plt.plot(x,y,'bo',label='data points')
plt.plot(X,Y2,'g-', label='quadratic approximation')
matplotlib.pylab.legend ()
ax.set_title("Nonlinear Least Square Problems", fontsize=18)
plt.show()

1
这是一个超级简单的例子。想象一个抛物面,就像一个边缘呈抛物线形状的碗。如果我们将底部放在坐标(x,y)=(a,b)处,然后在所有x和y的值上最小化抛物面的高度-我们期望最小值为x = a和y = b。这是可以实现此功能的代码。
import random

from scipy.optimize import least_squares


a, b = random.randint(1, 1000), random.randint(1, 1000)
print("Expect", [a, b])

def f(args):
    x, y = args
    return (x-a)**2 + (y-b)**2

x0 = [-1, -3]

result = least_squares(fun=f, x0=x0)

print(result.x)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接