我正在尝试用平滑函数(参数少于5个)(例如广义逻辑函数)来近似经验累积分布函数(ECDF I want to approximate)。
但是,使用scipy.optimize.curve_fit
时,拟合操作给出的近似值确实很差,或者根本不起作用(取决于初始值)。变量series
代表我的数据存储为pandas.Series
。
from scipy.optimize import curve_fit
def fit_ecdf(x):
x = np.sort(x)
def result(v):
return np.searchsorted(x, v, side='right') / x.size
return result
ecdf = fit_ecdf(series)
def genlogistic(x, B, M, Q, v):
return 1 / (1 + Q * np.exp(-B * (x - M))) ** (1 / v)
params = curve_fit(genlogistic, xdata = series, ydata = ecdf(series), p0 = (0.1, 10.0, 0.1, 0.1))[0]
我应该使用其他类型的函数进行拟合吗? 有代码错误吗?
更新-1
根据要求,我链接到包含the data的csv。
更新-2
经过大量搜索和反复试验后,我发现了此功能
f(x; a, b, c) = 1 - 1 / (1 + (x / b) ** a) ** c
with a = 4.61320000, b = 2.94570952, c = 0.5886922
比另一个更适合。唯一的问题是ECDF在x=1
附近显示了很小的步骤。如何修改f
以提高拟合质量?我正在考虑添加某种仅与这些要点“相关”的功能。这是拟合的图形结果,其中实线为ECDF,虚线表示(x, f(x))
点。
答案 0 :(得分:1)
我了解了如何处理x=1
附近的那一步。正如问题中所表达的那样,添加仅在该时间间隔内才有意义的某种功能就是改变游戏规则。
“步骤”大约在(1.7, 0.04)
处结束,因此我需要一种对x > 1.7
进行展平并具有y = 0.04
渐近线的函数。自然的选择(只为重点)是采用f(x) = 1/exp(x)
之类的函数。
多亏了詹姆斯·菲利普斯(JamesPhillips),我还为回归获得了正确的数据(没有双值=没有超重点)。
Python代码
from scipy.optimize import curve_fit
def fit_ecdf(x):
x = np.sort(x)
def result(v):
return np.searchsorted(x, v, side = 'right') / x.size
return result
ecdf = fit_ecdf(series)
unique_series = series.unique().tolist()
def cdf_interpolation(x, a, b, c, d):
f_1 = 0.95 + (0 - 0.95) / (1 + (x / b) ** a) ** c + 0.05
f_2 = (0 - 0.05)/(np.exp(d * x))
return f_1 + f_2
params = curve_fit(cdf_interpolation,
xdata = unique_series ,
ydata = ecdf(unique_series),
p0 = (6.0, 3.0, 0.4, 1.0))[0]
参数
a = 6.03256462
b = 2.89418871
c = 0.42997956
d = 1.06864006
图形结果
答案 1 :(得分:0)
我可以使用唯一值来拟合5参数逻辑方程式(请参见图像和代码),不确定下端曲线是否足以满足您的需求,请检查。
import numpy as np
def Sigmoidal_FiveParameterLogistic_model(x_in): # from zunzun.com
# coefficients
a = 9.9220221252324947E-01
b = -3.1572339989462903E+00
c = 2.2303376075685142E+00
d = 2.6271495036080207E-02
f = 3.4399008905318986E+00
return d + (a - d) / np.power(1.0 + np.power(x_in / c, b), f)