Python 连续分布的scipy.stats属性“熵”不';我不能手动工作

Python 连续分布的scipy.stats属性“熵”不';我不能手动工作,python,entropy,information-theory,probability-distribution,scipy.stats,Python,Entropy,Information Theory,Probability Distribution,Scipy.stats,scipy.stats中的每个连续分布都带有一个计算其微分熵的属性:.entropy。与正态分布(norm)和其他具有熵闭合形式解的分布不同,其他分布必须依赖于数值积分 试图找出.entropy属性在这些情况下调用的是哪个函数,我在scipy.stats.\u distn\u infrastructure.py中找到了一个名为\u entropy的函数,它使用integrate.quad(pdf)(数值积分)进行调用 但是,当我尝试比较这两种方法时(属性.entropy与函数\u entropy

scipy.stats
中的每个连续分布都带有一个计算其微分熵的属性:
.entropy
。与正态分布(
norm
)和其他具有熵闭合形式解的分布不同,其他分布必须依赖于数值积分

试图找出
.entropy
属性在这些情况下调用的是哪个函数,我在
scipy.stats.\u distn\u infrastructure.py
中找到了一个名为
\u entropy
的函数,它使用
integrate.quad(pdf)
(数值积分)进行调用

但是,当我尝试比较这两种方法时(属性
.entropy
与函数
\u entropy
的数值积分),函数给出了一个错误:

AttributeError:'rv\u freezed'对象没有属性'\u pdf'

为什么分布的属性
.entropy
计算得很好,但函数
\u entropy
给出了一个错误

import numpy as np
from scipy import integrate 
from scipy.stats import norm, johnsonsu
from scipy.special import entr

def _entropy(self, *args): #from _distn_infrastructure.py
    def integ(x):
        val = self._pdf(x, *args)
        return entr(val)

    # upper limit is often inf, so suppress warnings when integrating
    # _a, _b = self._get_support(*args)
    _a, _b = -np.inf, np.inf   
    with np.errstate(over='ignore'):
        h = integrate.quad(integ, _a, _b)[0]

    if not np.isnan(h):
        return h
    else:
        # try with different limits if integration problems
        low, upp = self.ppf([1e-10, 1. - 1e-10], *args)
        if np.isinf(_b):
            upper = upp
        else:
            upper = _b
        if np.isinf(_a):
            lower = low
        else:
            lower = _a
    return integrate.quad(integ, lower, upper)[0]
使用属性可以很好地工作:

print(johnsonsu(a=2.55,b=2.55).entropy())
返回
0.950370309122894

但该功能不:

print(_entropy(johnsonsu(a=2.55,b=2.55)))
返回错误
AttributeError:“rv\u freezed”对象没有属性“\u pdf”
,即使
johnsonsu


属性
.entropy
调用哪个函数,然后在
johnsonsu
的情况下?

如果使用的是冻结分布,则需要
johnsonsu(a=2.55,b=2.55)。entropy()
,否则需要
johnsonsu.entropy(a=2.55,b=2.55)

您的问题的原因部分基本上是在_entropy中引入下划线意味着“实现细节,不要直接调用”。一个较长的答案是,冻结的分发包封装了一个分发实例(self.dist),并将对_pdf、_pmf等的调用委托给它


编辑:执行johnsonsu(a=2.55,b=2.55)创建一个冻结的分发,rv\u冻结。除非您想多次重用该实例,否则不要这样做:只需将a、b形状参数作为熵函数的参数。

那么我如何才能让手动
\u熵
函数工作呢?这真的是属性
.entropy
所调用的吗?我不知道我是否在使用冻结分发,因为我不知道这些是什么。我想我所做的只是估计Johnson Su。您编写的两个代码示例对冻结和非冻结之间的区别没有帮助,因为它们都工作得很好
def _pdf(self, x, a, b):
    # johnsonsu.pdf(x, a, b) = b / sqrt(x**2 + 1) *
    #                          phi(a + b * log(x + sqrt(x**2 + 1)))
    x2 = x*x
    trm = _norm_pdf(a + b * np.log(x + np.sqrt(x2+1)))
    return b*1.0/np.sqrt(x2+1.0)*trm