python - 在 SciPy 中拟合分布时如何检查收敛性

标签 python scipy distribution model-fitting convergence

在 SciPy 中拟合分布时有没有办法检查收敛性?
我的目标是将 SciPy 分布(即 Johnson S_U 发行版)拟合到数十个数据集,作为自动数据监控系统的一部分。大多数情况下它工作正常,但一些数据集异常并且显然不遵循 Johnson S_U 分布。适合这些数据集会悄无声息地发散,即没有任何警告/错误/无论如何!相反,如果我切换到 R 并尝试适应那里,我永远不会得到收敛,这是正确的 - 无论拟合设置如何,R 算法都拒绝声明收敛。
数据:
两个数据集是 available in Dropbox :

  • data-converging-fit.csv ...拟合很好地收敛的标准数据(您可能认为这是一个丑陋、倾斜且重心的 Blob ,但 Johnson S_U 足够灵活以适应这样的野兽!):

  • enter image description here
  • data-diverging-fit.csv ...拟合发散的异常数据:

  • enter image description here
    拟合分布的代码:
    import pandas as pd
    from scipy import stats
    
    distribution_name = 'johnsonsu'
    dist = getattr(stats, distribution_name)
    
    convdata = pd.read_csv('data-converging-fit.csv', index_col= 'timestamp')
    divdata  = pd.read_csv('data-diverging-fit.csv', index_col= 'timestamp')
    
    在好的数据上,拟合参数具有共同的数量级:
    a, b, loc, scale = dist.fit(convdata['target'])
    a, b, loc, scale
    
    [out]: (0.3154946859186918, 
     2.9938226613743932,
     0.002176043693009398,
     0.045430055488776266)
    
    在异常数据上,拟合参数不合理:
    a, b, loc, scale = dist.fit(divdata['target'])
    a, b, loc, scale
    
    [out]: (-3424954.6481554992, 
    7272004.43156841, 
    -71078.33596490842, 
    145478.1300979394)
    
    我仍然没有收到一条关于拟合未能收敛的警告。
    通过在 StackOverflow 上研究类似的问题,我知道将我的数据装箱然后使用 curve_fit 的建议。 .尽管它具有实用性,但我认为该解决方案并不正确,因为这不是我们拟合分布的方式:分箱是任意的(分箱数)并且它会影响最终拟合。更现实的选择可能是 scipy.optimize.minimize和回调以了解收敛的进展;我仍然不确定它最终会告诉我算法是否收敛。

    最佳答案

    johnsonu.fit方法来自 scipy.stats.rv_continuous.fit .不幸来自 documentation似乎无法从这种方法中获得有关拟合的更多信息。
    然而,看着source code ,看来实际的优化是用 fmin 完成的,它确实返回了更多的描述性参数。您可以借用源代码并编写自己的 fit 实现。检查 fmin收敛的输出参数:

    import numpy as np
    import pandas as pd
    from scipy import optimize, stats
    
    distribution_name = 'johnsonsu'
    dist = getattr(stats, distribution_name)
    
    convdata = pd.read_csv('data-converging-fit.csv', index_col= 'timestamp')
    divdata  = pd.read_csv('data-diverging-fit.csv', index_col= 'timestamp')
    
    def custom_fit(dist, data, method="mle"):
        data = np.asarray(data)
        start = dist._fitstart(data)
        args = [start[0:-2], (start[-2], start[-1])]
        x0, func, restore, args = dist._reduce_func(args, {}, data=data)
        vals = optimize.fmin(func, x0, args=(np.ravel(data),))
        return vals
    
    custom_fit(dist, convdata['target'])
    
    [out]: Optimization terminated successfully.
             Current function value: -23423.995945
             Iterations: 162
             Function evaluations: 274
    array([3.15494686e-01, 2.99382266e+00, 2.17604369e-03, 4.54300555e-02])
    
    custom_fit(dist, divdata['target'])
    
    [out]: Warning: Maximum number of function evaluations has been exceeded.
    array([-12835849.95223926,  27253596.647191  ,   -266388.68675908,
              545225.46661612])
    

    关于python - 在 SciPy 中拟合分布时如何检查收敛性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68770788/

    相关文章:

    c++ - 在 C++11 中的类中的不同方法之间共享 random_number_engine

    statistics - 如何从多项分布中采样?

    二维数组的 Python Earth Mover 距离

    python - 敌人 Sprite 没有正确跟随玩家

    python - 用python消除列表中的空元素

    Python fsolve 值错误

    optimization - 提取并设置 numpy 数组的粗对角线

    python - Flask SQLAlchemy 从查询结果中的两个连接的映射实体获取列

    python - 根据值拆分Pandas Dataframe列

    python - 为什么两个机器上安装了不同版本的 numpy 和 scipy