如何根据 Python 中数据集的最佳拟合确定微分方程的未知参数?
How to determine unknown parameters of a differential equation based on the best fit to a data set in Python?
我正在尝试用 python 将不同的微分方程拟合到给定的数据集。为此,我分别使用 scipy 包和 solve_ivp 函数。
这对我来说很好,只要我对微分方程中包含的参数 (b= 0.005) 有粗略估计,例如:
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
import numpy as np
def f(x, y, b):
dydx= [-b[0] * y[0]]
return dydx
xspan= np.linspace(1, 500, 25)
yinit= [5]
b= [0.005]
sol= solve_ivp(lambda x, y: f(x, y, b),
[xspan[0], xspan[-1]], yinit, t_eval= xspan)
print(sol)
print("\n")
print(sol.t)
print(sol.y)
plt.plot(sol.t, sol.y[0], "b--")
然而,我想要实现的是,参数 b(或更多参数)is/are 根据求解的微分方程与给定数据集(x 和y)。有没有一种方法可以做到这一点,例如通过将此示例与 scipy 的 curve_fit 函数结合起来,这看起来如何?
提前致谢!
是的,你想的应该可行,应该很容易插在一起。你想打电话给
popt, pcov = scipy.optimize.curve_fit(curve, xdata, ydata, p0=[b0])
b = popt[0]
您现在必须定义一个函数 curve(x,*p)
,它根据唯一的参数 b
.
将任何点列表转换为值列表
def curve(x,b):
res = solve_ivp(odefun, [1,500], [5], t_eval=x, args = [b])
return res.y[0]
根据需要为容错添加可选参数。
为了使这更真实,也将初始点作为参数。然后它也变得更加明显,哪里需要列表,哪里需要单个参数。要获得合适的拟合任务,请向测试数据添加一些随机噪声。也让归零不要那么快,这样最后的剧情看起来还是有些意思的。
from scipy.integrate import solve_ivp
from scipy.optimize import curve_fit
xmin,xmax = 1,500
def f(t, y, b):
dydt= -b * y
return dydt
def curve(t, b, y0):
sol= solve_ivp(lambda t, y: f(t, y, b),
[xmin, xmax], [y0], t_eval= t)
return sol.y[0]
xdata = np.linspace(xmin, xmax, 25)
ydata = np.exp(-0.02*xdata)+0.02*np.random.randn(*xdata.shape)
y0 = 5
b= 0.005
p0 = [b,y0]
popt, pcov = curve_fit(curve, xdata, ydata, p0=p0)
b, y0 = popt
print(f"b={b}, y0 = {y0}")
这个returns
b=0.019975693539459473, y0 = 0.9757709108115179
现在根据拟合曲线绘制测试数据
我正在尝试用 python 将不同的微分方程拟合到给定的数据集。为此,我分别使用 scipy 包和 solve_ivp 函数。 这对我来说很好,只要我对微分方程中包含的参数 (b= 0.005) 有粗略估计,例如:
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
import numpy as np
def f(x, y, b):
dydx= [-b[0] * y[0]]
return dydx
xspan= np.linspace(1, 500, 25)
yinit= [5]
b= [0.005]
sol= solve_ivp(lambda x, y: f(x, y, b),
[xspan[0], xspan[-1]], yinit, t_eval= xspan)
print(sol)
print("\n")
print(sol.t)
print(sol.y)
plt.plot(sol.t, sol.y[0], "b--")
然而,我想要实现的是,参数 b(或更多参数)is/are 根据求解的微分方程与给定数据集(x 和y)。有没有一种方法可以做到这一点,例如通过将此示例与 scipy 的 curve_fit 函数结合起来,这看起来如何?
提前致谢!
是的,你想的应该可行,应该很容易插在一起。你想打电话给
popt, pcov = scipy.optimize.curve_fit(curve, xdata, ydata, p0=[b0])
b = popt[0]
您现在必须定义一个函数 curve(x,*p)
,它根据唯一的参数 b
.
def curve(x,b):
res = solve_ivp(odefun, [1,500], [5], t_eval=x, args = [b])
return res.y[0]
根据需要为容错添加可选参数。
为了使这更真实,也将初始点作为参数。然后它也变得更加明显,哪里需要列表,哪里需要单个参数。要获得合适的拟合任务,请向测试数据添加一些随机噪声。也让归零不要那么快,这样最后的剧情看起来还是有些意思的。
from scipy.integrate import solve_ivp
from scipy.optimize import curve_fit
xmin,xmax = 1,500
def f(t, y, b):
dydt= -b * y
return dydt
def curve(t, b, y0):
sol= solve_ivp(lambda t, y: f(t, y, b),
[xmin, xmax], [y0], t_eval= t)
return sol.y[0]
xdata = np.linspace(xmin, xmax, 25)
ydata = np.exp(-0.02*xdata)+0.02*np.random.randn(*xdata.shape)
y0 = 5
b= 0.005
p0 = [b,y0]
popt, pcov = curve_fit(curve, xdata, ydata, p0=p0)
b, y0 = popt
print(f"b={b}, y0 = {y0}")
这个returns
b=0.019975693539459473, y0 = 0.9757709108115179
现在根据拟合曲线绘制测试数据