подгонка параметров ODE при использовании решателя ODE octave / matlab
-
18-09-2019 - |
Вопрос
Я использую OdePkg в Octave для решения системы жестких ODE, напримеравтор ode5r:
function yprime = myODEs(t,Y,param)
yprime = [
- param(1) * Y(1); # ODE for Y(1)
param(1) * Y(1) - param(2) Y(2) * Y(3); # ODE for Y(2)
param(2) Y(2) * Y(3) # ODE for Y(3)
# etc.
];
time_span = [1, 24] # time span of interest
Y0 = [1.0, 1.1, 1.3] # initial values for dependent variables Y
param = [7.2, 8.6, 9.5] # parameters, to be optimized
[t, Y] = ode5r(@myODEs, time_span, Y0, ..., param);
Решатель сохраняет зависимые переменные Y в матрице относительно времени t (вектор):
t Y(1) Y(2) Y(3)
0.0 1.0 1.1 1.3
0.1 ... ... ...
0.5 ... ... ...
0.9 ... ... ...
... ... ... ...
4.0 ... ... ...
... ... ... ...
24.0 ... ... ...
Я хочу подогнать параметры в param, чтобы результирующие переменные Y наилучшим образом соответствовали моим эталонным значениям, например:
t Y(1) Y(2) Y(3)
0.5 1.1 N/A N/A
1.0 1.9 N/A N/A
4.0 2.3 2.7 2.1
5.0 N/A 2.6 2.2
24.0 0.9 1.5 2.0
Какая процедура Octave / Matlab (другие языки приветствуются) может выполните многопараметрическую подгонку (наименьший квадрат / сплайн)?Как это возможно, чтобы объедините наборы параметров для разных начальных значений Y0 в припадке?Я был бы рад, если бы вы могли дать мне несколько советов и возможностей.
С наилучшими пожеланиями, Саймон
Решение
С scipy это должно быть относительно просто. scipy.optimize.leastsq()
принимает функцию, которая должна возвращать массив остатков для заданного вектора параметров.Это сведет к минимуму сумму квадратов остатков.Чтобы обрабатывать несколько наборов данных с разными начальными значениями, вы просто запускаете ODE один раз для каждого набора данных, вычисляете остатки для каждой пары набор данных / запуск, а затем объединяете остаточные векторы вместе.Вот приблизительный набросок:
import numpy
from scipy import integrate, optimize
# The initial guess.
p0 = numpy.array([7.2, 8.6, 9.5])
# The collected datasets.
# A list of (t, y0, y) tuples.
# The y's are all (len(y0), len(t))-shaped arrays. The output of
# integrate.odeint is also in this format.
datasets = [...]
def odes(y, t, params):
dydt = [
-params[0] * y[0],
params[0]*y[0] - params[1]*y[1]*y[2],
params[1]*y[1]*y[2],
]
return np.array(dydt)
def residuals(params, datasets):
res = []
for t, y0, y in datasets:
res.append(integrate.odeint(odes, y0, t, args=(params,)) - y)
# Stack them horizontally and flatten the array into the expected vector.
# You're on your own for handling missing data. Look into the numpy.ma
# module.
all_residuals = numpy.hstack(res).ravel()
return all_residuals
opt_params, err = optimize.leastsq(residuals, p0, args=(datasets,))
Другие советы
Вы имеете в виду, что каждая функция y (t) должна быть установлена?В этом случае подгонка арендуемых квадратов или сплайнов для каждого набора Yi в зависимости от времени будет работать просто отлично.Не могу сказать, какой из них был бы лучшим, не видя ваших данных.
Вам придется придумать другую независимую переменную, если вы имеете в виду, что хотите подогнать кривую под все значения Yi для данного момента времени, а затем наблюдать, как эта кривая развивается с течением времени.
Обновить:Подгонка по методу наименьших квадратов - вот что это такое - у меня нет конкретной процедуры, которую я мог бы порекомендовать. У Сципи есть один, Я уверен.Мне жаль, что у меня нет лучшей рекомендации.Я только сейчас изучаю Python.
Я не знаю, что вы подразумеваете под "показателем пригодности".Подгонка по методу наименьших квадратов вычисляет коэффициенты, которые минимизируют среднеквадратичную ошибку между подгонкой и данными в каждой точке.
Всего лишь один способ объединить несколько наборов данных в единую подгонку:объедините их и повторно запустите вычисление.
Я разработал комплексный набор инструментов Matlab для подгонки параметров и начальных значений ODE к нескольким наборам экспериментальных данных.Он может обрабатывать различные начальные значения в зависимости от каждого эксперимента и доступен по адресу www.potterswheel.de.