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

问题描述 投票:0回答:2

我想用一个平滑函数(小于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))点。

python scipy curve-fitting
2个回答
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

图形结果


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)
© www.soinside.com 2019 - 2024. All rights reserved.