计算一组点的熵
Compute entropy of a set of points
我有一组位于 n 维球体上的点(因此,它们的范数为 1)。我需要计算这个集合的熵。
有没有一种工具可以让我做这样的事情?不然怎么办?
我的猜测是,由于必须根据概率分布计算熵,所以我需要将这个问题分成 2 个部分:
1) 一些函数采用点集并输出近似于该集的概率分布。
2) 一个接受概率分布(或其密度)并给出其熵的函数。
所有这些都是在知道点位于 n 球面上的情况下完成的。谢谢!
我不确定你到底有多少数据。但是根据您的解释,我有以下答案。我会建议使用 Kernel Density Estimation to estimate the pdf. This module is available in scipy and scikit-learn.
在 scikit-learn 中,您有更多选项可以选择要在 KDE 中使用的内核。
import numpy as np
from sklearn.neighbors.kde import KernelDensity
### create data ###
sample_count = 1000
n = 6
data = np.random.randn(sample_count, n)
data_norm = np.sqrt(np.sum(data*data, axis=1))
data = data/data_norm[:, None] # Normalized data to be on unit sphere
## estimate pdf using KDE with gaussian kernel
kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(data)
log_p = kde.score_samples(data) # returns log(p) of data sample
p = np.exp(lop_p) # estimate p of data sample
entropy = -np.sum(p*lop_p) # evaluate entropy
我不确定,但我想更有效的方法是用 -np.mean(log(p))
替换 np.sum(p*np.log(p))
。您应该利用您的数据并执行 monte carlo 集成,我的实现是:
def get_entropy(X):
if len(X.shape)==1:
X=X.reshape(-1,1)
params = {'bandwidth': np.logspace(-10, 10, 20)}
gs = GridSearchCV(KernelDensity(), params)
gs.fit(X)
kde=gs.best_estimator_
log_probs=kde.score_samples(X)
return -np.mean(log_probs)
我在几种常见的分布上对其进行了测试,如果提供了足够的样本,我总是非常接近熵的分析推导。
我会说之前的答案是错误的,假设我们认为我们的数据集乘以 2(每个样本出现两次)。那么估计的熵应该不会移动但是前面的公式会说熵已经加倍了。
对数据集求平均 log(p) 是蒙特卡洛积分方法,对数据集求和 p*log(p) 不是。如果我错了,请纠正我。
我有一组位于 n 维球体上的点(因此,它们的范数为 1)。我需要计算这个集合的熵。 有没有一种工具可以让我做这样的事情?不然怎么办?
我的猜测是,由于必须根据概率分布计算熵,所以我需要将这个问题分成 2 个部分:
1) 一些函数采用点集并输出近似于该集的概率分布。
2) 一个接受概率分布(或其密度)并给出其熵的函数。
所有这些都是在知道点位于 n 球面上的情况下完成的。谢谢!
我不确定你到底有多少数据。但是根据您的解释,我有以下答案。我会建议使用 Kernel Density Estimation to estimate the pdf. This module is available in scipy and scikit-learn.
在 scikit-learn 中,您有更多选项可以选择要在 KDE 中使用的内核。
import numpy as np
from sklearn.neighbors.kde import KernelDensity
### create data ###
sample_count = 1000
n = 6
data = np.random.randn(sample_count, n)
data_norm = np.sqrt(np.sum(data*data, axis=1))
data = data/data_norm[:, None] # Normalized data to be on unit sphere
## estimate pdf using KDE with gaussian kernel
kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(data)
log_p = kde.score_samples(data) # returns log(p) of data sample
p = np.exp(lop_p) # estimate p of data sample
entropy = -np.sum(p*lop_p) # evaluate entropy
我不确定,但我想更有效的方法是用 -np.mean(log(p))
替换 np.sum(p*np.log(p))
。您应该利用您的数据并执行 monte carlo 集成,我的实现是:
def get_entropy(X):
if len(X.shape)==1:
X=X.reshape(-1,1)
params = {'bandwidth': np.logspace(-10, 10, 20)}
gs = GridSearchCV(KernelDensity(), params)
gs.fit(X)
kde=gs.best_estimator_
log_probs=kde.score_samples(X)
return -np.mean(log_probs)
我在几种常见的分布上对其进行了测试,如果提供了足够的样本,我总是非常接近熵的分析推导。
我会说之前的答案是错误的,假设我们认为我们的数据集乘以 2(每个样本出现两次)。那么估计的熵应该不会移动但是前面的公式会说熵已经加倍了。
对数据集求平均 log(p) 是蒙特卡洛积分方法,对数据集求和 p*log(p) 不是。如果我错了,请纠正我。