微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

初始化 Python 自定义分发

如何解决初始化 Python 自定义分发

我在 Scipy 中使用自定义对数伽马分布,我想将它与各种预定义的 Scipy 分布一起使用。我的问题是自定义分发似乎需要与预定义分发有所不同。具体来说,似乎我需要先初始化自定义分发才能使用它。见下文:

import matplotlib.pyplot as plt
import pandas as pd

import numpy as np
from scipy.stats import gamma
from scipy.special import gamma as gamma_func
from scipy.special import erf,erfinv
from scipy.stats import rv_continuous
from scipy.stats import lognorm,norm

class custom_lgamma(rv_continuous):
    """ 
    pdf defined on page 227 in the book https://www.amazon.com/Loss-distributions-Wiley-Probability-Statistics/dp/0471879290
    The parameters of this distribution are a and lambdax
    """
    
    dist_name = "Custom_Log_Gamma"
        
    def _pdf(self,x,a,lambdax):
        """ pdf of the log gamma function """
        return (lambdax**(a)*(np.log(x))**(a-1))/(x**(lambdax+1)*gamma_func(a))

    def _cdf(self,lambdax):
        """ cdf of the log gamma function """
        u = lambdax*np.log(x)
        return gamma.cdf(u,a=a)
    
    def _sf(self,v):
        """ survivial fuction of the log gamma function. This is 1 - CDF. """
        u = lambdax*np.log(x)
        return 1 - gamma.cdf(u,a=a)
    
    def _ppf(self,lambdax):
        """ inverse cdf of the log gamma function. This is required to conduct efficient random variable simulation. """
        u = gamma.ppf(x,a=a)
        return np.exp(u/lambdax)
    
    def _argcheck(self,lambdax):
        """ check that the fitted parameters fall within the required bounds """
        param1_test = a > 0
        param2_test = lambdax > 0
        return param1_test and param2_test

test_data2 = custom_lgamma().rvs(a=5,lambdax=3,size=1000)

lg = custom_lgamma()
lg.fit(test_data2,floc=0,fscale=1)

custom_lgamma().fit(test_data2,fscale=1)

这两种实现都有效,但是,我希望能够使用自定义分发而无需初始化它,类似于使用预定义分发的方式:

norm.fit(test_data2)

预定义的分发不需要初始化或可调用。如果我尝试以这种方式使用自定义分发,我会得到结果:

custom_lgamma.fit(test_data2,fscale=1)

>>>
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-47-9b87a6428141> in <module>
----> 1 custom_lgamma.fit(test_data2,fscale=1)

TypeError: fit() missing 1 required positional argument: 'data'

有没有办法定义自定义的 scipy 分布,使其不需要初始化或可调用?我的 scipy 是 1.5.2。谢谢!

解决方法

您没有初始化您的发行版;这就是 SciPy 的分发基础设施的构建方式。您对 rv_continuous 类的实例和 rv_frozen 类的实例感到困惑。

当您调用您的分发类(在您的情况下为 custom_lgamma)时,SciPy 为用户界面生成文档和代码,用于创建我们从 scipy.stats 看到和使用的分发(例如 norm,gamma) (这是执行 custom_lgamma() 时发生的情况)。此实例包含pdfcdf 等方法,这些方法使用形状参数(就像其他scipy.stats 分布一样)。

再次调用此实例(例如 norm())将创建一个 冻结 分布(rv_frozen 类的一个实例),其形状参数无法更改(这将是如果您再次调用您的 custom_lgamma 实例或执行 custom_lgamma()() 会发生这种情况)。此实例具有仅接受分位数参数的 pdf 方法。

这是 SciPy 使用的约定:

class custom_lgamma_gen(rv_continuous):
    # implement your distribution methods here.
    ....

# this is the instance containing user interface of the distribution.
custom_lgamma = custom_lgamma_gen(name="custom_lgamma")


# now,you can call the fit method just like you would
# do with other scipy.stats distributions.
custom_lgamma.fit(test_data2,floc=0,fscale=1)


# to create a frozen distribution,do:
custom_lgamma_frozen = custom_lgamma()


# now you can call the methods without shape parameters
custom_lgamma_frozen.pdf(0.5)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。