Непрерывная взаимная информация в 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
обратите внимание, что передерживания ровно одно очко-это сделано специально, чтобы предотвратить сингулярность в составляющей это gaussian_kde класса. Так как величины X и y взаимно приближаются к бесконечности, этот эффект становится незначительным.
моя текущая загвоздка в попытке получить множественные интеграции на оценка плотности ядра Гаусса в SciPy. Я пытаюсь использовать это составляющей dblquad для выполнения интеграции, но в последнем случае я получаю поразительный поток следующих сообщений.
когда я поставил numpy.seterr ( all='ignore' )
:
предупреждение: вхождение округления обнаружена ошибка, которая предотвращает требуемый допуск от достигнутый. Ошибка может быть недооцененный.
и когда я установил его в 'call'
использование обработчика ошибок:
ошибка с плавающей запятой (underflow), с флагом 4
ошибка с плавающей запятой (недопустимое значение), с флагом 8
довольно легко понять, что происходит, не так ли? Ну, почти: IEEE 754-2008 и Сципи только скажи мне, что здесь происходит, а не почему или как работать вокруг него.
в итоге: minfo_xy
как правило, сводится к nan
; его выборка недостаточна для предотвращения потери или недействительности информации при выполнении float64 math.
существует ли общее решение этой проблемы при использовании SciPy?
еще лучше: если есть надежная, консервированная реализация непрерывной взаимной информации для Python с интерфейсом, который принимает две коллекции плавающих значения точек или Объединенная коллекция пар, это позволит разрешить эту проблему. Пожалуйста, свяжите его, если вы знаете о том, что существует.
спасибо заранее.
Edit: это решает 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
или какое-то другое большое число -- которое может исключить Нэн результаты, созданные простыми арифметическими операциями над входными переменными.
никаких обещаний на этом, но иногда полезно попробовать быстрое исправление, прежде чем заниматься значительной алгоритмической переписью или заменой альтернативных инструментов.