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

[Frontmatter] (пропустите это, если вы просто хотите вопрос):

В настоящее время я рассматриваю использование взаимной информации Шеннона-Уивера и нормализованной избыточности для измерения степени маскировки информации между пакетами дискретных и непрерывных значений признаков, упорядоченных по функциям. Используя этот метод, моей целью является создание алгоритма, который выглядит очень похоже на 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. Я пытался использовать dblquad SciPy для выполнения интеграции, но в последнем случае я получаю поразительное изложение следующих сообщений.

Когда я установил 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)

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

1 ответ

Решение

Прежде чем пытаться найти более радикальные решения, такие как переосмысление проблемы или использование различных инструментов интеграции, посмотрите, поможет ли это замещать INF=float('INF') с INF=1E12 или другое большое число - которое может исключить результаты NaN, созданные простыми арифметическими операциями с входными переменными.

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

Другие вопросы по тегам