Подгонка кривой к связанным ОДУ

есть вопрос по подгонке/оптимизации кривой. У меня есть три связанных ОДУ, которые описывают биохимическую реакцию с исчезновением субстрата и образованием двух продуктов. Я нашел примеры, которые помогли мне создать код для решения ОДУ (ниже). Теперь я хочу оптимизировать неизвестные константы скорости (k, k3 и k4), чтобы они соответствовали экспериментальным данным P, которые являются сигналом от продукта y[1]. Какой самый простой способ сделать это? Спасибо.

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

# Experimental data 
P = [29.976,193.96,362.64,454.78,498.42,517.14,515.76,496.38,472.14,432.81,386.95,
352.93,318.93,279.47,260.19,230.92,202.67,180.3,159.09,137.31,120.47,104.51,99.371,
89.606,75.431,67.137,58.561,55.721]

# Three coupled ODEs
def conc (y, t) : 
    a1 = k * y[0] 
    a2 = k2 * y[0]
    a3 = k3 * y[1]
    a4 = k4 * y[1]
    a5 = k5 * y[2]
    f1 = -a1 -a2
    f2 = a1 -a3 -a4
    f3 = a4 -a5
    f = np.array([f1, f2, f3])
    return f


# Initial conditions for y[0], y[1] and y[2]
y0 = np.array([50000, 0.0, 0.0])

# Times at which the solution is to be computed.
t = np.linspace(0.5, 54.5, 28)

# Experimentally determined parameters.
k2 = 0.071
k5 = 0.029

# Parameters which would have to be fitted
k = 0.002
k3 = 0.1
k4 = 0.018

# Solve the equation
y = odeint(conc, y0, t)

# Plot data and the solution.
plt.plot(t, P, "bo")
#plt.plot(t, y[:,0]) # Substrate
plt.plot(t, y[:,1]) # Product 1
plt.plot(t, y[:,2]) # Product 2
plt.xlabel('t')
plt.ylabel('y')
plt.show()

person Magnus    schedule 14.07.2013    source источник
comment
Что, если у меня есть экспериментальные данные для всех трех меняющихся концентраций? Как бы я отнесся к части данных ODR?, Спасибо, M   -  person Magnus    schedule 23.07.2013


Ответы (1)


Редактировать: я внес некоторые изменения в код, чтобы показать, как он соответствует экспериментальным данным всех ODE.

Как это:

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from scipy.odr import Model, Data, ODR
# Experimental data 
P = [29.976,193.96,362.64,454.78,498.42,517.14,515.76,496.38,472.14,432.81,386.95,
352.93,318.93,279.47,260.19,230.92,202.67,180.3,159.09,137.31,120.47,104.51,99.371,
89.606,75.431,67.137,58.561,55.721]

# Times at which the solution is to be computed.
t = np.linspace(0.5, 54.5, 28)


def coupledODE(beta, x):
    k, k3, k4 = beta

    # Three coupled ODEs
    def conc (y, t) : 
        a1 = k * y[0] 
        a2 = k2 * y[0]
        a3 = k3 * y[1]
        a4 = k4 * y[1]
        a5 = k5 * y[2]
        f1 = -a1 -a2
        f2 = a1 -a3 -a4
        f3 = a4 -a5
        f = np.array([f1, f2, f3])
        return f


    # Initial conditions for y[0], y[1] and y[2]
    y0 = np.array([50000, 0.0, 0.0])

    # Experimentally determined parameters.
    k2 = 0.071
    k5 = 0.029

    # Parameters which would have to be fitted
    #k = 0.002
    #k3 = 0.1
    #k4 = 0.018

    # Solve the equation
    y = odeint(conc, y0, x)

    return y[:,1]
    # in case you are only fitting to experimental findings of ODE #1

    # return y.ravel()
    # in case you have experimental findings of all three ODEs

data = Data(t, P)
# with P being experimental findings of ODE #1

# data = Data(np.repeat(t, 3), P.ravel())
# with P being a (3,N) array of experimental findings of all ODEs

model = Model(coupledODE)
guess = [0.1,0.1,0.1]
odr = ODR(data, model, guess)
odr.set_job(2)
out = odr.run()
print out.beta
print out.sd_beta

f = plt.figure()
p = f.add_subplot(111)
p.plot(t, P, 'ro')
p.plot(t, coupledODE(out.beta, t))
plt.show()

Если вы используете интерактивный интерактивный интерактивный интерфейс Peak-o-Mat (http://lorentz.sf.net). программу подгонки кривой на основе scipy, вы можете добавить свою модель ODE и сохранить ее в userfunc.py (см. раздел настройки в документации):

import numpy as np
from scipy.integrate import odeint
from peak_o_mat import peaksupport as ps

def coupODE(x, k, k3, k4):

    # Three coupled ODEs
    def conc (y, t) : 
        a1 = k * y[0] 
        a2 = k2 * y[0]
        a3 = k3 * y[1]
        a4 = k4 * y[1]
        a5 = k5 * y[2]
        f1 = -a1 -a2
        f2 = a1 -a3 -a4
        f3 = a4 -a5
        f = np.array([f1, f2, f3])
        return f


    # Initial conditions for y[0], y[1] and y[2]
    y0 = np.array([50000, 0.0, 0.0])

    # Times at which the solution is to be computed.
    #t = np.linspace(0.5, 54.5, 28)

    # Experimentally determined parameters.
    k2 = 0.071
    k5 = 0.029

    # Parameters which would have to be fitted
    #k = 0.002
    #k3 = 0.1
    #k4 = 0.018

    # Solve the equation
    y = odeint(conc, y0, x)
    print y
    return y[:,1]

ps.add('ODE',
          func='coupODE(x,k,k3,k4)',
          info='thre coupled ODEs',
          ptype='MISC')

Вам нужно будет подготовить данные в виде текстового файла с двумя столбцами для времени и экспериментальных данных. Импортируйте данные в пик-о-мат, введите «ODE» в качестве подходящей модели, выберите соответствующие начальные параметры для k, k3, k4 и нажмите «Подогнать».

person Christian K.    schedule 16.07.2013
comment
Это было очень полезно. Спасибо Кристиан! - person Magnus; 18.07.2013