【问题标题】:Why does scipy.optimize.curve_fit not produce a line of best fit for my points?为什么 scipy.optimize.curve_fit 不会产生最适合我的点的线?
【发布时间】:2013-11-11 21:10:22
【问题描述】:

我有一组数据点(下面代码中的 x 和 y),我正在尝试通过我的点创建一条最适合的线性线。我正在使用scipy.optimize.curve_fit。我的代码产生一条线,但不是一条最合适的线。我尝试提供函数模型参数以用于我的渐变和截距,但每次它都会产生完全相同的线,不适合我的数据点。

蓝点是我的数据点,红线应该适合:

如果有人能指出我哪里出错了,我将非常感激:

import numpy as np
import matplotlib.pyplot as mpl
import scipy as sp
import scipy.optimize as opt

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]
trialX = np.linspace(1.0,4.0,1000)                         #Trial values of x

def f(x,m,c):                                        #Defining the function y(x)=(m*x)+c
    return (x*m)+c

popt,pcov=opt.curve_fit(f,x,y)                       #Returning popt and pcov
ynew=f(trialX,*popt)                                                  

mpl.plot(x,y,'bo')
mpl.plot(trialX,ynew,'r-')
mpl.show()

【问题讨论】:

  • 我自己设法解决了问题。 x 被定义为一个列表,而不是一个数组。我只是通过将 np.array 放在定义的 x 和 y 数组的前面来修复它。
  • 我也得出了同样的结论李子,我应该先看到这条评论!下次发生这种情况时,请随时将其发布为您自己问题的答案并接受它。
  • 请注意,这已被修补:github.com/scipy/scipy/issues/3037

标签: python optimization scipy curve-fitting


【解决方案1】:

编辑:此行为现已在当前版本的 scipy 中进行了修补,以使 .curve_fit 更加简单:

https://github.com/scipy/scipy/issues/3037


出于某种原因,.curve_fit 确实希望输入是一个 numpy 数组,如果您将其传递给常规列表,则会给您错误的结果(恕我直言,这是意外行为,可能是一个错误)。将x的定义改为:

x=np.array([1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7])

你会得到:

我猜自 m*x 以来发生的事情,其中​​ m 是一个整数,x 是一个列表,将产生该列表的 m 个副本,显然 不是您正在寻找的结果!

【讨论】:

  • 对我来说这听起来像是curve_fit 中的一个错误:你会在github.com/scipy/scipy 提出问题吗?
  • @Zhenya 我一直在考虑,这不是一个错误,但对于新用户来说意料之外的。因此,github.com/scipy/scipy/issues/3037
  • 注意:f 是 your 函数,curve_fit 只是将 your x 传递给它。因此,您应该检查您的函数是否对您的数据具有正确的行为。 :)
【解决方案2】:

您也可以使用 numpy.polyfit 来获得最佳拟合线:

import numpy as np
import matplotlib.pyplot as mpl

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]
trialX = np.linspace(1.0,4.0,1000)                         #Trial values of x

#get the first order coefficients 
fit = np.polyfit(x, y, 1)

#apply 
ynew = trialX * fit[0] + fit[1]                                              

mpl.plot(x,y,'bo')
mpl.plot(trialX,ynew,'r-')
mpl.show()

这是输出:

【讨论】:

  • 您可以通过将拟合线更改为以下内容来缩放此答案:fit_poly = np.poly1d(np.polyfit(x, y, 1))ynew = fit_poly(trialX)。如果您以后需要,这样可以更轻松地更改为二次方。
  • 我又给了你一个赞,这应该足以在你的后续帖子中添加图片(并编辑这个)。欢迎来到堆栈溢出!您无需添加诸如“希望这有帮助”之类的内容,如果有,您将获得选票,否则您将获得反对票或要求澄清的 cmets。我们试图在这里保持答案干净!
猜你喜欢
  • 2021-07-03
  • 2013-03-15
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 2014-12-05
  • 2018-04-24
  • 1970-01-01
相关资源
最近更新 更多