使用二维核密度估计器估计正弦时间序列的互信息

计算科学 matlab 信息论
2021-12-25 00:52:19

这是重现Moon等人的尝试1995年,作者的副本可以通过这里获得。

作为基准,我们估计一个简单正弦信号的时滞互信息sin(0.02πt)使用高斯核:

K(y)=exp((yyi)TS1(yyi)2h2)(2π)d/2hddet(S)1/2,
其中选择为 其中是多元核的维数,是数据点的数量。h
h={4(d+2)}1/d+4n1/(d+4),
dn

我写了一个 Matlab 函数(代码在文末)。

假设是原始时间序列有 400 个数据点,并且作者将估计的互信息 tau的函数xtsin(0.02πt)t=1,2,,400xtτsin[0.02π(tτ)]Ixt,xtττ

在此处输入图像描述

但是,我从我的代码中得到的是

在此处输入图像描述

虽然定性特征(如滞后 0、50 和 100 处的发散互信息),但量级相差甚远,整体形状不正确。

我的第一个怀疑是我对联合 pdf 和边际 pdf 使用了不同的窗口宽度,它们可能不一致。所以我的问题是:如何在互信息估计的背景下一致地构建联合和边际 pdf 估计?

第二个问题是:除了可能不一致的 pdf KDE 之外,代码中还有什么问题吗?

编辑1:

我之所以选择 KDE 而不是其他方法,是因为我认为 KDE 在概念上简单直观,并且可能在实现上也很简单。除了 MI,我还想估计传输熵和可能的其他信息论度量。我觉得估计联合概率足以适用于各种信息论测量。如果您对我上面的论点有意见,请告诉我。

我没有使用任何只能在 Matlab 中找到的东西。欢迎使用 R、Python 等编写代码。

编辑 2:Matlab 代码

Matlab代码:

function [MI] = get_MI(xt, xt_lag)
% xt is original time series, xt_lag is the lagged one, both are column
% vectors
x_pair = [xt' xt_lag']; n=length(xt);

d=1; h_d1=(4/(d+2))^(1/(d+4)) * n^(-1/(d+4));

d=2; h_d2=(4/(d+2))^(1/(d+4)) * n^(-1/(d+4));

MI = 0.;

Sxy_pair = cov(x_pair); invS_pair = Sxy_pair\eye(2); detS_pair = det(Sxy_pair);

Sxy_xt = cov(xt'); invS_xt = Sxy_xt\eye(1); detS_xt = det(Sxy_xt);

Sxy_lag = cov(xt_lag'); invS_lag = Sxy_lag\eye(1); detS_lag = det(Sxy_lag);

for ix=1:n
    Psq = p_mkde(x_pair(ix,:)', x_pair', h_d2, invS_pair, detS_pair);
    Ps = p_mkde(x_pair(ix,1), xt, h_d1, invS_xt, detS_xt);
    Pq = p_mkde(x_pair(ix,2), xt_lag, h_d1, invS_lag, detS_lag);

    MI = MI + (log2(Psq) - log2(Ps) - log2(Pq));
end

MI = MI/n;

end

function [pxy]=p_mkde(x,X,h,invS,detS)

s1=size(X);
d=s1(1);
N=s1(2);

pxy_sum=0;
for ix=1:N
    p2=(x-X(:,ix))'*invS*(x-X(:,ix));
    pxy_sum=pxy_sum+1/sqrt((2*pi)^d*detS)*exp(-p2/(2*h^2));
end
pxy=1/(N*h^d)*pxy_sum;
end
1个回答

让我首先重申这是一个糟糕的 MI 估计程序。请不要在任何严肃的业务中使用它,除非您绝对确定自己知道自己在做什么。

您在代码中犯了两个严重错误

  1. 您的比例不匹配,因为您没有正确进行集成。互信息在论文中被定义为概率而不是概率密度但是您的内核密度估计器会为您提供集成为 1 的概率密度,但不会在网格上的点上总和为 1。如果要使用论文中的求和公式,则需要将密度转换回概率。

  2. 您仅在数据所在的点添加概率,并在这些区域上多次计数。您应该集成整个发行版的支持!一个简单的方法是制作一个统一的网格来集成。我认为您应该仔细审查互信息的定义。(您需要添加概率,而不是对数据的逐点 MI 估计。)

这不是一个代码审查网站,而是代码中的一些小东西。

  • 永远不要使用保留的 matlab 函数名称作为变量:sum是其中之一
  • 你不需要inv,所以不要使用它。使用\and/代替
  • 尽量不要i用作循环变量。i是 MATLAB 中的虚数(也是j
  • 提示:MATLAB 有一个用于 1D 的 KDE,您可以根据以下内容验证您的代码:ksdensity

编辑:我误解了代码。我错了。OP正在用样本总和代替期望,因此使用密度和网格都没有问题。