9

我有以下代码:

import numpy as np
from scipy.optimize import curve_fit


def func(x, p): return p[0] + p[1] + x


popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=(0, 0)) 

它将引发TypeError: func() 恰好需要 2 个参数 (3 given)。好吧,这听起来很公平 - curve_fit 将 (0, 0) 解压缩为两个标量输入。所以我尝试了这个:

popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=((0, 0),))

同样,它说:ValueError: object too deep for desired array

如果我将其保留为默认值(未指定 p0):

popt, pcov = curve_fit(func, np.arange(10), np.arange(10))  

它将引发IndexError: invalid index to scalar variable。显然,它只给了函数一个 p 的标量。

我可以使 def func(x, p1, p2): return p1 + p2 + x 让它工作,但在更复杂的情况下,代码会显得冗长和混乱。如果有一个更清洁的解决方案来解决这个问题,我会非常喜欢它。

谢谢!

4

4 回答 4

7

不确定这是否更干净,但至少现在向拟合函数添加更多参数更容易。也许人们甚至可以从中做出更好的解决方案。

import numpy as np
from scipy.optimize import curve_fit


def func(x, p): return p[0] + p[1] * x

def func2(*args):
    return func(args[0],args[1:])

popt, pcov = curve_fit(func2, np.arange(10), np.arange(10), p0=(0, 0))
print popt,pcov

编辑:这对我有用

import numpy as np
from scipy.optimize import curve_fit

def func(x, *p): return p[0] + p[1] * x

popt, pcov = curve_fit(func, np.arange(10), np.arange(10), p0=(0, 0))
print popt,pcov
于 2013-10-17T02:57:00.363 回答
2

问题

使用curve_fit时必须明确说出拟合参数的数量。做类似的事情:

def f(x, *p):
    return sum( [p[i]*x**i for i in range(len(p))] )

会很棒,因为这将是一个通用的 n 阶多项式拟合函数,但不幸的是,在我的 SciPy 0.12.0 中,它提出了:

ValueError: Unable to determine number of fit parameters.

解决方案

所以你应该这样做:

def f_1(x, p0, p1):
    return p0 + p1*x

def f_2(x, p0, p1, p2):
    return p0 + p1*x + p2*x**2

等等……

然后你可以使用p0参数调用:

curve_fit(f_1, xdata, ydata, p0=(0,0))
于 2013-08-20T07:01:42.323 回答
1

scipy.optimize.curve_fit

scipy.optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, **kw)

Use non-linear least squares to fit a function, f, to data.

Assumes ydata = f(xdata, *params) + eps

解释这个想法

要拟合的函数应该只采用标量而不是: *p0)。请记住,拟合的结果取决于初始化参数。

工作示例

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

def func(x, a0, a1):
    return a0 + a1 * x

x, y = np.arange(10), np.arange(10) + np.random.randn(10)/10
popt, pcov = curve_fit(func, x, y, p0=(1, 1))

# Plot the results
plt.title('Fit parameters:\n a0=%.2e a1=%.2e' % (popt[0], popt[1]))
# Data
plt.plot(x, y, 'rx')
# Fitted function
x_fine = np.linspace(x[0], x[-1], 100)
plt.plot(x_fine, func(x_fine, popt[0], popt[1]), 'b-')
plt.savefig('Linear_fit.png')
plt.show()

拟合结果显示在图中。

于 2016-06-06T14:00:39.743 回答
1

您可以定义返回其他函数的函数(请参阅使用 scipy.optimize.curve_fit 传递附加参数?

工作示例:

import numpy as np
import random
from scipy.optimize import curve_fit
from matplotlib import pyplot as plt
import math

def funToFit(x):
    return 0.5+2*x-3*x*x+0.2*x*x*x+0.1*x*x*x*x


xx=[random.uniform(1,5) for i in range(30)]
yy=[funToFit(xx[i])+random.uniform(-1,1) for i in range(len(xx))]


a=np.zeros(5)
def make_func(numarg):
    def func(x,*a):
        ng=numarg
        v=0
        for i in range(ng):
            v+=a[i]*np.power(x,i)
        return v
    return func

leastsq, covar = curve_fit(make_func(len(a)),xx,yy,tuple(a))
print leastsq
def fFited(x):
    v=0
    for i in range(len(leastsq)):
        v+=leastsq[i]*np.power(x,i)
    return v


xfine=np.linspace(1,5,200)
plt.plot(xx,yy,".")
plt.plot(xfine,fFited(xfine))
plt.show()
于 2017-06-20T14:31:34.527 回答