Python 如何计算N个变量的shannon熵和互信息

Python 如何计算N个变量的shannon熵和互信息,python,statistics,information-theory,Python,Statistics,Information Theory,我需要计算互信息,以及N个变量的香农熵 我写了一个计算特定分布的香农熵的代码。 假设我有一个变量x,数字数组。 接下来,我需要计算归一化的概率密度函数,所以使用numpy.histogram很容易得到它 import scipy.integrate as scint from numpy import* from scipy import* def shannon_entropy(a, bins): p,binedg= histogram(a,bins,normed=True) p=p/le

我需要计算互信息,以及N个变量的香农熵

我写了一个计算特定分布的香农熵的代码。 假设我有一个变量x,数字数组。 接下来,我需要计算归一化的概率密度函数,所以使用numpy.histogram很容易得到它

import scipy.integrate as scint
from numpy import*
from scipy import*

def shannon_entropy(a, bins):

p,binedg= histogram(a,bins,normed=True)
p=p/len(p)

x=binedg[:-1]
g=-p*log2(p)
g[isnan(g)]=0.

return scint.simps(g,x=x)
选择inserting x,并仔细选择此功能工作的箱子编号

但是这个函数非常依赖于箱子的数量:选择这个参数的不同值,我得到了不同的值

特别是如果我的输入是一个常量值数组:

x=[0,0,0,....,0,0,0]
这个变量的熵显然必须是0,但是如果我选择的bin数等于1,我得到了正确的答案,如果我选择不同的值,我得到了奇怪的无意义(负)答案。。我的感觉是numpy.histogram的参数normaled=True或density=True(如中所述),它们应该返回规范化的直方图,可能在我从概率密度函数(numpy.histogram的输出)切换到概率质量函数(香农熵的输入)的那一刻,我犯了一些错误,我有:

我想找到一种解决这些问题的方法,我想有一种有效的方法来计算香农熵,它与bin数无关

我写了一个函数来计算更多变量分布的香农熵,但是我得到了同样的错误。 代码是这样的,其中函数shannon_entropydd的输入是数组,其中每个位置都有统计计算中必须涉及的每个变量

def intNd(c,axes):

assert len(c.shape) == len(axes)
assert all([c.shape[i] == axes[i].shape[0] for i in range(len(axes))])
if len(axes) == 1:
    return scint.simps(c,axes[0])
else:
    return intNd(scint.simps(c,axes[-1]),axes[:-1])



def shannon_entropydd(c,bins=30):



hist,ax=histogramdd(c,bins,normed=True)

for i in range(len(ax)):
    ax[i]=ax[i][:-1]

p=-hist*log2(hist)

p[isnan(p)]=0

return intNd(p,ax)
我需要这些量,以便能够计算特定变量集之间的值:

M_info(x,y,z)=H(x)+H(z)+H(y)-H(x,y,z)

其中H(x)是变量x的香农熵


我必须找到一种方法来计算这些量,所以如果有人有一种完全不同的代码,我可以打开它,我不需要修复这个代码,但要找到一种正确的方法来计算这个统计函数

结果很大程度上取决于估计的密度。你能假设密度的具体形式吗?如果避免直方图或其他通用估计(如核密度估计),则可以减少结果对估计的依赖性。如果你能提供更多有关变量的细节,我可以做更具体的评论

作为我论文工作的一部分,我研究了互信息的估计[1]。第8.1节和附录F中有一些关于MI的内容


[1]

我认为,如果选择
bins=1
,你会发现熵总是
0
,因为值所在的可能bin没有“不确定性”(“不确定性”是熵的度量)。您应该选择一些“足够大”的容器,以考虑变量可以采用的值的多样性。如果您有离散值:对于二进制值,您应该取
bins>=2
。如果可以接受变量的值位于
{0,1,2}
中,则应该具有
bin>=3
,依此类推

我必须说我没有读过你的代码,但这对我来说很有用:

import numpy as np

x = [0,1,1,1,0,0,0,1,1,0,1,1]
bins = 10
cx = np.histogram(x, bins)[0]

def entropy(c):
    c_normalized = c/float(np.sum(c))
    c_normalized = c_normalized[np.nonzero(c_normalized)]
    h = -sum(c_normalized * np.log(c_normalized))  
    return h

hx = entropy(cx)

关键是:我不想先验地知道我所期望的是哪种分布,我想有一个通用的代码来计算变量之间的交互信息。理论上,我可以有一组数据,然后做一个柱状图,从中我需要推断出概率质量函数,并从中计算出这个数据集与另一个数据集之间的互信息。@user3585292好的,很公平。但是,计算具有未知相关性的任意变量的MI的问题需要构造它们的联合分布。。。在一定程度上,你可以做到这一点,你有一个通用的通用预测算法。我不是想让你气馁,只是想说你能得到的东西是有限的。这就是说,如果您使用2个或(可能)3个变量,您可能会通过直方图或其他密度估计(如核密度)得到可行的结果。
import numpy as np

x = [0,1,1,1,0,0,0,1,1,0,1,1]
bins = 10
cx = np.histogram(x, bins)[0]

def entropy(c):
    c_normalized = c/float(np.sum(c))
    c_normalized = c_normalized[np.nonzero(c_normalized)]
    h = -sum(c_normalized * np.log(c_normalized))  
    return h

hx = entropy(cx)