中的每个连续分布scipy.stats
都带有一个计算其微分熵的属性:.entropy
。与正态分布 ( norm
) 和其他具有熵的封闭解的其他分布不同,其他分布必须依赖于数值积分。
试图找出.entropy
在这些情况下属性调用的函数,我发现了一个调用的函数_entropy
(scipy.stats._distn_infrastructure.py
数值integrate.quad(pdf)
积分)。
但是当我尝试比较这两种方法(属性.entropy
与数值积分与函数_entropy
)时,函数给出了一个错误:
AttributeError: 'rv_frozen' object has no attribute '_pdf'
为什么分布的属性.entropy
计算得很好,但是函数却_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.9503703091220894
但该功能不会:
print(_entropy(johnsonsu(a=2.55,b=2.55)))
返回错误 AttributeError: 'rv_frozen' object has no attribute '_pdf'
,即使johnsonsu
确实具有此属性:
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
.entropy
在 的情况下,属性调用的是哪个函数johnsonsu
?