以下是ODE参数最小二乘拟合的代码。使用了Python的“最小化”和“最小二乘”功能。已经尝试了不同的方法和ODE求解器/步骤(scipy ode / odeint)。这个问题已经在MATLAB中轻松解决,但是Python不断返回初始猜测。我希望您发现编码错误,否则我会对Python优化功能感到失望。 Obj显示目标(残差平方和),而ode函数(一阶)显示参数未知的方程。数据集已附加。
import numpy as np
from scipy.integrate import ode
from scipy.optimize import least_squares
from scipy.optimize import minimize
from scipy.optimize import SR1
import matplotlib.pyplot as plt
import math
Minput=np.loadtxt('C:\\Users\\Ladan\\Documents\\Python Scripts\\Python\\moisturesmoothopt.txt')
Minput=Minput.flatten()
time=np.linspace(0,1800,901)
A=np.zeros(3)
XC,RC,alpha=A
#bnds=([0,0,0],[Minput[0],math.inf,math.inf])
bnds=((0,Minput[0]),(0,math.inf),(0,math.inf))
def firstorder(X,time,A):
if X>=XC:
dX=-RC
if X<XC:
dX=-RC*(X/XC)**alpha
return dX
def obj(A):
X0=Minput[0]
# Xpred=odeint(firstorder,X0,time,args=(A,))
Xpred=ode(firstorder).set_integrator('vode', method='bdf',
order=15).set_initial_value(Minput[0],0).set_f_params(A)
#Xpred=ode(firstorder).set_integrator('lsoda').set_initial_value(Minput[0],0).set_f_params(A)
EPR=Xpred
EPR2=EPR.y.flatten()
ERRone=np.sum(np.power((EPR2-Minput),2))
ERR=ERRone/((901-3)) # residual sum of squares deivided by dof
return ERR
XC=1
RC=0.005
alpha=1.5
A0=[XC,RC,alpha]
Parameters=minimize(obj,A0,method='SLSQP',bounds=bnds,options={'ftol':1e-10,
'maxiter': 1000})
print('parameters',Parameters)
Minput数组的数据在线共享:
答案 0 :(得分:0)
尽管我在scipy中使用了较新的ode求解器,但我倾向于偏爱良好的ol'odeint
函数,该函数虽然年代久远,但仍然相当可靠,并且由于我不喜欢的原因在许多情况下提供了更好的性能不太了解。无论如何,我在很大程度上重组了您的分析代码,以同时使用scipy.optimize.least_squares
和scipy.integrate.odeint
。已经取得了进展,但是我确实收到有关电源中无效值的某种警告。您将需要做进一步的调查,但这应该可以使您走上正确的轨道
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint
from scipy.optimize import least_squares
Minput=np.loadtxt('Data.txt').T
time=np.linspace(0,1800,901)
bnds=([0,0,0],[Minput[0],np.inf,np.inf])
def firstorder(X,time, XC, RC, alpha):
if X >= XC:
dX = -RC
else:
dX = -RC * (X/XC)**alpha
return dX
XC=1
RC=0.005
alpha=1.5
A0=(XC, RC, alpha)
def residuals(x0):
Mcalc = odeint(firstorder, y0=Minput[0], t=time, args=tuple(x0))[:,0]
return Mcalc - Minput
Mcalc = odeint(firstorder, y0=Minput[0], t=time, args=A0)[:,0]
result = least_squares(residuals, x0=A0, bounds=bnds)
print(result)
Mfit = odeint(firstorder, y0=Minput[0], t=time, args=tuple(result.x))[:,0]
plt.plot(time, Minput, label='data')
plt.plot(time, Mcalc, label='initial values')
plt.plot(time, Mfit, label='fit')
plt.legend()
打印出:
/---/python3.6/site-packages/ipykernel_launcher.py:20: RuntimeWarning: invalid value encountered in power
active_mask: array([0, 0, 0])
cost: 50.571520689865935
fun: array([ 0.00000000e+00, 8.14148814e-03, 1.61829763e-02, 2.44244644e-02,
...])
grad: array([-1.18907831, nan, -7.75389712])
jac: array([[ 0. , 0. , 0. ],
[ 0. , -2. , 0. ],
[ 0. , -3.99999994, 0. ],
...,
[ 0.07146036, nan, 0.1084222 ],
[ 0.07130456, nan, 0.10827456],
[ 0.07114924, nan, 0.1081272 ]])
message: '`xtol` termination condition is satisfied.'
nfev: 30
njev: 12
optimality: nan
status: 3
success: True
x: array([1.0000002 , 0.00717926, 1.50000032])