Непрерывная взаимная информация в Python

[Frontmatter] (пропустите это, если вам просто нужен вопрос) :

Я сейчас ищу Shannon-Weaver Mutual Information и нормализованная избыточность для измерения степени маскирования информации между пакетами дискретных и непрерывных значений признаков, организованных по признакам. Используя этот метод, моя цель - построить алгоритм, который очень похож на ID3 , но вместо использования энтропии Шеннона алгоритм будет искать (как ограничение цикла), чтобы максимизировать или минимизировать общую информацию между отдельным элементом и набором функций на основе полного входного пространства функций, добавляя новые функции к последней коллекции, если (и только если) они увеличивают или уменьшают взаимную информацию, соответственно. Это, по сути, перемещает алгоритм принятия решения ID3 в парное пространство, объединяя к нему ансамблевой подход со всеми ожидаемыми временными и пространственными сложностями обоих методов.

[/ Frontmatter]


Переходя к вопросу: я пытаюсь получить непрерывный интегратор , работающий на Python, используя SciPy .Поскольку я работаю со сравнениями дискретных и непрерывных переменных, моя текущая стратегия для каждого сравнения пар функция-свойство следующая:

  • Дискретная функция по сравнению с дискретной функцией: использовать дискретную форму взаимной информации. Это приводит к двойному суммированию вероятностей, с которым мой код справляется без проблем.

  • Во всех остальных случаях (дискретное или непрерывное, обратное и непрерывное против непрерывного): используйте непрерывную форму, используя гауссову оценку , чтобы сгладить функции плотности вероятности .

Я могу выполнить некоторую дискретизацию для последних случаев, но поскольку мои наборы входных данных не являются по своей природе линейными, это потенциально излишне сложно.


Вот характерный код:

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)

Однако остается вопрос об исправлении округления, как и запрос на более надежную реализацию. Любая помощь в любой области будет принята с благодарностью.

18
задан MrGomez 2 December 2011 в 22:55
поделиться