viernes, 20 de abril de 2012

[MODELADO Y SIMULACIÓN] Pruebas estadísticas para números pseudoaleatorios

En esta tarea se seleccionara una librería de cualquier tipo que genere números pseudoaleatorios siguiendo una distribución, y comprobaremos que tan aleatorios son estos números generados.

Librería generadora de números pseudoaleatorios

Seleccioné la distribución logística generada por la librería numpy (numpy.random.logistic)

Prueba estadística

Cuando se analizan datos medidos por una variable cuantitativa continua, las pruebas estadísticas de estimación y contraste frecuentemente empleadas se basan en suponer que se ha obtenido una muestra aleatoria de una distribución de probabilidad de tipo normal o de Gauss.

Pero en muchas ocasiones esta suposición no resulta válida, y en otras la sospecha de que no sea adecuada no resulta fácil de comprobar, por tratarse de muestras pequeñas.

En estos casos disponemos de dos posibles mecanismos:

Los datos se pueden transformar de tal manera que sigan una distribución normal.
O bien se puede acudir a pruebas estadísticas que no se basan en ninguna suposición en cuanto a la distribución de probabilidad a partir de la que fueron obtenidos los datos, y por ello se denominan pruebas no paramétricas (distribución free), mientras que las pruebas que suponen una distribución de probabilidad determinada para los datos se denominan pruebas paramétricas.

Seleccioné la prueba de Anderson-Darling de la librería scipy para comprobar que la distribución en los números generados es realmente la seleccionada. También se realizó un test de frecuencia para saber que tan aleatorios son los números generados por la librería, en este caso monobit.

Programa

En la práctica me basé en el código de Cecilia y de Juan Carlos para generar los números pseudoaleatorios, utilizando las herramientas anteriormente descritas.

import numpy
from scipy import stats

ls = []

f = open("datos.txt","w")

for i in range(1000):
    dist = numpy.random.logistic(1, 1, None)
    ls.append(dist)
    f.write("%0.3f\n" %dist)

anderson, critical, sig = stats.anderson(ls, dist="logistic")

for i in range(len(critical)):
    if anderson > critical[i]:
        print "Hipotesis rechazada con valor de significancia "+str(sig[i])
    else:
        print "Hipotesis no rechazada con valor de significancia "+str(sig[i])


El código anterior genera 1000 números pseudoaleatorios siguendo la distribución logística. y dando como resultadoestos números graficados, que por lo que se ve, parese que son muy aleatorios:


El programa hace un test de anderson dando como resultado el siguiente:


Parece ser que la distribución es la correcta, puesto que las hipotesis o se rechazan.

Ahora veremos que tan aleatorios son los números mediante monobit.

import math, numpy
from scipy.special import erf
                                                                                                                                                                                                                 
def mono(lista):
    lista2 = [-1 for i in lista if i==0]
    suma = sum(lista) + sum(lista2)
    sumaAbs = abs(suma)/math.sqrt(len(lista)) 
    p_value = erf(sumaAbs/math.sqrt(2))
    
    if(p_value > 0.01):
        print "%f: P" % p_value
    else:
        print "%f: NP" % p_value

def main():
    cantidad = 1000
    L1 = []
    
    for i in range(cantidad):
        x = numpy.random.logistic(1,1, None)
        x = abs(int(round(x)))
        if(x > 1.0):
                x = 1.0
        elif(x < 0.0): 
                x = 0.0
        L1.append(x)
    
    mono(L1)

main()
El código es basado en el del Compañero Juancarlos para realizar la prueba de frecuencia monobit.

El resultado es el siguiente:

Noté que al correr la prueba varias veces, de vez en cuando fallaba. Sin embargo la mayoría de las veces esta pasa. Se puede concluir que genera números aleatorios de forma muy eficiente.

1 comentario:

  1. Todo bien salvo que la ortografía. Van 5 y 5 con los castigos pendientes.

    ResponderEliminar