ODE拟合与Symfit for Python:如何获得初始值的估计值?

ODE拟合与Symfit for Python:如何获得初始值的估计值?,python,parameters,ode,symfit,Python,Parameters,Ode,Symfit,我想知道如何提取状态变量的初始值 基本上,初始值也被视为参数 我提供初始值是因为它们是集成所需要的。但是,这些值有时被视为附加参数(模型参数旁边),因此提供的初始值也被视为初始猜测。事实上,在进行生长实验时,我们有一些初始条件,但我们可能不知道所有这些条件(取决于具体的实验条件和正在研究的系统) 考虑一个简单的微生物生长模型,其生长速率mu由众所周知的Monod动力学(参数mumax和ks)和恒定的生物量底物产量(参数yxs)以及与生长相关的产物形成(参数ypx)控制。请参阅下面的代码 对于进一

我想知道如何提取状态变量的初始值

基本上,初始值也被视为参数

我提供初始值是因为它们是集成所需要的。但是,这些值有时被视为附加参数(模型参数旁边),因此提供的初始值也被视为初始猜测。事实上,在进行生长实验时,我们有一些初始条件,但我们可能不知道所有这些条件(取决于具体的实验条件和正在研究的系统)

考虑一个简单的微生物生长模型,其生长速率mu由众所周知的Monod动力学(参数mumax和ks)和恒定的生物量底物产量(参数yxs)以及与生长相关的产物形成(参数ypx)控制。请参阅下面的代码

对于进一步的实现,我想计算随时间变化的一阶灵敏度、参数相关性等

from symfit import variables, parameters, ODEModel, Fit, D
import numpy as np
from matplotlib import pyplot as plt
# define ODE model
ks, mumax, ypx, yxs = parameters('ks, mumax, ypx, yxs')
p, s, x, t = variables('p, s, x, t')
model_dict = {
    D(x, t): mumax * s / (ks + s) * x,
    D(s, t): -1/yxs * mumax * s / (ks + s) * x,
    D(p, t): ypx * mumax * s / (ks + s) * x,
}
ode_model = ODEModel(model_dict, initial={t:0.0, x:0.1, s:20.0, p:0.0})

# Generate noisy measurement data
tSample = np.array([1, 2, 4, 6, 8, 12])
pSample, sSample, xSample = ode_model(t=tSample, ks=0.01, mumax=0.4, ypx=0.2, yxs=0.5)
xRelErr = 0.05
sRelErr = 0.10
pRelErr = 0.10
xNoise = xSample + xSample * xRelErr * np.random.randn(xSample.size)
sNoise = sSample + sSample * sRelErr * np.random.randn(sSample.size)
pNoise = pSample + pSample * pRelErr * np.random.randn(pSample.size)

# constraints for parameters
ks.min = 0.0
mumax.min = 0.0
ypx.min = 0.0
yxs.min = 0.0

# initial guesses for parameters
ks.value = 0.01
mumax.value = 0.4
ypx.value = 0.2
yxs.value = 0.5

# perform fitting
fit = Fit(ode_model, t=tSample, x=xNoise, s=sNoise, p=pNoise)
fit_result = fit.execute()

# show fit
print(fit_result)
print(fit_result.covariance_matrix)

好问题。简而言之,答案是否定的,因为这还没有实施。(虽然它已经在列表中出现了一段时间,请参见。)

然而,在某些情况下,可能已经有了解决办法。假设你想要

x0 = Parameter('x0')
ode_model = ODEModel(model_dict, initial={t: 0.0, x: x0, s: 20.0, p: 0.0})
在你上面的例子中
symfit
当前只会检查
model\u dict
中的
参数
对象,因此它不会看到
x0
。所以,如果您的模型明确地依赖于
x0
,它将起作用。也许您可以找到某种方法使
x0
出现在您的模型中。最坏的情况是,您可以将其中一个组件与一些简单的标识相乘,如
cos(x0)**2+sin(x0)**2

model_dict = {
    D(x, t): mumax * s / (ks + s) * x * (cos(x0)**2 + sin(x0)**2),
    D(s, t): -1/yxs * mumax * s / (ks + s) * x,
    D(p, t): ypx * mumax * s / (ks + s) * x,
}
但是,这是不提供担保的;)。在我自己的研究中,当我有一个明确依赖初始参数的模型时,我注意到,
model_dict
很难估计这些参数的雅可比矩阵,因此拟合是不稳定的。然而,这是几个版本之前的版本,从那时起很多事情都发生了变化,所以请尝试一下

