lunes, 2 de abril de 2012

[MSDS] Tarea 3 Pruebas estadísticas para los números pseudoaleatorios

El objetivo de esta tarea es determinar si los generadores de números pseudoaleatorios incluidos en las librerias de los diferentes lenguajes de programación se apegan a alguna distribución y si los mismos presentan las características deseables de los números pseudoaleatorios.

Herramientas

  • Lenguaje de Programación: Python
  • Libreria generadora de números pseudoaleatorios: random.normalvariate(0,1) (Normal Estándar)
  • Distribución a evaluar: Normal
  • Libreria de Pruebas Estadisticas: Scipy
  • Graficador: GNUPlot

1. ¿Los números generados de acoplan a la distribución indicada?


Para realizar esta prueba primero realice un código en Python que, con la ayuda de la libreria random, nos permite generar números pseudoaleatorios.
En mi caso voy a generar números pseudoaleatorios que se acoplen a la distribución normal utilizando la función random.randomvariate(0,1), como vemos, los parámetros serán 0 y 1, esto es, significancia = 0 y una desviación = 1, para seguir una normal estándar.
Por default se generan 10000 números, ya que hay que tener una muestra bastante grande; pero es posible enviar la cantidad como parámetro también.
Además se implementa una prueba de Anderson (scipy.stats.anderson), al generar los números, éstos se van almacenando en una lista, la lista se envía a la prueba Anderson para que los valores sean evaluados y se deteminará si la muestra proviene de una distribución específica (en éste caso, la distribución normal).

Código Python


Una vez que corremos el código, se generará un archivo llamado data.dat, éste contiene los números generados, lo que haré después es graficarlos. Pensé en hacer un código que implementara canastas, sin embargo, decidí dejar el trabajo a GNUPlot, con el siguiente código se generaran canastas de 0.1 unidades de ancho, leeremos el archivo data.dat e iremos creando un histograma de frecuencias.
Adicional a eso, implemente en el archivo de GNUPlot la función de densidad de probabilidad de la distribución normal para ver el acople de la distribución de los números generados y la forma original de la distribución normal. La formula es la siguiente:


Código GNUPlot


Gráfica


Fueron generados 1 000 000 de números, se acomodaron por canastas y formaron un histograma, si lo comparamos con la gráfica normal estandar (en rojo, con líneas) podemos ver que se acoplan casi perfectamente, tentativamente podemos deducir que efectivamente los números generados por random.randomvariate() si se acoplan a la distribución normal.

Prueba Anderson


Los resultados de la prueba Anderson para la muestra de 1 000 000 fueron:


Las hipótesis relacionadas no fueron rechazadas para todos los niveles de significancia, entonces podemos terminar de deducir que los números si se acoplan a la distribución normal.

2. ¿Los números generados presentan características deseables de "números aleatorios"?


Para las pruebas de aleatoriedad decidi basarme en la pagina random.org y leer un poco sobre los test, entonces me puse implementar 2 de ellos:

1. Frecuency Monobit

El propósito de esta prueba es calcular la proporción de ceros y unos en una muestra dada de números pseudoaleatorios.
Se espera que la proporción sea aproximadamente el mismo, es decir, que la proporción de unos dea 1/2 y la proporción de ceros también.

2. Frecuency Block

El enfoque de la prueba es calcular la proporción de unos en una muestra dada e números aleatorios, pero esta ves, la secuencia es dividida en bloques más pequeños y del mismo tamaño.
El propósito de este ensayo es determinar si la frecuencia de unos en un bloque de M-bits es de aproximadamente M / 2, como sería espera que en el supuesto de aleatoriedad.

Código


Ésta es la implementación de las pruebas, para hacerlo un poco más equilibrado, decidí comparar 2 muestras diferentes de 10000 números pseudoaleatorios cada una. La primera es generada con random.normalvariate() redondeando algunos valores y aplicando algunas condiciones para obtener valores binarios 0 y 1. La segunda es generada con random.randint() poniendo como limites 0 y 1 obviamente.
Después ambas listas se envían a evaluar, primero por Frecuency Monobit y después por Frecuency Block:


Los resultados de las pruebas para ambas listas fueron:



Podemos ver como para la lista generada por random.normalvariate() la proporción es 1, podemos deducir que la probabilidad entre ceros y unos es idéntica, por lo que se trata de una librería que cumple con los estándares para la generación de números aleatorios. No sorprende que haya pasado ambas pruebas.
No podemos decir lo mismo de la librería random.randint() cuya proporción es bastante baja comparada con la anterior. Podemos ver que cumple con los estándares de la prueba monobit, pero la prueba de bloques fue un fracaso total, entonces es 50% menos confiable que la random.normalvariate() además del umbral que las separa a las dos por la prueba monobit.

Referencias

1 comentario: