2013-04-25 3 views
2

Хорошо, как бы я подошел к написанию кода для оптимизации констант a и b в дифференциальном уравнении, например dy/dt = a * y^2 + b, используя curve_fit? Я бы использовал odeint для решения ODE, а затем curve_fit для оптимизации a и b. Если бы вы могли представить информацию об этой ситуации, я бы очень признателен!Оптимизация констант в дифференциальных уравнениях в Python

ответ

4

Возможно, вам будет лучше сгенерировать ODEs with Sympy. Scipy/Numpy являются фундаментально численными пакетами и на самом деле не созданы для выполнения алгебраических/символических операций.

+0

Спасибо, что интересно и может помочь, например, что я хочу делать с дифференциальным уравнением, когда-то решаемым odeint, является оптимизация одной или двух констант с помощью curve_fit. вы думаете, мне придется использовать sympy для этого или есть другой способ? – user2199360

+0

Более подходящая ссылка для SymPy: http://docs.sympy.org/dev/modules/solvers/ode.html –

+0

@ user2199360: пока Scipy не настроен для символических операций, Sympy не настроен для числовых операций как оптимизация. Если вы используете curvefit, тип кривой, который вы подгоняете, может предоставить вам интерпретацию числовых результатов, которые вы можете использовать для создания символической функции (например, если параметры являются полиномиальными коэффициентами, то вы можете использовать их для записи полином в символической форме). Возможно, если вы отредактируете свой вопрос, чтобы описать общую задачу, которую вы пытаетесь выполнить, люди могут дать более полезный вклад. – BrenBarn

4

Вы, безусловно, можете сделать это:

import numpy as np 
from scipy.integrate import odeint 
from scipy.optimize import curve_fit 

def f(y, t, a, b): 
    return a*y**2 + b 

def y(t, a, b, y0): 
    """ 
    Solution to the ODE y'(t) = f(t,y,a,b) with initial condition y(0) = y0 
    """ 
    y = odeint(f, y0, t, args=(a, b)) 
    return y.ravel() 

# Some random data to fit 
data_t = np.sort(np.random.rand(200) * 10) 
data_y = data_t**2 + np.random.rand(200)*10 

popt, cov = curve_fit(y, data_t, data_y, [-1.2, 0.1, 0]) 
a_opt, b_opt, y0_opt = popt 

print("a = %g" % a_opt) 
print("b = %g" % b_opt) 
print("y0 = %g" % y0_opt) 

import matplotlib.pyplot as plt 
t = np.linspace(0, 10, 2000) 
plt.plot(data_t, data_y, '.', 
     t, y(t, a_opt, b_opt, y0_opt), '-') 
plt.gcf().set_size_inches(6, 4) 
plt.savefig('out.png', dpi=96) 
plt.show() 

0

Для решения конкретно этот тип проблемы, я решил написать пакет оболочку, которая объединяет sympy и scipy. Это называется symfit. Место для вашей ОДУ будет выглядеть следующим образом:

tdata = np.array([10, 26, 44, 70, 120]) 
ydata = 10e-4 * np.array([44, 34, 27, 20, 14]) 
y, t = variables('y, t') 
a, b = parameters('a, b') 

model_dict = { 
    D(y, t): a*y^2 + b 
} 

ode_model = ODEModel(model_dict, initial={t: 0.0, y: 0.0}) 

fit = Fit(ode_model, t=tdata, y=ydata) 
fit_result = fit.execute() 

Как вы можете видеть, как она определяется как Dict, не подходящая для систем (первого порядка) ОДУ не является проблемой. Проверьте docs для получения дополнительной информации!