scipy curve_fit возвращает начальные оценки - PullRequest
0 голосов
/ 05 июня 2018

Чтобы соответствовать гиперболической функции, я пытаюсь использовать следующий код:

import numpy as np
from scipy.optimize import curve_fit

def hyperbola(x, s_1, s_2, o_x, o_y, c):
    # x > Input x values
    # s_1 > slope of line 1
    # s_2 > slope of line 2
    # o_x > x offset of crossing of asymptotes
    # o_y > y offset of crossing of asymptotes
    # c   > curvature of hyperbola

    b_2 = (s_1 + s_2) / 2
    b_1 = (s_2 - s_1) / 2

    return o_y + b_1 * (x - o_x) + b_2 * np.sqrt((x - o_x) ** 2 + c ** 2 / 4)

min_fit = np.array([-3.0, 0.0, -2.0, -10.0, 0.0])
max_fit = np.array([0.0, 3.0, 3.0, 0.0, 10.0])
guess = np.array([-2.5/3.0, 4/3.0, 1.0, -4.0, 0.5])

vars, covariance = curve_fit(f=hyperbola, xdata=n_step, ydata=n_mean, p0=guess, bounds=(min_fit, max_fit))

Где n_step и n_mean - это значения измерений, сгенерированные ранее.Код работает нормально и не выдает сообщения об ошибках, но возвращает только начальное предположение с очень небольшим изменением.Также ковариационная матрица содержит только нули.Я попытался сделать то же самое с лучшим начальным предположением, но это не имеет никакого влияния.Кроме того, я построил точно такую ​​же функцию с исходным предположением в качестве входных данных, и это действительно дает мне функцию, близкую к реальным значениям.Кто-нибудь знает, где я здесь ошибаюсь?Или я использую неправильную функцию, чтобы привести себя в форму?

1 Ответ

0 голосов
/ 05 июня 2018

Проблема должна быть с n_step и n_mean (которые не указаны в вопросе, как указано в настоящее время);при попытке воспроизвести проблему с каким-либо произвольно выбранным набором входных параметров оптимизация работает, как и ожидалось.Давайте попробуем.

Во-первых, давайте определим некоторые произвольно выбранные входные параметры в данном пространстве параметров как

params = [-0.1, 2.95, -1, -5, 5]

Давайте посмотрим, как это выглядит:

import matplotlib.pyplot as plt
xs = np.linspace(-30, 30, 100)
plt.plot(xs, hyperbola(xs, *params))

enter image description here

Исходя из этого, давайте определим некоторые довольно грубые входные данные для xdata и ydata с помощью

xdata = np.linspace(-30, 30, 10)
ydata = hyperbola(xs, *params)

С этими, давайтезапустите оптимизацию и посмотрите, соответствуют ли мы нашим заданным параметрам:

vars, covariance = curve_fit(f=hyperbola, xdata=xdata, ydata=ydata, p0=guess, bounds=(min_fit, max_fit))
print(vars)  # [-0.1   2.95 -1.   -5.    5.  ]

То есть, идеально подходит, даже если наши params довольно отличаются от наших guess.Другими словами, если мы можем свободно выбирать n_step и n_mean, то метод работает, как и ожидалось.

Чтобы попытаться немного усложнить оптимизацию, мы могли бы также попытаться добавить немногошум:

np.random.seed(42)
xdata = np.linspace(-30, 30, 10)
ydata = hyperbola(xdata, *params) + np.random.normal(0, 10, size=len(xdata))
vars, covariance = curve_fit(f=hyperbola, xdata=xdata, ydata=ydata, p0=guess, bounds=(min_fit, max_fit))
print(vars)  #  [ -1.18173287e-01   2.84522636e+00  -1.57023215e+00  -6.90851334e-12   6.14480856e-08]
plt.plot(xdata, ydata, '.')
plt.plot(xs, hyperbola(xs, *vars))

enter image description here

Здесь мы отмечаем, что оптимум заканчивается тем, что он отличается от наших предоставленных params и guess, однаков пределах, предусмотренных min_fit и max_fit, и все еще при условии хорошей подгонки.

...