Разница между алгоритмом Левенберга-Марквардта и ODR

Я смог подогнать кривые к набору данных х / у, используяПик-O-MAT, как показано ниже. Это линейный фон и 10 лоренцевских кривых. Peak-o-mat results

Так как мне нужно подогнать много похожих кривых, я написал скриптовую процедуру подгонки, используяmpfit.py, который является алгоритмом Левенберга-Марквардта. Однако подгонка занимает больше времени и, на мой взгляд, менее точна, чем результат пиковой нагрузки:

Starting values Starting values

Fit result with fixed linear background (значения для линейного фона взяты из пикового результата) Fit fixed

Fit result with all variables free Fit free

Я считаю, что начальные значения уже очень близки, но даже с фиксированным линейным фоном левый лоренц явно ухудшает подгонку.

Результат еще хуже для полной свободной подгонки.

Peak-o-mat, кажется, используетscipy.odr.odrpack, Теперь, что более вероятно:

I did some implementation error? odrpack is more suitable for this particular problem?

Подгонка к более простой задаче (линейные данные с одним пиком посередине) показывает очень хорошую корреляцию между вершинами и моим сценарием. Также я не нашел много о ordpack.

Edit: Кажется, я мог бы ответить на вопрос сам, однако ответ немного тревожит. Использование scipy.odr (которое позволяет использовать метод odr или leastsq) позволяет получить результат как peak-o-mat, даже без ограничений.

На рисунке ниже снова показаны данные, начальные значения (почти идеальные), а затем значения odr и leastsq. Кривые компонентов для одра

scipy.odr

Я переключусь на odr, но это все равно оставляет меня расстроенным. Методы (mpfit.py, scipy.optimize.leastsq, scipy.odr в режиме leastsq) «должны»; дают одинаковые результаты.

И для людей, спотыкающихся об этом посте: для подбора odr должна быть указана ошибка для значений x и y. Если ошибки нет, используйте маленькие значения с sx & lt; & lt; с.

linear = odr.Model(f)
mydata = odr.RealData(x, y, sx = 1e-99, sy = 0.01)
myodr = odr.ODR(mydata, linear, beta0 = beta0, maxit = 2000)
myoutput1 = myodr.run() 

Ответы на вопрос(1)

Ваш ответ на вопрос