【问题标题】:What is the derivative of Shannon's Entropy?香农熵的导数是什么?
【发布时间】:2019-10-15 22:24:25
【问题描述】:

我有以下简单的 python 函数,它根据香农的信息理论计算单个输入 X 的熵:

import numpy as np

def entropy(X:'numpy array'):
  _, frequencies = np.unique(X, return_counts=True)
  probabilities  = frequencies/X.shape[0]
  return -np.sum(probabilities*np.log2(probabilities))

a = np.array([1., 1., 1., 3., 3., 2.])
b = np.array([1., 1., 1., 3., 3., 3.])
c = np.array([1., 1., 1., 1., 1., 1.])

print(f"entropy(a): {entropy(a)}")
print(f"entropy(b): {entropy(b)}")
print(f"entropy(c): {entropy(c)}")

输出如下:

entropy(a): 1.4591479170272446
entropy(b): 1.0
entropy(c): -0.0

但是,我还需要计算对dx 的导数:

d熵/dx

这不是一件容易的事,因为主要公式

-np.sum(概率*np.log2(概率))

接受probabilities,而不是x 值,因此不清楚如何区分dx

有人知道怎么做吗?

【问题讨论】:

  • 您可能会在herehere 找到您的答案(这是互联网搜索的结果;我不是该领域的专家)。
  • @anatolyg 谢谢你的回复,遗憾的是没有一个链接提供答案,第一个讨论如何找到最大熵,第二个是相对于p(超过d probability)。

标签: python numpy data-science derivative entropy


【解决方案1】:

解决此问题的一种方法是使用finite differences 以数值方式计算导数。

在这种情况下,我们可以定义一个小常数来帮助我们计算数值导数。此函数采用单参数函数并计算其对输入 x 的导数:

ε = 1e-12
def derivative(f, x):
    return (f(x + ε) - f(x)) / ε

为了使我们的工作更容易,让我们定义一个计算熵的最内层运算的函数:

def inner(x):
    return x * np.log2(x)

回想一下,和的导数是导数的和。因此,真正的导数计算发生在我们刚刚定义的inner函数中。

所以,熵的数值导数是:

def numerical_dentropy(X):
    _, frequencies = np.unique(X, return_counts=True)
    probabilities = frequencies / X.shape[0]
    return -np.sum([derivative(inner, p) for p in probabilities])

我们可以做得更好吗?当然,我们可以!这里的关键见解是产品规则:(f g)' = fg' + gf',其中f=xg=np.log2(x)。 (另请注意d[log_a(x)]/dx = 1/(x ln(a))。)

因此,分析熵可以计算为:

import math
def dentropy(X):
    _, frequencies = np.unique(X, return_counts=True)
    probabilities = frequencies / X.shape[0]
    return -np.sum([(1/math.log(2, math.e) + np.log2(p)) for p in probabilities])

使用样本向量进行测试,我们有:

a = np.array([1., 1., 1., 3., 3., 2.])
b = np.array([1., 1., 1., 3., 3., 3.])
c = np.array([1., 1., 1., 1., 1., 1.])

print(f"numerical d[entropy(a)]: {numerical_dentropy(a)}")
print(f"numerical d[entropy(b)]: {numerical_dentropy(b)}")
print(f"numerical d[entropy(c)]: {numerical_dentropy(c)}")

print(f"analytical d[entropy(a)]: {dentropy(a)}")
print(f"analytical d[entropy(b)]: {dentropy(b)}")
print(f"analytical d[entropy(c)]: {dentropy(c)}")

当执行时,给我们:

numerical d[entropy(a)]: 0.8417710972707937
numerical d[entropy(b)]: -0.8854028621385623
numerical d[entropy(c)]: -1.4428232973189605
analytical d[entropy(a)]: 0.8418398787754222
analytical d[entropy(b)]: -0.8853900817779268
analytical d[entropy(c)]: -1.4426950408889634

作为奖励,我们可以使用 automatic differentiation 库测试这是否正确:

import torch

a, b, c = torch.from_numpy(a), torch.from_numpy(b), torch.from_numpy(c)

def torch_entropy(X):
    _, frequencies = torch.unique(X, return_counts=True)
    frequencies = frequencies.type(torch.float32)
    probabilities = frequencies / X.shape[0]
    probabilities.requires_grad_(True)
    return -(probabilities * torch.log2(probabilities)).sum(), probabilities

for v in a, b, c:
    h, p = torch_entropy(v)
    print(f'torch entropy: {h}')
    h.backward()
    print(f'torch derivative: {p.grad.sum()}')

这给了我们:

torch entropy: 1.4591479301452637
torch derivative: 0.8418397903442383
torch entropy: 1.0
torch derivative: -0.885390043258667
torch entropy: -0.0
torch derivative: -1.4426950216293335

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 2014-03-31
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    相关资源
    最近更新 更多