18

[Frontmatter] (如果你只是想问这个问题,请跳过这个)

我目前正在研究使用Shannon-Weaver 互信息标准化冗余来测量按特征组织的离散和连续特征值袋之间的信息屏蔽程度。使用这种方法,我的目标是构建一个看起来与ID3非常相似的算法,但不是使用香农熵,该算法将寻求(作为循环约束)最大化或最小化单个特征和基于完整输入特征空间的特征集合之间的共享信息,当(且仅当)新特征增加或分别减少互信息。实际上,这将 ID3 的决策算法移动到对空间中,将集成方法与这两种方法的所有预期时间和空间复杂性结合在一起。

[/前线]


关于这个问题:我正在尝试让一个使用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

请注意,为了防止 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)

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

4

1 回答 1

4

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

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

于 2011-12-02T22:00:10.603 回答