scipy:用fmin和odeint找到最佳参数,不合适

时间:2015-11-24 20:51:50

标签: python numpy scipy

下面我解决了描述弹簧质量缓冲器系统的二阶ODE:u''+ c u'+ k u = 0。我对odeint求解器没有任何问题.odeint函数在指定时间内正确求解位置U(t)。

#modeling spring mass system
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy import integrate

#Make the following substitution to make system first order
#Y[1]=y′(t) and Y[0]=y(t),
#system: Y[0]'=Y[1] and Y[1]'=-c*Y[1]-k*Y[0]


#=======================================================
def eq(par,initial_cond,start_t,end_t,incr):
     #-time-grid-----------------------------------
     t  = np.linspace(start_t, end_t,incr)
     #differential-eq-system----------------------
     def funct(y,t):
        ut=y[0]
        ut_dt=y[1]
        c,k=par
        # the model equations u'=Y[1], u''=-k*Y[0]-c*Y[1] from u''+c*u'+k*u=0
        f0 =ut_dt
        f1 =-k*ut-c*ut_dt
        return [f0, f1]
     #integrate------------------------------------
     ds = integrate.odeint(funct,initial_cond,t)
     return (ds[:,0],ds[:,1],t)
#=======================================================

#parameters   
c=2. #spring coefficient 
k=10. #dampening coefficient

#collect parameters in tuple
coefs=(c,k)

# initial conditions

u0=6.
ud0=0.
y0=[u0,ud0]

start,stop,incr=0,20,100

#Solve and plot solution
F0,F1,T=eq(coefs,y0,start,stop,incr)
plt.figure()
plt.plot(T,F0,'-b',T,F1,'-r')
plt.legend(('u0', 'u1'),'upper center')
plt.title('Mass-Spring System')

但是,如果给定模拟测量,我想使用scipy.optimize.fmin()来找到该系统的最佳拟合参数(c,k)。所以我使用上面的解决方案,其中c = 2,k = 10,并添加随机噪声。

rand_i=randn(incr)
#noiselevel
nl=.05
noisy_data=F0+nl*rand_i
plt.plot(noisy_data,label="noisy_data:c=2,k=10")
plt.legend()

接下来,我为fmin()设置了一个评分函数以最小化。我猜测参数,c = 1,k = 1。

from scipy.optimize import fmin

#1.Get 'Real' Data
#====================================================
nd=noisy_data#solution with parameters: c=2,k=10
#====================================================

#2.Set up Info for Model System
#===================================================
# guess parameters   
c=1 #spring coefficient 
k=1 #dampening coefficient

#collect parameters in tuple
coefs=(c,k)

# initial conditions
u0=6.
ud0=0.
y0=[u0,ud0]

# model steps
#---------------------------------------------------
start_time=0
end_time=20
intervals=100
mt=np.linspace(start_time,end_time,intervals)

#3.Score Fit of System
#=========================================================
def score(parms):
    #a.Get Solution to system
    F0,F1,T=eq(coefs,y0,start_time,end_time,intervals)
    #b.Pick of Model Points to Compare
    um=F0
    #c.Score Difference between model(ode output) and data points (noisy data)
    ss=lambda data,model:((data-model)**2).sum()
    return ss(nd,um)
#========================================================


#4.Optimize Fit
#=======================================================
fit_score=score(coefs)
answ=fmin(score,(coefs))

问题是fmin找不到正确的参数。它发现即使得分函数很高,猜测参数也是最好的。下面我打印fmin解答,并显示即使在调用fmin()之后它与初始猜测相同。

print(answ==[c,k])

有谁知道为什么fmin()找不到正确的参数,c = 2,k = 10?

1 个答案:

答案 0 :(得分:0)

您的代码中存在一个微不足道的错误:您使用输入参数score定义parms,但随后将所述变量称为coefs。修正:

def score(coefs): #changed
    #a.Get Solution to system
    F0,F1,T=eq(coefs,y0,start_time,end_time,intervals)
    #b.Pick of Model Points to Compare
    um=F0
    #c.Score Difference between model(ode output) and data points (noisy data)
    ss=lambda data,model:((data-model)**2).sum()
    return ss(nd,um)

在:

In [369]: answ
Out[369]: array([ 1.,  1.])

后:

In [373]: answ
Out[373]: array([ 2.0425695 ,  9.96937966])

但是,请注意answ==(c,k) 总是 False,即使是完美契合:您正在使用浮点数。任何有意义的比较应该看起来像max(abs(answ-[2,10])/abs(answ))<tol或类似的东西。 (我知道您的原始问题用于表明值没有更改,但仍然。)