将数据拟合到python中的ode的数值解

时间:2016-10-23 07:20:20

标签: python numpy scipy curve-fitting data-analysis

我有一个两个一阶ODE的系统,它们是非线性的,因此难以以封闭形式解析地解决。我想将这个ODE系统的数值解适合数据集。我的数据集仅适用于作为ODE系统一部分的两个变量中的一个。我该怎么做? This没有帮助,因为那里只有一个变量。

我目前导致错误的代码是:

import numpy as np
from scipy.integrate import odeint
from scipy.optimize import curve_fit

def f(y, t, a, b, g):
    S, I = y # S, I are supposed to be my variables
    Sdot = -a * S * I
    Idot = (a - b) * S * I + (b - g - b * I) * I
    dydt = [Sdot, Idot]
    return dydt

def y(t, a, b, g, y0):
    y = odeint(f, y0, t, args=(a, b, g))
    return y.ravel()

I_data =[] # I have data only for I, not for S
file = open('./ratings_showdown.csv')
for e_raw in file.read().split('\r\n'):
    try:
        e=float(e_raw); I_data.append(e)
    except ValueError:
        continue

data_t = range(len(I_data))
popt, cov = curve_fit(y, data_t, I_data, [.05, 0.02, 0.01, [0.99,0.01]]) 
#want to fit I part of solution to data for variable I
#ERROR here, ValueError: setting an array element with a sequence
a_opt, b_opt, g_opt, y0_opt = popt

print("a = %g" % a_opt)
print("b = %g" % b_opt)
print("g = %g" % g_opt)
print("y0 = %g" % y0_opt)

import matplotlib.pyplot as plt
t = np.linspace(0, len(data_y), 2000)
plt.plot(data_t, data_y, '.',
         t, y(t, a_opt, b_opt, g_opt, y0_opt), '-')
plt.gcf().set_size_inches(6, 4)
#plt.savefig('out.png', dpi=96) #to save the fit result
plt.show()

2 个答案:

答案 0 :(得分:1)

这种类型的ODE拟合在symfit中变得更加容易,我专门写作scipy的用户友好包装器。我认为这对你的情况非常有用,因为减少锅炉板代码的数量简化了很多事情。

从文档中大致应用到您的问题:

from symfit import variables, parameters, Fit, D, ODEModel

S, I, t = variables('S, I, t')
a, b, g = parameters('a, b, g')

model_dict = {
    D(S, t): -a * S * I,
    D(I, t): (a - b) * S * I + (b - g - b * I) * I
}

ode_model = ODEModel(model_dict, initial={t: 0.0, S: 0.99, I: 0.01})

fit = Fit(ode_model, t=tdata, I=I_data, S=None)
fit_result = fit.execute()

查看docs以获取更多信息:)

答案 1 :(得分:0)

所以我想出了问题所在。 curve_fit()函数显然返回一个列表,因为它是第二个返回值。因此,我没有将初始条件作为列表[0.99,0.01]传递,而是将它们分别作为0.99和0.01传递。