почему curve_fit не сходится для соответствия бета-функции? - PullRequest
0 голосов
/ 04 июня 2018

У меня небольшая проблема с моим кодом Python, когда я пытаюсь подогнать бета-функцию к нескольким точкам.Проблема в том, что либо решение не сходится (и результирующие коэффициенты равны nans), либо оно ничего не делает (при результатах остаются такими же, как мое первоначальное предположение), либо оно, очевидно, соответствует, но тогда подгонка не похожак точкам данных вообще.Я читал похожие посты о бета-функции и о curve_fit, потому что оба вопроса обсуждаются в литературе по stackoverflow, но я не смог найти решение конкретной проблемы, которая у меня есть, поэтому мне было интересно, могли бы вы датьУ меня есть некоторые идеи.

У меня есть набор точек:

x = np.array([0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array([0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153,
   0.]

, и затем я пытаюсь подобрать их с помощью функции gamma, используя curve_fit следующим образом:

from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst):
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )
popt2,pcov2 = curve_fit(betafunc,x,y,p0=(0.5,1.5,0.5))

И вот тут возникает моя проблема, потому что в зависимости от моего первоначального предположения я получаю либо popt2=[nan,nan,nan], либо popt2=p0, либо несколько раз значения, которые при построении не имитируют данные вообще.

Я также знаю, что бета-функция предназначена для 0 enter image description here,

...Я уже установил другой профиль (который также использует три свободных параметра), и с ним нет проблем, поэтому я не понимаю, почему этот другой бета-профиль не работает.Любое руководство приветствуется!

1 Ответ

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

Ваша реализация предназначена для функции плотности вероятности бета-распределения (а не бета-функции).Он определяется в интервале 0 <= x <= 1. Следовательно, ваши независимые данные (координата x) должны быть полностью в этом интервале.То, как вы это обеспечите, зависит от более широкого контекста того, что вы пытаетесь сделать.Возможные подходы включают сокращение или отображение на некоторую часть интервала. </p>

Следуя вашему примеру, следующее (сокращение) выполняется без ошибок:

import numpy as np
from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst):
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )

x = np.array( [0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array( [0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153, 0.] )


popt2,pcov2 = curve_fit(betafunc,x[:-1],y[:-1],p0=(0.5,1.5,0.5))

print popt2
print pcov2

и выдает результат:

[ 1.22624727  1.74192827  0.37084996]
[[ 0.03758865  0.04888083 -0.00132468]
 [ 0.04888083  0.09142608 -0.00309165]
 [-0.00132468 -0.00309165  0.00094766]]

И это также (масштабирование x) выполняется без ошибок:

import numpy as np
from scipy.optimize import curve_fit
from scipy.special import gamma as gamma
def betafunc(x,a,b,cst,scale):
    x = x / scale
    return cst*gamma(a+b) * (x**(a-1)) * ((1-x)**(b-1))  / ( gamma(a)*gamma(b) )

x = np.array( [0.1, 0.3, 0.5, 0.7, 0.9, 1.1])
y = np.array( [0.45112234, 0.56934313, 0.3996803 , 0.28982859, 0.19682153, 0.] )

popt2,pcov2 = curve_fit(betafunc,x,y,p0=(0.5,1.5,0.5,1.1))

print popt2
print pcov2

и выдает результат:

[ 1.37100253  2.36832069  0.32337175  1.16052822]
[[ 0.04972377  0.15943756 -0.00792804  0.02550767]
 [ 0.15943756  0.71001918 -0.04180131  0.14426687]
 [-0.00792804 -0.04180131  0.00312037 -0.00983075]
 [ 0.02550767  0.14426687 -0.00983075  0.0373759 ]]

Обратите внимание, что во втором примере xмасштабирование диапазона также является одной из подходящих переменных.Но это также может быть постоянным в зависимости от вашей проблемы.Все зависит от вашего контекста.

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

...