我有一个两个一阶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()
答案 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传递。