将元组作为scipy.optimize.curve_fit的输入参数传递

问题描述 投票:7回答:4

我有以下代码:

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个)。嗯,这听起来很公平 - curve_fit使(0,0)不是两个标量输入。所以我尝试了这个:

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

同样,它说:ValueError:对象太深,不适合所需的数组

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

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

它会引发IndexError:标量变量的索引无效。显然,它只给p的函数标量。

我可以使def func(x,p1,p2):返回p1 + p2 + x以使其正常工作,但是在更复杂的情况下,代码看起来会变得冗长和混乱。如果对这个问题有一个更清洁的解决方案,我真的很喜欢它。

谢谢!

python numpy scipy curve-fitting
4个回答
5
投票

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

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

2
投票

Problem

使用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.

Solution

所以你应该这样做:

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))

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

Explaining the idea

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

Working example

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()

Result from the fit is shown in the plot.


1
投票

您可以定义返回其他函数的函数(请参阅Passing additional arguments using 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()
© www.soinside.com 2019 - 2024. All rights reserved.