¿Cómo genero un histograma para una distribución de probabilidad determinada (para probar funcionalmente un servidor)?

StackOverflow https://stackoverflow.com/questions/53786

Pregunta

Estoy intentando automatizar las pruebas funcionales de un servidor utilizando una distribución de frecuencia de solicitudes realista.(una especie de prueba de carga, una especie de simulación)

he elegido el Weibull distribución, ya que "en cierto modo" coincide con la distribución que he observado (aumenta rápidamente, disminuye rápidamente pero no instantáneamente)

Utilizo esta distribución para generar la cantidad de solicitudes que deben enviarse cada día entre una fecha de inicio y una fecha de finalización determinadas.

He creado un algoritmo en Python que funciona pero parece complicado:

how_many_days = (end_date - start_date).days
freqs = defaultdict(int)
for x in xrange(how_many_responses):
    freqs[int(how_many_days * weibullvariate(0.5, 2))] += 1
timeline = []
day = start_date
for i,freq in sorted(freqs.iteritems()):
    timeline.append((day, freq))
    day += timedelta(days=1)
return timeline

¿Qué mejores formas existen de hacer esto?

¿Fue útil?

Solución

Esto es rápido y probablemente no tan preciso, pero si calcula el PDF usted mismo, al menos hará que sea más fácil colocar varios más pequeños o más grandes en una sola línea de tiempo. dev es la desviación estándar en el ruido guassiano, que controla la rugosidad.Tenga en cuenta que esto es no la forma "correcta" de generar lo que deseas, pero es fácil.

import math
from datetime import datetime, timedelta, date
from random import gauss

how_many_responses = 1000
start_date = date(2008, 5, 1)
end_date = date(2008, 6, 1)
num_days = (end_date - start_date).days + 1
timeline = [start_date + timedelta(i) for i in xrange(num_days)]

def weibull(x, k, l):
    return (k / l) * (x / l)**(k-1) * math.e**(-(x/l)**k)

dev = 0.1
samples = [i * 1.25/(num_days-1) for i in range(num_days)]
probs = [weibull(i, 2, 0.5) for i in samples]
noise = [gauss(0, dev) for i in samples]
simdata = [max(0., e + n) for (e, n) in zip(probs, noise)]
events = [int(p * (how_many_responses / sum(probs))) for p in simdata]

histogram = zip(timeline, events)

print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram)

Otros consejos

¿Por qué no lo intentas? El molinillo 3 Para probar la carga de su servidor, viene con todo esto y más prediseñado, y es compatible con Python como lenguaje de secuencias de comandos.

Una revisión un poco más larga pero probablemente más legible de sus últimas cuatro líneas:

samples = [0 for i in xrange(how_many_days + 1)]
for s in xrange(how_many_responses):
    samples[min(int(how_many_days * weibullvariate(0.5, 2)), how_many_days)] += 1
histogram = zip(timeline, samples)
print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram)

Esto siempre deja caer las muestras dentro del rango de fechas, pero obtiene un aumento correspondiente al final de la línea de tiempo de todas las muestras que están por encima del rango [0, 1].

En lugar de dar el número de solicitudes como un valor fijo, ¿por qué no utilizar un factor de escala?Por el momento, estás tratando las solicitudes como una cantidad limitada y aleatorizando los días en los que caen esas solicitudes.Parecería más razonable tratar sus solicitudes por día como independientes.

from datetime import *
from random import *

timeline = []
scaling = 10
start_date = date(2008, 5, 1)
end_date = date(2008, 6, 1)

num_days = (end_date - start_date).days + 1
days = [start_date + timedelta(i) for i in range(num_days)]
requests = [int(scaling * weibullvariate(0.5, 2)) for i in range(num_days)]
timeline = zip(days, requests)
timeline

Reescribí el código anterior para que fuera más corto (¿pero tal vez ahora esté demasiado confuso?)

timeline = (start_date + timedelta(days=days) for days in count(0))
how_many_days = (end_date - start_date).days
pick_a_day = lambda _:int(how_many_days * weibullvariate(0.5, 2))
days = sorted(imap(pick_a_day, xrange(how_many_responses)))
histogram = zip(timeline, (len(list(responses)) for day, responses in groupby(days)))
print '\n'.join((d.strftime('%Y-%m-%d ') + "*" * c) for d,c in histogram)

Otra solución es utilizar Rpy, que pone todo el poder de R (incluidas muchas herramientas para distribuciones) fácilmente en Python.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top