Número de contenedores al calcular información mutua

10

Quiero cuantificar la relación entre dos variables, A y B, utilizando información mutua. La forma de calcularlo es agrupando las observaciones (ver ejemplo de código Python a continuación). Sin embargo, ¿qué factores determinan qué número de contenedores es razonable? Necesito que el cálculo sea rápido, así que no puedo simplemente usar muchos contenedores para estar seguro.

from sklearn.metrics import mutual_info_score

def calc_MI(x, y, bins):
    c_xy = np.histogram2d(x, y, bins)[0]
    mi = mutual_info_score(None, None, contingency=c_xy)
    return mi
pir
fuente

Respuestas:

15

No existe el mejor número de contenedores para estimar la información mutua (MI) con histogramas. La mejor manera es elegirlo mediante validación cruzada si puede, o confiar en una regla general. Esta es la razón por la cual se han propuesto muchos otros estimadores de IM que no se basan en histogramas.

El número de contenedores dependerá del número total de puntos de datos . Debe intentar evitar demasiados contenedores para evitar errores de estimación para la distribución conjunta entre las dos variables. También debe evitar muy pocos contenedores para poder capturar la relación entre las dos variables. Dado que genera un histograma 2D con bins de igual ancho para ambos y yo personalmente elegiría: En este caso, en promedio para dos variables aleatorias distribuidas uniformemente, tendrá al menos puntos para cada celda del histograma: D = nnp.histogram2d(x, y, D)Dxy5 n

D=n/5
5
nDXDY5nD25D2n/5D=n/5
Esta es una opción posible que simula el enfoque de partición adaptativo propuesto en (Cellucci, 2005) . El último enfoque se usa a menudo para estimar MI para inferir redes genéticas: por ejemplo, en MIDER .

Si tiene muchos puntos de datos y no faltan valores, no debe preocuparse demasiado por encontrar la mejor cantidad de contenedores; por ejemplo, si . Si este no es el caso, puede considerar corregir MI para muestras finitas. (Steuer et al., 2002) discute alguna corrección para MI para la tarea de inferencia de red genética.n = 100 , 000nn=100,000


Estimar el número de contenedores para un histograma es un viejo problema. Tal vez le interese esta charla de Lauritz Dieckman sobre la estimación del número de contenedores para MI. Esta charla se basa en un capítulo del libro de Mike X Cohen sobre series temporales neurales.

Puede elegir y independiente y usar la regla general utilizada para estimar el número de bins en los histogramas 1D.D YDXDY

Regla de Freedman-Diaconis (sin suposición sobre la distribución): donde es la diferencia entre el 75-cuantil y el 25-cuantil. Mire esta pregunta relacionada en SE .

DX=maxXminX2IQRn1/3
IQR

Regla de Scott (suposición de normalidad): donde es la desviación estándar para .

DX=maxXminX3.5sXn1/3
sXX

Regla de Sturges (puede subestimar el número de bins pero es bueno para grande ): n

DX=1+log2n

Es difícil estimar correctamente el IM con histogramas. Entonces puede elegir un estimador diferente:

  • El estimador NN de Kraskov , que es un poco menos sensible a la elección de parámetros: o vecinos más cercanos a menudo se usa por defecto. Documento: (Kraskov, 2003)kk=4k=6
  • Estimación de MI con Kernels (Moon, 1995) .

Hay muchos paquetes para estimar MI:

  • Caja de herramientas de estimación de entropía no paramétrica para Python. sitio .
  • Kit de herramientas de dinámica de información en Java, pero también disponible para Python. sitio .
  • Caja de herramientas ITE en Matlab. sitio .
Simone
fuente
1

Prefiero minepyobtener y estimar información mutua en python.

Puede ver los detalles de implementación del paquete aquí , y un código de ejemplo aquí . En aras de una referencia más fácil, copio y pego el ejemplo y se muestra aquí:

import numpy as np
from minepy import MINE

def print_stats(mine):
    print "MIC", mine.mic()
    print "MAS", mine.mas()
    print "MEV", mine.mev()
    print "MCN (eps=0)", mine.mcn(0)
    print "MCN (eps=1-MIC)", mine.mcn_general()

x = np.linspace(0, 1, 1000)
y = np.sin(10 * np.pi * x) + x
mine = MINE(alpha=0.6, c=15)
mine.compute_score(x, y)

print "Without noise:"
print_stats(mine)
print

np.random.seed(0)
y +=np.random.uniform(-1, 1, x.shape[0]) # add some noise
mine.compute_score(x, y)

print "With noise:"
print_stats(mine)

Lo que da esto como salida:

Without noise:
MIC 1.0
MAS 0.726071574374
MEV 1.0
MCN (eps=0) 4.58496250072
MCN (eps=1-MIC) 4.58496250072

With noise:
MIC 0.505716693417
MAS 0.365399904262
MEV 0.505716693417
MCN (eps=0) 5.95419631039
MCN (eps=1-MIC) 3.80735492206

Mi experiencia es que los resultados son sensibles alphay el valor predeterminado .6es razonable. Sin embargo, en mis datos reales alpha=.3es mucho más rápido y la información mutua estimada tiene una correlación realmente alta con el caso alpha=.6. Entonces, en caso de que esté utilizando MI para seleccionar los que tienen un MI alto, simplemente puede usar uno más pequeño alphay usar los valores más altos como reemplazo con una buena precisión.

adrin
fuente
¡Gracias! ¿Has comparado minepy con sklearn para estimar MI?
pir
No, no lo he hecho. ¡Aunque no estoy seguro de por qué no!
Adrin
Acabo de hacer una comparación de sklearn y minepy (tanto alpha = 0.3 como alpha = 0.6). ¡Los resultados son muy diferentes! Dado que es tan fácil, probablemente también debería verificar sus resultados usando ambas bibliotecas :)
pir
2
MIC no es igual a la información mutua (MI). Son dos cosas completamente diferentes.
Simone
1
Si seguro. En el documento original de MIC hay muchas comparaciones entre MI y MIC: uvm.edu/~cdanfort/csc-reading-group/… MIC muestra que puede usarse como un proxy de la cantidad de ruido para una relación funcional: propiedad que se llama 'equidad' en el documento original. No obstante, el IM sigue siendo una muy buena medida de dependencia para muchas tareas: por ejemplo, selección de características o inferencia de red genética. También es más rápido de estimar que MIC.
Simone