lmfit用于绘制参数

时间:2019-06-21 13:20:57

标签: python lmfit

我正在尝试对一个简单的化学反应系统进行敏感性分析。 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')

1 个答案:

答案 0 :(得分:1)

例如,k3和/或k4最终达到或至少非常接近1.0的上限。您应谨慎使用边界,并在物理上有意义。也就是说,真正的“问题”是您使用Parameters.add_many()并将所有参数设置为[0, 1]之间。

从这个意义上说,这种契合确实有效,甚至可以满足您的要求;但是,如果您放宽这些界限,则可能会获得更好的结果。

FWIW,可能没有必要先用Nelder-Mead再用leastsq解决(如果您确实想这样做,则应该正确拼写Nelder0。