Python中的连续互信息

MrG*_*mez 18 python math floating-point scipy information-theory

[Frontmatter] (如果您只是想要问题,请跳过此处):

我目前正在考虑使用Shannon-Weaver互信息规范化冗余来测量按特征组织的离散和连续特征值之间的信息屏蔽程度.使用这种方法,我的目标是构建一个看起来非常类似于ID3的算法,但是算法将寻找(作为循环约束)以最大化或最小化单个特征和集合之间的共享信息,而不是使用香农熵.基于完整输入要素空间的要素,如果(并且仅当)它们分别增加或减少相互信息,则向后一个集合添加新要素.实际上,这将ID3的决策算法移动到成对空间中,使用两种方法的所有预期时间和空间复杂性来装订集合方法.

[/ Frontmatter]


关于这个问题:我正在尝试使用SciPy让一个连续的集成商在Python中工作.因为我正在使用离散变量和连续变量的比较,我对特征 - 特征对的每个比较的当前策略如下:

  • 离散特征与离散特征:使用离散形式的互信息.这导致概率的双重求和,我的代码处理没有问题.

  • 所有其他情况(离散与连续,反向,连续与连续):使用连续形式,使用高斯估计来平滑概率密度函数.

对于后一种情况,我可能会执行某种离散化,但由于我的输入数据集本身并不是线性的,因此这可能是不必要的复杂.


这是突出的代码:

import math
import numpy
import scipy
from scipy.stats import gaussian_kde
from scipy.integrate import dblquad

# Constants
MIN_DOUBLE = 4.9406564584124654e-324 
                    # The minimum size of a Float64; used here to prevent the
                    #  logarithmic function from hitting its undefined region
                    #  at its asymptote of 0.
INF = float('inf')  # The floating-point representation for "infinity"

# x and y are previously defined as collections of 
# floating point values with the same length

# Kernel estimation
gkde_x = gaussian_kde(x)
gkde_y = gaussian_kde(y)

if len(binned_x) != len(binned_y) and len(binned_x) != len(x):
    x.append(x[0])
    y.append(y[0])

gkde_xy = gaussian_kde([x,y])
mutual_info = lambda a,b: gkde_xy([a,b]) * \
           math.log((gkde_xy([a,b]) / (gkde_x(a) * gkde_y(b))) + MIN_DOUBLE)

# Compute MI(X,Y)
(minfo_xy, err_xy) = \
    dblquad(mutual_info, -INF, INF, lambda a: 0, lambda a: INF)

print 'minfo_xy = ', minfo_xy
Run Code Online (Sandbox Code Playgroud)

请注意,为了防止SciPy的gaussian_kde类中出现奇点,故意过度计算一个点.随着x和y的大小相互接近无穷大,这种影响变得可以忽略不计.


我目前的障碍是试图在SciPy中针对高斯核密度估计进行多次积分.我一直在尝试使用SciPy的dblquad来执行集成,但在后一种情况下,我收到了令人震惊的以下消息.

当我设置numpy.seterr ( all='ignore' ):

警告:检测到舍入错误的发生,这会阻止实现所请求的容差.错误可能被低估了.

当我将其设置为'call'使用错误处理程序时:

浮点错误(下溢),标志4

浮点错误(无效值),标志为8

很容易弄清楚发生了什么,对吗?嗯,几乎:IEEE 754-2008和SciPy只告诉我这里发生了什么,而不是为什么如何解决它.


结果:minfo_xy通常会解决nan; 它的采样不足以防止信息在执行Float64数学时丢失或无效.

使用SciPy时是否存在此问题的一般解决方法?

更好的是:如果Python的连续互信息的强大,固定实现具有两个浮点值集合或合并的对集合的接口,它将解决这个完整的问题.如果您知道存在的,请链接它.

先感谢您.


编辑:这解决了nan上面示例中的传播问题:

mutual_info = lambda a,b: gkde_xy([a,b]) * \
    math.log((gkde_xy([a,b]) / ((gkde_x(a) * gkde_y(b)) + MIN_DOUBLE)) \
        + MIN_DOUBLE)
Run Code Online (Sandbox Code Playgroud)

然而,舍入校正的问题仍然存在,对更强大的实现的要求也是如此.任何领域的任何帮助将不胜感激.

Ray*_*ger 4

在尝试更激进的解决方案(例如重新构建问题或使用不同的集成工具)之前,看看这是否有帮助。替换INF=float('INF')INF=1E12或其他一些大数字——这可能会消除通过对输入变量进行简单算术运算而创建的NaN结果。

对此没有任何承诺,但有时在进行重大算法重写或替换替代工具之前尝试快速修复会有所帮助。

  • 不接受它是故意的,因为它回答了一个警告,但不是整个问题(我希望得到更多答案)。因此,我将尽力填补缺失的细节。-- 解决方法确实是使用更正确的积分器。如果这些不可用,大部分问题可以通过使用绝对和相对 epsilon 值来解决。问题是:SciPy 的“dblquad”有一个错误,这些值被丢弃到地板上进行内部集成。因此,他们的团队已收到补丁通知。-- 现在将其标记为已接受。 (2认同)