2010-09-28 8 views
11

Estoy ejecutando Python 2.6.5 en Mac OS X 10.6.4 (esta no es la versión nativa, lo instalé yo mismo) con Scipy 0.8.0. Si hago lo siguiente:¿Pueden algunos explicar este extraño comportamiento de la distribución hipergeométrica en scipy?

>>> from scipy.stats import hypergeom 
>>> hypergeom.sf(5,10,2,5) 

consigo un IndexError. Entonces lo hago:

>>> hypergeom.sf(2,10,2,2) 
-4.44.... 

Sospecho que el valor negativo se debe a la mala precisión del punto flotante. Luego hago el primero de nuevo:

>>> hypergeom.sf(5,10,2,5) 
0.0 

¡Ahora funciona! ¿Alguien puede explicar esto? ¿Estás viendo este comportamiento también?

+2

Se hace lo mismo en Python 2.6.6 en Debian. – eumiro

+2

Para lo que sea que valga, parece que podría tratarse de un error y, por lo tanto, sería mejor preguntarlo en la lista scipy-users: http://mail.scipy.org/mailman/listinfo/scipy-user Es más probable que aparezca la atención de los desarrolladores allí ... –

+5

Abrí un ticket para esto: http://projects.scipy.org/scipy/ticket/1291. Como mencionó Joe Kington, sería útil informar errores o comportamientos inesperados a la lista de correo o al rastreador de errores de un paquete. – user333700

Respuesta

3

El problema parece surgir basado si la primera llamada a la función de supervivencia está en el rango que obviamente debería ser cero (ver mi comentario a la respuesta anterior). Por ejemplo, para llamadas a hypergeom.sf (x, M, n, N) falla si la primera llamada a una función hipergeométrica para la función es una situación donde x> n, donde la función de supervivencia siempre será cero.

Se podría solucionar este problema trivial temporalmente por:

def new_hypergeom_sf(k, *args, **kwds): 
    from scipy.stats import hypergeom 
    (M, n, N) = args[0:3] 
    try: 
     return hypergeom.sf(k, *args, **kwds) 
    except Exception as inst: 
     if k >= n and type(inst) == IndexError: 
      return 0 ## or conversely 1 - hypergeom.cdf(k, *args, **kwds) 
     else: 
      raise inst 

Ahora bien, si usted no tiene ningún problema en la edición de la /usr/share/pyshared/scipy/stats/distributions.py (o archivo equivalente), el arreglo es probable que en la línea 3966, donde en este momento se lee:

place(output,cond,self._sf(*goodargs)) 
    if output.ndim == 0: 
     return output[()] 
    return output 

Pero si lo cambia a:

if output.ndim == 0: 
     return output[()] 
    place(output,cond,self._sf(*goodargs)) 
    if output.ndim == 0: 
     return output[()] 
    return output 

Ahora funciona sin IndexError. Básicamente, si el resultado es de dimensión cero porque falla las comprobaciones, intenta llamar al lugar, falla y no genera la distribución. (Esto no ocurre si ya se ha creado una distribución previa, lo que probablemente explica por qué no se detectó en las pruebas anteriores). Tenga en cuenta que el lugar (definido en la función_base.py de numpy) cambiará los elementos de la matriz (aunque estoy no estoy seguro si cambia la dimensionalidad) por lo que es mejor dejar que deje la verificación de 0 dim después del lugar también. No he probado completamente esto para ver si este cambio rompe cualquier otra cosa (y se aplica a todas las distribuciones discretas de variables aleatorias), por lo que quizás sea mejor hacer la primera corrección.

Lo rompe; Por ejemplo, stats.hypergeom.sf (1,10,2,5) regresa como cero (en lugar de 2/9).

Esta solución parece funcionar mucho mejor, en la misma sección:

class rv_discrete(rv_generic): 
... 
    def sf(self, k, *args, **kwds): 
    ... 
     if any(cond): 
      place(output,cond,self._sf(*goodargs)) 
     if output.ndim == 0: 
      return output[()] 
     return output 
1

No sé pitón, pero la función se define de esta manera: hypergeom.sf (x, M, n, N, loc = 0)

M es el número de objetos interesantes, N el número total de objetos, yn es la frecuencia con la que "eliges uno" (Lo siento, estadístico alemán).

Si tuviera un recipiente con 20 bolas, 7 de los amarillo (una interesante amarilla), entonces n es 20 y M es 7.

Tal vez la función se comporta de forma indefinida en el (sin sentido) caso cuando M> N?

+0

La función definida en python está bien definida para los valores de M, n, N utilizados. Desde docstring en python para scipy.stats.hypergeom, M es el número total de objetos, n es el número de objetos de tipo 1 y N se dibujan sin reemplazo. Entonces los probs son hipergeom (x = 0,10,2,5) = 2/9, hypergeom (x = 1,10,2,5) = 5/9, hypergeom (x = 2,10,2,5) = 2/9; entonces la función de supervivencia para x <0 es 0, es 7/9 para 0 <= x <1, 2/9 para 1 <= x <2, y 0 para 2 <= x. Para el sf (función de supervivencia, leer como 1-cdf, función de distribución acumulativa) de la distribución hipergeométrica, sabemos que la respuesta debería ser 0. –

Cuestiones relacionadas