如何使用 scipy.optimize.curve_fit 来使用变量列表
How to use scipy.optimize.curve_fit to use lists of variable
我有随时间变化的数据轨迹,我想为其拟合一个函数。函数的输入是列表,我希望 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])
我想创建一个迭代循环,以便通过最小化错误为我提供最大数量变量的最佳拟合。
我也找到了这个讨论-
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 行,在 leastsq
提高 TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
类型错误:输入不当:N=6 不得超过 M=4
´´´
简短的回答是 "No"。 curve_fit
需要单个 list/ndarray 可变参数,这些参数按顺序与您提供的模型函数的参数相对应。也就是说,您必须明确命名函数中的所有参数,并使变量列表严格为一维。
话又说回来,curve_fit
只不过是 scipy.optimize.least_squares
的包装而已。要使用该方法,您传入一个(仍然严格为 1D)list/ndarray 并使用这些值从该单个变量数组构建要最小化的数组(通常为 data-model
)。在一些包含许多组件或数据集的复杂情况下,这会变得更容易使用。也就是说,curve_fit
方法不能很好地扩展到 50 个位置变量。
根据问题的性质,您可能还会找到 lmfit
(https://lmfit.github.io/lmfit-py/ -- disclaimer: I am the original author) useful. This organizes Parameters by name, not position in a list and provides more built-in ways to constrain Parameters and explore uncertainties. What may be of particular for your case, the lmfit.Model
class for curve-fitting includes the ability to easily add models together into a composite (for example, 2 Gaussians + n exponential background as shown at https://lmfit.github.io/lmfit-py/examples/documentation/builtinmodels_nistgauss2.html)。这可能会帮助您表达您想要做的事情。
我能够直接使用 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()
我有随时间变化的数据轨迹,我想为其拟合一个函数。函数的输入是列表,我希望 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])
我想创建一个迭代循环,以便通过最小化错误为我提供最大数量变量的最佳拟合。
我也找到了这个讨论-
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 行,在 leastsq 提高 TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) 类型错误:输入不当:N=6 不得超过 M=4 ´´´
简短的回答是 "No"。 curve_fit
需要单个 list/ndarray 可变参数,这些参数按顺序与您提供的模型函数的参数相对应。也就是说,您必须明确命名函数中的所有参数,并使变量列表严格为一维。
话又说回来,curve_fit
只不过是 scipy.optimize.least_squares
的包装而已。要使用该方法,您传入一个(仍然严格为 1D)list/ndarray 并使用这些值从该单个变量数组构建要最小化的数组(通常为 data-model
)。在一些包含许多组件或数据集的复杂情况下,这会变得更容易使用。也就是说,curve_fit
方法不能很好地扩展到 50 个位置变量。
根据问题的性质,您可能还会找到 lmfit
(https://lmfit.github.io/lmfit-py/ -- disclaimer: I am the original author) useful. This organizes Parameters by name, not position in a list and provides more built-in ways to constrain Parameters and explore uncertainties. What may be of particular for your case, the lmfit.Model
class for curve-fitting includes the ability to easily add models together into a composite (for example, 2 Gaussians + n exponential background as shown at https://lmfit.github.io/lmfit-py/examples/documentation/builtinmodels_nistgauss2.html)。这可能会帮助您表达您想要做的事情。
我能够直接使用 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()