无法使用scipy.optimize.curve_fit拟合ECDF

时间:2018-08-31 11:39:18

标签: python scipy curve-fitting

我正在尝试用平滑函数(参数少于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))点。

Here are the graphical results of the fit

2 个答案:

答案 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

图形结果 ECDF & Inferred CDF

答案 1 :(得分:0)

我可以使用唯一值来拟合5参数逻辑方程式(请参见图像和代码),不确定下端曲线是否足以满足您的需求,请检查。 enter image description here

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)