Ортогональная регрессионная подгонка в методе наименьших квадратов scipy

метод leastsq в scipy lib соответствует кривой для некоторых данных. И этот метод подразумевает, что в этих данных значения Y зависят от некоторого аргумента X. И вычисляет минимальное расстояние между кривой и точкой данных по оси Y (dy)

но что, если мне нужно рассчитать минимальное расстояние по обеим осям (dy и dx)

есть ли какие-то способы реализовать этот расчет?

вот пример кода при использовании одной оси расчет:

import numpy as np
from scipy.optimize import leastsq

xData = [some data...]
yData = [some data...]

def mFunc(p, x, y):
    return y - (p[0]*x**p[1])  # is takes into account only y axis

plsq, pcov = leastsq(mFunc, [1,1], args=(xData,yData))
print plsq

недавно я попробовал scipy.библиотека odr и возвращает правильные результаты только для линейной функции. Для других функций, таких как y=a*x^b, он возвращает неправильные результаты. Вот как я его использую:

def f(p, x):      
    return p[0]*x**p[1]

myModel = Model(f)
myData = Data(xData, yData)
myOdr = ODR(myData, myModel , beta0=[1,1])
myOdr.set_job(fit_type=0) #if set fit_type=2, returns the same as leastsq
out = myOdr.run()
out.pprint()

Это возвращает неправильные результаты, не нужные, а в некоторых входных данных даже не близки к реальным. Может быть, есть какие-то особые способы его использования, что я делаю неправильно?

3 ответов


scipy.odr реализует регрессию ортогонального расстояния. Смотрите инструкции для основного использования в docstring:

https://github.com/scipy/scipy/blob/master/scipy/odr/odrpack.py#L27


Я нашел решение. Scipy Odrpack работает норамально, но для правильных результатов ему нужно хорошее начальное предположение. Поэтому я разделил процесс на два этапа.

первый шаг: найдите начальную догадку, используя метод наименьших квадратов ordinaty.

второй шаг: substitude эти начальные догадки в ODR как параметр beta0.

и он работает очень хорошо с приемлемой скоростью.

Спасибо, ребята, ваш совет направил меня к правильному решению


Если/когда вы сможете инвертировать функцию, описанную p, вы можете просто включить x-pinverted (y) в mFunc, я думаю, как sqrt(a^2+b^2), поэтому (псевдо-код)

return sqrt( (y - (p[0]*x**p[1]))^2 + (x - (pinverted(y))^2)

например

y=kx+m   p=[m,k]    
pinv=[-m/k,1/k]

return sqrt( (y - (p[0]+x*p[1]))^2 + (x - (pinv[0]+y*pinv[1]))^2)

но то, что вы просите в некоторых случаях проблематично. Например, если полиномиальная (или ваша кривая X^j) имеет минимум ym в y(m), и у вас есть точка x, y ниже ym, какое значение вы хотите вернуть? Не всегда есть решение.