Подтвердить что ты не робот

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

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

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


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

Когда я устанавливаю numpy.seterr ( all='ignore' ):

Предупреждение: обнаружена ошибка округления, которая предотвращает      требуемый допуск от достижения. Ошибка может быть      занижены.

И когда я устанавливаю его на 'call' с помощью обработчика ошибок:

Ошибка с плавающей запятой (underflow), с флагом 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)

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

4b9b3361

Ответ 1

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

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