有没有一种方法可以优化输出,限制来自 scipy.optimize 的 fmin 中的参数

Is there a way where I can optimize the output restricting the parameters in fmin from scipy.optimize

我在做什么:我修改了僵尸入侵系统的代码以演示它应该如何编写并尝试优化最小二乘误差(定义为分数函数)使用 fmin 函数。

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy import integrate
from scipy.optimize import fmin
#=====================================================
#Notice we must import the Model Definition
from zombiewithdata import eq
#=====================================================

#1.Get Data
#====================================================
Td=np.array([0.5,1,1.5,2,2.2,3,3.5,4,4.5,5])#time
Zd=np.array([0,2,2,5,2,10,15,50,250,400])#zombie pop
#====================================================

#2.Set up Info for Model System
#===================================================
# model parameters
#----------------------------------------------------
P = 0       # birth rate
d = 0.0001  # natural death percent (per day)
B = 0.0095  # transmission percent  (per day)
G = 0.0001  # resurect percent (per day)
A = 0.0001  # destroy perecent (per day)
rates=(P,d,B,G,A)

# model initial conditions
#---------------------------------------------------
S0 = 500.               # initial population
Z0 = 0                  # initial zombie population
R0 = 0                  # initial death population
y0 = [S0, Z0, R0]      # initial condition vector

# model steps
#---------------------------------------------------
start_time=0.0
end_time=5.0
intervals=1000
mt=np.linspace(start_time,end_time,intervals)

# model index to compare to data
#----------------------------------------------------
findindex=lambda x:np.where(mt>=x)[0][0]
mindex=map(findindex,Td)
#=======================================================



#3.Score Fit of System
#=========================================================
def score(parms):
    #a.Get Solution to system
    F0,F1,F2,T=eq(parms,y0,start_time,end_time,intervals)
    #b.Pick of Model Points to Compare
    Zm=F1[mindex]
    #c.Score Difference between model and data points
    ss=lambda data,model:((data-model)**2).sum()
    return ss(Zd,Zm)
#========================================================


#4.Optimize Fit
#=======================================================
fit_score=score(rates)
answ=fmin(score,(rates),full_output=1,maxiter=1000000)
bestrates=answ[0]
bestscore=answ[1]
P,d,B,G,A=answ[0]
newrates=(P,d,B,G,A)
#=======================================================

#5.Generate Solution to System
#=======================================================
F0,F1,F2,T=eq(newrates,y0,start_time,end_time,intervals)
Zm=F1[mindex]
Tm=T[mindex]
#======================================================

现在在 #optimize fit 部分,当我限制 "rates" 的值时,有没有什么方法可以获得最好的 bestrates 值,比如 lb <= P, d, B, G, A < = ub where lb=lower bound and ub=upper bound and manage to get minimum score in that restricted region?它不一定是最优化的值。 fmin 使用 Nelder-Mead(单纯形)算法。

我对此很陌生,所以在正确方向上的任何帮助都会很棒。随时询问有关代码的任何疑问,我会尽我所知回答。 .谢谢。

不知道Adventures in Python : Fitting a Differential Equation System to Data的原作者为什么要绕圈子得到给定数据点对应的样本,通过传递给eq一个可以大大简化程序时间数组代替其构造参数

#=======================================================
def eq(par,initial_cond,t):
     #differential-eq-system----------------------
     def funct(y,t):
        Si, Zi, Ri=y
        P,d,B,G,A=par
        # the model equations (see Munz et al. 2009)
        f0 = P - B*Si*Zi - d*Si
        f1 = B*Si*Zi + G*Ri - A*Si*Zi
        f2 = d*Si + A*Si*Zi - G*Ri
        return [f0, f1, f2]
     #integrate------------------------------------
     ds = odeint(funct,initial_cond,t)
     return ds.T
#=======================================================

这可以称为

T = np.linspace(0, 5.0, 1000+1)
S,Z,R=eq(rates,y0,T)

但也可以只生成 score 函数

中所需的值
Tm=np.append([0],Td)
Sm,Zm,Rm=eq(rates,y0,Tm)

然后将得分函数简化为

def score(parms):
    #a.Get Solution to system
    Sm,Zm,Rm=eq(parms,y0,Tm)
    #c.Score Difference between model and data points
    ss=lambda data,model:((data-model)**2).sum()
    return ss(Zd,Zm[1:])

现在,如果您想要强烈拒绝负面参数,那么您可以将 return 值更改为

    return ss(Zd,Zm[1:]) + 1e6*sum(max(0,-x)**2 for x in parms)

这确实使所有参数都为正(以前在我的笔记本中第一个参数为负)。