7

我有一些关于某些属性的统计数据,例如:

1st iter : p1:10 p2:0 p3:12 p4:33 p5:0.17 p6:ok p8:133 p9:89
2nd iter : p1:43 p2:1 p6:ok p8:12 p9:33
3rd iter : p1:14 p2:0 p3:33 p5:0.13 p9:2
...

(p1 -> number of tries, p2 -> try done well, p3..pN -> properties of try).

我需要计算每个属性的信息量。经过一些量化程序(例如到 10 个级别)以使所有输入数字在同一级别上,输入文件开始如下所示:

p0: 4 3 2 4 5 5 6 7
p3: 4 5 3 3   
p4: 5 3 3 2 1 2 3 
...

哪里p(0) = funct(p1,p2)

并非每条输入线都能pK如此len(pk) <= len(p0)

现在我知道如何通过香农熵为每条线计算每个属性的熵。我需要从这里计算互信息。

I(p0,pK)由于长度不同,互信息的联合熵计算卡住了。

我正在计算这样一个元素的熵:

def entropy(x):
    probs = [np.mean(x == c) for c in set(x)]
    return np.sum(-p * np.log2(p) for p in probs)

那么,对于关节,我需要使用product来生成输入数组x并使用zip(p0,pk)而不是set(x)

4

2 回答 2

7

我假设您想随后计算, ,...p1中的每一个之间的互信息。p2p3

1)H(X)从 p1 计算熵:

等式 1

每个x都是来自 的后续元素p1

2)用相同的方程计算H(Y)pK,每个x都是来自的后续元素p1

p13) 从和创建一个新的对集合pK

pairs = zip(p1, pK)

请注意,如果数据列中的值具有不同的含义,那么您可能应该填充缺失的数据(例如使用0s 或前一次迭代中的值)。

4) 使用以下方法计算联合熵H(X,Y)

等式 2

请注意,您不能只使用第一个方程并将每一对视为单个元素 - 您必须遍历该方程之间p1和中的整个笛卡尔积,使用集合pK计算概率。pairs因此,为了迭代整个笛卡尔积,请使用for xy in itertools.product(p1, pK): ....

5)然后你可以有和之间的互信息p1pK

等式 3

使用 numpy 功能,您可以计算联合熵,如下所示

def entropy(X, Y):
    probs = []
    for c1 in set(X):
        for c2 in set(Y):
            probs.append(np.mean(np.logical_and(X == c1, Y == c2)))

    return np.sum(-p * np.log2(p) for p in probs if p > 0)

其中if p > 0熵的定义一致:

在 p(x i ) = 0 对某个 i 的情况下,对应的被加数 0 log b (0) 的值取为 0

如果您不想使用numpy,那么没有它的版本可能类似于:

def entropyPart(p):
    if not p:
        return 0

    return -p * math.log(p)

def entropy(X, Y):
    pairs = zip(X, Y)
    probs = []
    for pair in itertools.product(X,Y):
        probs.append(1.0 * sum([p == pair for p in pairs]) / len(pairs))

   return sum([entropyPart(p) for p in probs])
于 2013-09-16T10:10:51.770 回答
0

从这篇维基百科文章的正式定义部分获取公式。他们称之为信息增益,但它与互信息相同。为了计算包含在此公式中的样本的熵,请使用Wikipedia 文章的定义部分中的公式。

因此,您首先计算整个数据集的熵,并从中减去当您知道所讨论的属性值时剩下的熵。

多维直方图可以在 Python 中使用numpy.histogramdd().

于 2013-09-16T15:10:04.423 回答