使用Python symfit ODEModel拟合多维数据遇参数传递错误求助
问题:symfit ODEModel拟合多维数据时出现TypeError错误
尝试用symfit的ODEModel拟合含时变输入的ODE参数,参考官方《Fitting multidimensional datasets》示例编写代码,但运行时出现TypeError: got an unexpected keyword argument 'inp'错误。
原实现代码
import symfit as sf import numpy as np # data x = np.arange(0,19) data = 10e-4 * np.array([8,10,12,11,10,15,25,37,46,40,43,35,27,14,8,10,13,9,10]) data2 = 10e-3 * np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0]) # model t, mp, inp = sf.variables('t, mp, inp') tau, w = sf.parameters('tau, w') model = {sf.D(mp, t): (-mp + inp * w) / tau } # fitting ode_model = sf.ODEModel(model, initial={inp: data2[0], t: 0.0, mp: data[0]}) fit = sf.Fit(ode_model, inp=data2, t=x, mp=data) fit_result = fit.execute()
完整错误栈
/usr/local/lib/python3.10/dist-packages/symfit/core/fit.py in __init__(self, model, objective, minimizer, constraints, absolute_sigma, *ordered_data, **named_data) 372 # Bind as much as possible the provided arguments. 373 signature = self._make_signature() --> 374 bound_arguments = signature.bind_partial(*ordered_data, **named_data) 375 376 # Select objective function to use. Has to be done before calling /usr/lib/python3.10/inspect.py in bind_partial(self, *args, **kwargs) 3191 Raises `TypeError` if the passed arguments can not be bound. 3192 """ -> 3193 return self._bind(args, kwargs, partial=True) 3194 3195 def __reduce__(self): /usr/lib/python3.10/inspect.py in _bind(self, args, kwargs, partial) 3173 arguments[kwargs_param.name] = kwargs 3174 else: -> 3175 raise TypeError( 3176 'got an unexpected keyword argument {arg!r}'.format( 3177 arg=next(iter(kwargs)))) TypeError: got an unexpected keyword argument 'inp'
错误原因
你的怀疑正确:inp不是模型的自变量,而是随时间变化的输入信号。原代码中错误地将inp作为独立变量定义,并且在sf.Fit()中当作输入参数传入,导致symfit无法识别该参数。
修正方案
将inp定义为时间t的函数,而非独立变量,同时调整初始条件和拟合参数的传入方式:
修正后的代码
import symfit as sf import numpy as np # 数据 x = np.arange(0,19) data = 10e-4 * np.array([8,10,12,11,10,15,25,37,46,40,43,35,27,14,8,10,13,9,10]) data2 = 10e-3 * np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0]) # 模型定义:将inp声明为t的函数 t, mp = sf.variables('t, mp') tau, w = sf.parameters('tau, w') inp = sf.Function('inp')(t) # 将inp定义为t的函数 model = {sf.D(mp, t): (-mp + inp * w) / tau } # 创建ODEModel:仅需设置状态变量mp的初始条件和初始时间,无需设置inp的初始值 ode_model = sf.ODEModel(model, initial={t: 0.0, mp: data[0]}) # 拟合:将inp的观测数据与t对应传入 fit = sf.Fit(ode_model, t=x, inp=data2, mp=data) fit_result = fit.execute() # 打印拟合结果 print(fit_result)
关键修正点
- 定义inp为t的函数:用
sf.Function('inp')(t)将inp声明为随时间变化的输入,而非独立变量,让symfit识别其为时变输入信号。 - 调整初始条件:初始条件只需设置状态变量
mp和初始时间t,inp是输入信号无需设置初始值。 - 正确传入拟合数据:在
sf.Fit()中通过inp=data2将输入数据与时间t=x绑定,模型会在每个时间点使用对应的inp值进行积分计算。
内容的提问来源于stack exchange,提问作者soupinacanoe
相关产品推荐
相关产品推荐

