如何使用scipy.optimize.curve_fit来使用变量列表

inkz8wg9  于 2022-11-09  发布在  其他
关注(0)|答案(3)|浏览(152)

我有时间变化的数据轨迹,我想拟合一个函数。函数的输入是列表,我想让curve_fit优化列表中的所有值,以拟合曲线。到目前为止,我已经得到-

from scipy.optimize import curve_fit
from matplotlib.pylab import plt
from numpy import exp

def ffunc2(x, a, b):
    counter = 0
    return_value = 0
    while counter < len(a):
        return_value += a[counter] * exp(b[counter] * x)
        counter += 1
    return return_value

# INITIAL DATA

x = [1, 2, 3, 5]
y = [1, 8, 81, 125]

number_variable = 2

# INTIAL GUESS

p0 = []
counter = 0
while counter < number_variable:
    p0.append(0.0)
    counter += 1

p, _ = curve_fit(ffunc2, x, y, p0=[0.0, 0.0])

我想创建一个循环,它通过迭代使误差最小化,从而得到最佳拟合,并具有最大数量的变量。
我也找到了此讨论-Using scipy curve_fit for a variable number of parameters

from numpy import exp
from scipy.optimize import curve_fit

def wrapper_fit_func(x, N, *args):
    a, b, c = list(args[0][:N]), list(args[0][N:2*N]), list(args[0][2*N:3*N])
    return fit_func(x, a, b)

def fit_func(x, a, b):
    counter = 0
    return_value = 0
    while counter < len(a):
        return_value += a[counter] * exp(b[counter] * x)
        counter += 1
    return return_value

x = [1, 2, 3, 5]
y = [1, 8, 81, 125]
params_0 = [0,1.0,2.0,3.0,4.0,5.0]

popt, pcov = curve_fit(lambda x, *params_0: wrapper_fit_func(x, 3, params_0), x, y, p0=params_0)

但是得到一个错误--文件“C:\python\lib\site-packages\scipy\optimize\minpack.py”,第387行,在最小平方中出现了类型错误(“不正确的输入:N=%s不能超过M=%s' %(n,m))类型错误:输入不正确:N=6不得超过M=4

gcxthw6b

gcxthw6b1#

我可以直接使用sci_py.optimize.least_squares来解决这个问题,因为它将元组作为输入,而不是直接使用变量。但是我必须定义错误函数。我认为它有助于解决我的问题。

from scipy.optimize import least_squares
from matplotlib.pylab import plt
from numpy import exp
import numpy as np

# define function to fit

def ffunc2(a, x):
    counter = 0
    return_value = 0
    while counter < len(a):
        return_value += a[counter] * exp(x * a[counter + 1])
        counter += 2

    return return_value

def error_func(tpl, x, y):
    return ffunc2(tpl,x) - y

# INPUT DATA

x = np.array([1, 2, 3, 5])
y = np.array([0.22103418, 0.24428055, 0.26997176, 0.32974425,])

# INITIAL GUESS

p0 = (1, 1)*10
output = least_squares(error_func, x0=p0, jac='2-point', bounds=(0, np.inf), method='trf', ftol=1e-08,
                       xtol=1e-08, gtol=1e-08, x_scale=1.0, loss='linear', f_scale=1.0, diff_step=None,
                       tr_solver=None,
                       tr_options={}, jac_sparsity=None, max_nfev=None, verbose=0, args=(x, y))

tpl_final = output.x
print (tpl_final)

final_curve = ffunc2(tpl_final,x)

plt.plot(x, y, 'r-', x, final_curve, 'g-')
plt.show()
djp7away

djp7away2#

简短的回答是“不”。curve_fit需要一个变量参数的列表/ndarray,这些参数按顺序与您提供的模型函数的参数相对应。也就是说,您必须显式地命名函数中的所有参数,并使变量列表严格地一维化。
同样,curve_fit只不过是scipy.optimize.least_squares的 Package 器。(仍然是严格的一维)list/ndarray,并使用这些值构建要最小化的数组(通常是data-model)。在一些包含许多组件或数据集的复杂情况下,这会变得更容易使用。也就是说,curve_fit方法不能很好地缩放到50个位置变量。
根据问题的性质,您可能还会发现lmfithttps://lmfit.github.io/lmfit-py/--免责声明:我是原作者)非常有用。它按名称组织参数,而不是按列表中的位置,并提供了更多的内置方式来约束参数和探索不确定性。对于您的情况可能特别重要的是,用于曲线拟合的lmfit.Model类包括轻松地将模型一起添加到组合中的能力(例如,2高斯+ n指数背景,如https://lmfit.github.io/lmfit-py/examples/documentation/builtinmodels_nistgauss2.html所示)。这可能有助于您表达您正在尝试做的事情。

23c0lvtd

23c0lvtd3#

请看这篇文章https://stackoverflow.com/a/73951825/20160627,我建议使用scipy.optimize.curve_fit,其中包含任意数量和位置的参数,以便在列表中进行拟合或修复

相关问题