我正在尝试对一个简单的化学反应系统进行敏感性分析。 A-> B(反应速率为k1)和A1-> B(k2),B-C(k3),C-> B(k4)。关键是要绘制速率。因此,如果k1值较小,则k2值较大,并且k3和k4相等。对于k1和k2,我得到某种趋势,但k4始终相同。我想念什么?我修改参数有误吗?
我的尝试
import matplotlib.pyplot as plt
import numpy as np
from lmfit import Parameters, report_fit, Minimizer, minimize, printfuncs, conf_interval, conf_interval2d
from scipy.integrate import odeint
from sys import exit
time = 10
Nt = 200
tt = np.linspace(0,time, Nt)
p = Parameters()
# add with tuples: (NAME VALUE VARY MIN MAX EXPR BRUTE_STEP)
p.add_many(('k1', 0.5, True, 0,1), ('k2', 0.5, True, 0,1), ('k3', 0.5, True, 0,1), ('k4', 0.5, True, 0,1))
time = 10
Nt = 11
tt = np.linspace(0,time, Nt)
def f(xs, t, ps):
"""Test"""
try:
k1 = ps['k1'].value
k2 = ps['k2'].value
k3 = ps['k3'].value
k4 = ps['k4'].value
except:
k1, k2, k3, k4 = ps
a, a1, b, c = xs
da_dt = - k1*a
da1_dt = - k2*a1
db_dt = k1*a + k2*a1 + k4*c - k3*b
dc_dt = k3*b - k4*c
return da_dt, da1_dt, db_dt, dc_dt
def g(t, x0, ps):
"""
Solution to the ODE x'(t) = f(t,x,k) with initial condition x(0) = x0
"""
x = odeint(f, x0, t, args=(ps,))
return x
def residual(ps, ts, data):
x0 = np.array([1,0.5,0,0])
model = g(ts, x0, ps)
return (model)
#exit()
x0 = np.array([1,0.5,0,0])
k1, k2, k3, k4 = 1,1,1,1
true_params = np.array((k1,k2,k3,k4))
data = g(tt, x0, true_params)
data += ((np.random.normal(size=data.shape)))
# create Minimizer
mini = Minimizer(residual, p,fcn_args=(tt,data))
# first solve with Nelder-Mead
out1 = mini.minimize(method='emcee')
out2 = mini.minimize(params=out1.params, method='Powell')
print(fit_report(out2))
print(report_fit(out1.params, min_correl=2))
##
ci, trace = conf_interval(mini, out2, sigmas = [0.01,0.02,0.3,0.4],
trace=True, verbose=True, maxiter = 200)
figure(1)
x, y, prob = trace['k1']['k1'], trace['k1']['k2'], trace['k1']['prob']
#x, y, prob = trace['k2']['k2'], trace['k2']['k1'], trace['k2']['prob']
scatter(x, y, c=prob ,s=30)
#plt.gca().set_xlim((0.00, 0.1))
#plt.gca().set_ylim((0.01, 0.1))
ylabel('k2')
xlabel('k1')
#plt.show()
figure(2)
x2, y2, prob2 = trace['k3']['k3'], trace['k3']['k4'],trace['k3']['prob']
x2, y2, prob2 = trace['k4']['k4'], trace['k4']['k3'],trace['k4']['prob']
scatter(x2, y2, s= 30, c= prob2)
#plt.gca().set_xlim((0, 0.1))
#plt.gca().set_ylim((0, 0.1))
xlabel('k3')
ylabel('k4')
答案 0 :(得分:1)
例如,k3
和/或k4
最终达到或至少非常接近1.0的上限。您应谨慎使用边界,并在物理上有意义。也就是说,真正的“问题”是您使用Parameters.add_many()
并将所有参数设置为[0, 1]
之间。
从这个意义上说,这种契合确实有效,甚至可以满足您的要求;但是,如果您放宽这些界限,则可能会获得更好的结果。
FWIW,可能没有必要先用Nelder-Mead再用leastsq
解决(如果您确实想这样做,则应该正确拼写Nelder0。