我需要计算一种称为互信息的度量。首先,我需要计算另一个称为熵的度量,例如x和y的联合熵:
-∬p(x,y)·log p(x,y)dxdy
因此,为了计算p(x,y)
,我使用了内核密度估算器(以这种方式,函数kde2d
,它返回了Z
值(x和y的概率)窗口)。
同样,到目前为止,我有一个Z
值[1x100] x [1x100]
的矩阵,它等于我的p(x,y)
。但我必须通过发现表面下的体积(doble积分)来整合它。但我没有找到办法做到这一点。用于计算双正交的函数quad2d
没有用,因为我只集成了一个数值矩阵p(x,y)
,它给了我一个常数....
任何人都知道找到音量/计算双积分的东西吗?
persp3d
:
谢谢大家!!!!
答案 0 :(得分:4)
获得kde2d
的结果后,非常直接来计算数值积分。下面的示例会话概述了如何执行此操作。
如您所知,数字双积分只是一个二维求和。默认情况下,kde2d
会将range(x)
和range(y)
作为2D域。我看到你有100 * 100矩阵,所以我认为你已经使用n = 100
设置了kde2d
。现在,kde$x
,kde$y
定义了一个100 * 100网格,den$z
为每个网格单元格提供了密度。很容易计算每个网格单元的大小(它们都相等),然后我们做三个步骤:
z * log(z)
;由于z
是100 * 100矩阵,因此这也是一个矩阵。你只需将它们相加,然后乘以单元格大小cell_size
,就可得到非标准化的熵; ## sample data: bivariate normal, with covariance/correlation 0
set.seed(123); x <- rnorm(1000, 0, 2) ## marginal variance: 4
set.seed(456); y <- rnorm(1000, 0, 2) ## marginal variance: 4
## load MASS
library(MASS)
## domain:
xlim <- range(x)
ylim <- range(y)
## 2D Kernel Density Estimation
den <- kde2d(x, y, n = 100, lims = c(xlim, ylim))
##persp(den$x,den$y,den$z)
z <- den$z ## extract density
## den$x, den$y expands a 2D grid, with den$z being density on each grid cell
## numerical integration is straighforward, by aggregation over all cells
## the size of each grid cell (a rectangular cell) is:
cell_size <- (diff(xlim) / 100) * (diff(ylim) / 100)
## normalizing constant; ideally should be 1, but actually only close to 1 due to discretization
norm <- sum(z) * cell_size
## your integrand: z * log(z) * (-1):
integrand <- z * log(z) * (-1)
## get numerical integral by summation:
entropy <- sum(integrand) * cell_size
## self-normalization:
entropy <- entropy / norm
<强>验证强>
上面的代码给出了4.230938
的熵。现在,Wikipedia - Multivariate normal distribution给出了熵公式:
(k / 2) * (1 + log(2 * pi)) + (1 / 2) * log(det(Sigma))
对于上述双变量正态分布,我们有k = 2
。我们有Sigma
(协方差矩阵):
4 0
0 4
其行列式为16.因此,理论值为:
(1 + log(2 * pi)) + (1 / 2) * log(16) = 4.224171
很好的比赛!