我有一组数据,我正在尝试使用 scipy 的 minimumsq 函数将其拟合到 ODE 模型中。我的 ODE 有参数 beta
和 gamma
,因此它看起来像这样:
# dS/dt = -betaSI
# dI/dt = betaSI - gammaI
# dR/dt = gammaI
# with y0 = y(t=0) = (S(0),I(0),R(0))
这个想法是找到beta
和gamma
,以便我的 ODE 系统的最佳数值积分接近数据。如果我知道初始条件中的所有点,我就可以使用 minimumsq y0
很好地做到这一点。
现在,我正在尝试做同样的事情,但现在将y0
的一个条目作为额外的参数传递。这就是我和蟒蛇停止交流的地方......我做了一个函数,现在我传递给 minimumsq 的参数的第一个条目是我的变量 R 的初始条件。我收到以下消息:
*Traceback (most recent call last):
File "/Users/Laura/Dropbox/SHIV/shivmodels/test.py", line 73, in <module>
p1,success = optimize.leastsq(errfunc, initguess, args=(simpleSIR,[y0[0]],[Tx],[mydata]))
File "/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 283, in leastsq
gtol, maxfev, epsfcn, factor, diag)
TypeError: array cannot be safely cast to required type*
这是我的代码。对于此示例,它需要的内容要复杂一些,因为实际上我想拟合另一个具有 7 个参数的颂歌,并希望一次拟合多个数据集。但我想在这里发布一些更简单的东西......任何帮助将不胜感激!谢谢!
import numpy as np
from matplotlib import pyplot as plt
from scipy import optimize
from scipy.integrate import odeint
#define the time span for the ODE integration:
Tx = np.arange(0,50,1)
num_points = len(Tx)
#define a simple ODE to fit:
def simpleSIR(y,t,params):
dydt0 = -params[0]*y[0]*y[1]
dydt1 = params[0]*y[0]*y[1] - params[1]*y[1]
dydt2 = params[1]*y[1]
dydt = [dydt0,dydt1,dydt2]
return dydt
#generate noisy data:
y0 = [1000.,1.,0.]
beta = 12*0.06/1000.0
gamma = 0.25
myparam = [beta,gamma]
sir = odeint(simpleSIR, y0, Tx, (myparam,))
mydata0 = sir[:,0] + 0.05*(-1)**(np.random.randint(num_points,size=num_points))*sir[:,0]
mydata1 = sir[:,1] + 0.05*(-1)**(np.random.randint(num_points,size=num_points))*sir[:,1]
mydata2 = sir[:,2] + 0.05*(-1)**(np.random.randint(num_points,size=num_points))*sir[:,2]
mydata = np.array([mydata0,mydata1,mydata2]).transpose()
#define a function that will run the ode and fit it, the reason I am doing this
#is because I will use several ODE's to see which one fits the data the best.
def fitfunc(myfun,y0,Tx,params):
myfit = odeint(myfun, y0, Tx, args=(params,))
return myfit
#define a function that will measure the error between the fit and the real data:
def errfunc(params,myfun,y0,Tx,y):
"""
INPUTS:
params are the parameters for the ODE
myfun is the function to be integrated by odeint
y0 vector of initial conditions, so that y(t0) = y0
Tx is the vector over which integration occurs, since I have several data sets and each
one has its own vector of time points, Tx is a list of arrays.
y is the data, it is a list of arrays since I want to fit to multiple data sets at once
"""
res = []
for i in range(len(y)):
V0 = params[0][i]
myparams = params[1:]
initCond = np.zeros([3,])
initCond[:2] = y0[i]
initCond[2] = V0
myfit = fitfunc(myfun,initCond,Tx[i],myparams)
res.append(myfit[:,0] - y[i][:,0])
res.append(myfit[:,1] - y[i][:,1])
res.append(myfit[1:,2] - y[i][1:,2])
#end for
all_residuals = np.hstack(res).ravel()
return all_residuals
#end errfunc
#example of the problem:
V0 = [0]
params = [V0,beta,gamma]
y0 = [1000,1]
#this is just to test that my errfunc does work well.
errfunc(params,simpleSIR,[y0],[Tx],[mydata])
initguess = [V0,0.5,0.5]
p1,success = optimize.leastsq(errfunc, initguess, args=(simpleSIR,[y0[0]],[Tx],[mydata]))
问题出在变量 initguess 上。 函数 optimize.minimumsq 具有以下调用签名:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html
第二个参数 x0 必须是一个数组。 您的列表
initguess = [v0,0.5,0.5]
不会转换为数组,因为 v0 是列表而不是 int 或浮点数。 因此,当您尝试在 minimumsq 函数中将 initguess 从列表转换为数组时,会出现错误。
我会调整变量参数从
def errfunc(params,myfun,y0,Tx,y):
所以它是一个一维数组。 使前几个条目成为 v0 的值,然后将 beta 和 gamma 附加到该条目。