您也可以使用非基于梯度的方法,如或希望很快

我将对此进行调查,我为此提出了一个问题。如果您想参与其中,欢迎提供任何帮助,例如提供一个我可以用作测试的最小工作示例。

我可以确认该建议在Symfit 0.5.1中有效,但需要注意的是,“初始”值需要指定为,例如x0*.value*。当您调用“print(fit_result)”时,这会产生一个奇怪的问题,它会抱怨“'NoneType'对象没有属性'sqrt'”,但其他一切似乎都很好

这里有一个(或多或少)最简单的例子来说明这一点:

来自symfit.core.minimizers导入差异进化、BFGS、BasinHopping
将symfit导入为sf
将numpy作为np导入
将matplotlib.pyplot作为plt导入
信号=np.阵列([3.69798582e-04,-4.42968073e-04,-1.62901574e-04,-2.66074317e-03,
-2.69579455e-03、7.74354388e-04、2.19358448e-03、6.38607419e-03、,
3.78642692e-03、-3.27400548e-03、-4.34699571e-03、2.41753615e-04、,
9.96158926e-03、1.8999040E-02、3.60202254e-02、7.63199623e-02、,
1.43007912e-01、2.48988030e-01、3.95977066e-01、5.65958061e-01、,
7.12988678e-01、8.09083671e-01、8.50628154e-01、8.72826358e-01、,
8.83509851e-01、8.81799211e-01、8.81649458e-01、8.88619439e-01、,
8.82045565e-01、8.91226071e-01、9.07541872e-01、9.12674298e-01、,
9.06886981e-01、8.98514353e-01、9.02275457e-01、9.07204574e-01、,
9.01857725e-01、8.920167771E-01、8.99608399e-01、8.98652789e-01、,
8.98421894e-01、8.94907751e-01、9.09122059e-01、9.13065656e-01、,
9.09254937e-01、9.10644851e-01、8.99605570e-01、8.99581621e-01、,
9.12054065e-01、9.06361431e-01、9.03838466e-01、9.09130042e-01、,
9.1344399E-01、9.18176457e-01、9.08160892e-01、9.03154574e-01、,
9.03069088e-01、9.02597396e-01、8.98854582e-01、9.07801262e-01])
周期=np.arange(len(信号))
s、 c=sf.变量('s,c')
r、 K,s0=sf.参数('r,K,s0')
lg2_e=np.log2(np.exp(1))
s0.min=1e-7
s0.0值=1e-6
s0.max=1e-5
K.min=0.1
K.值=1
K.max=2
r、 最小值=0.1/lg2_e
r、 值=1/lg2_e
r、 最大值=2/lg2_e
逻辑方程={
sf.D(s,c):r*s*(1-s/K)*(sf.cos(s0)**2+sf.sin(s0)**2)
}
logistic_model=sf.ODEModel(logistic_eqn,initial={c:0.0,s:s0.value})
逻辑拟合=sf.拟合(逻辑拟合模型,c=周期,s=信号)#,最小值=差异演化)
拟合结果=逻辑拟合执行()
#打印(拟合结果)
sig_拟合,=逻辑模型(c=周期,**拟合结果.参数)
plt.绘图(周期、信号“o”)
plt.绘图(周期、信号拟合)

您能添加一个示例吗?我很乐意为您提供帮助(感谢您使用symfit),但我不确定您需要什么。您已经为
ODEModel
提供了初始值,以便它能够集成,对吗?解决方案的Thx。当然,我可以为测试提供一个最小的工作示例。我也有一些关于初始值作为优化参数的想法:根据我的经验,我们确实经常有一些模型状态,我们无法(或无法)测量,所以至少对于这些状态,我们需要初始值作为参数,尽管我们主要感兴趣的是模型参数。此外,我认为必须始终仔细评估参数估计值,例如wrt相关性等。因此,在可用性(对可接受性很重要)和输出复杂性之间总会有一些折衷。但这是一个哲学问题。。。非常感谢您的工作!不幸的是,我不能在stackoverflow上PM你。也许你可以回答这个问题,并提供一个最小的例子?非常感谢您的帮助:)。我认为打印(拟合结果)错误发生在方差未定义的情况下——可能是在