Tengo un pequeño problema que me está volviendo loco. Tengo que escribir el procedimiento para un proceso de adquisición en línea de una serie de tiempo multivariante. En cada intervalo de tiempo (por ejemplo, 1 segundo), obtengo una nueva muestra, que es básicamente un vector de coma flotante de tamaño N. La operación que necesito hacer es un poco complicada:
Para cada nueva muestra, calculo los porcentajes para esa muestra (normalizando el vector para que los elementos sumen 1).
Calculo el vector de porcentajes promedio de la misma manera, pero usando los valores pasados.
Para cada valor pasado, calculo la desviación absoluta del vector de porcentajes relacionado con esa muestra con el vector de porcentajes promedio global calculado en el paso 2. De esta manera, la desviación absoluta es siempre un número entre 0 (cuando el vector es igual al promedio vector) y 2 (cuando es totalmente diferente).
Utilizando el promedio de las desviaciones para todas las muestras anteriores, calculo la desviación absoluta media, que nuevamente es un número entre 0 y 2.
Utilizo la desviación media absoluta para detectar si una nueva muestra es compatible con las otras muestras (comparando su desviación absoluta con la desviación media absoluta de todo el conjunto calculado en el paso 4).
Dado que cada vez que se recolecta una nueva muestra, el promedio global cambia (y también la desviación absoluta media también cambia), ¿hay alguna manera de calcular este valor sin escanear el conjunto de datos completo varias veces? (una vez para calcular los porcentajes promedio globales y una vez para recopilar las desviaciones absolutas). Ok, sé que es absolutamente fácil calcular los promedios globales sin escanear todo el conjunto, ya que solo tengo que usar un vector temporal para almacenar la suma de cada dimensión, pero ¿qué pasa con la desviación absoluta media? Su cálculo incluye elabs()
operador, ¡así que necesito acceder a todos los datos pasados!
Gracias por tu ayuda.
fuente
He utilizado el siguiente enfoque en el pasado para calcular la desviación de absolución de manera moderadamente eficiente (tenga en cuenta que este es un enfoque de programadores, no un estadístico, por lo que indudablemente puede haber trucos inteligentes como el de shabbychef que podrían ser más eficientes).
ADVERTENCIA: este no es un algoritmo en línea. Requiere
O(n)
memoria Además, tiene un rendimiento en el peor de los casosO(n)
, para conjuntos de datos como[1, -2, 4, -8, 16, -32, ...]
(es decir, el mismo que el recálculo completo). [1]Sin embargo, debido a que aún funciona bien en muchos casos de uso, podría valer la pena publicarlo aquí. Por ejemplo, para calcular la desviación absoluta de 10000 números aleatorios entre -100 y 100 a medida que llega cada elemento, mi algoritmo tarda menos de un segundo, mientras que el recálculo completo lleva más de 17 segundos (en mi máquina, variará por máquina y según datos de entrada). Sin embargo, debe mantener todo el vector en la memoria, lo que puede ser una restricción para algunos usos. El esquema del algoritmo es el siguiente:
O(n)
operaciones de movimiento, para muchos casos de uso esto no es así.Algún código de muestra, en python, está debajo. Tenga en cuenta que solo permite agregar elementos a la lista, no eliminarlos. Esto podría agregarse fácilmente, pero en el momento en que escribí esto no lo necesitaba. En lugar de implementar las colas de prioridad yo mismo, he usado la lista ordenada del excelente paquete blist de Daniel Stutzbach , que usa B + Tree s internamente.
Considere este código licenciado bajo la licencia MIT . No se ha optimizado ni pulido significativamente, pero ha funcionado para mí en el pasado. Nuevas versiones estarán disponibles aquí . Avíseme si tiene alguna pregunta o si encuentra algún error.
[1] Si los síntomas persisten, consulta a tu médico.
fuente
O(n)
memoria y, en el peor de los casos, toma O (n) tiempo para cada elemento agregado. Sin embargo, en los datos distribuidos normalmente (y probablemente en otras distribuciones) funciona de manera bastante eficiente.fuente
MAD (x) es solo dos cálculos medios concurrentes, cada uno de los cuales se puede hacer en línea a través del binmedian algoritmo .
Puede encontrar el documento asociado, así como el código C y FORTRAN en línea aquí .
(esto es solo el uso de un truco inteligente además del ingenioso truco de Shabbychef, para ahorrar memoria).
Apéndice:
Existe una gran cantidad de métodos antiguos de múltiples pasos para calcular cuantiles. Un enfoque popular es mantener / actualizar un reservorio de observaciones de tamaño determinista seleccionado al azar de la corriente y calcular cuantiles de forma recursiva (ver esta revisión) en este reservorio. Este enfoque (y el relacionado) son reemplazados por el propuesto anteriormente.
fuente
Lo siguiente proporciona una aproximación inexacta, aunque la imprecisión dependerá de la distribución de los datos de entrada. Es un algoritmo en línea, pero solo se aproxima a la desviación absoluta. Se basa en un algoritmo bien conocido para calcular la varianza en línea, descrito por Welford en la década de 1960. Su algoritmo, traducido a R, se ve así:
Se realiza de manera muy similar a la función de varianza incorporada de R:
La modificación del algoritmo para calcular la desviación absoluta simplemente implica una
sqrt
llamada adicional . Sin embargo,sqrt
presenta imprecisiones que se reflejan en el resultado:Los errores, calculados como arriba, son mucho mayores que para el cálculo de la varianza:
Sin embargo, dependiendo de su caso de uso, esta magnitud de error puede ser aceptable.
fuente
n
hace más grande,error/n
se desvanece muy poco, sorprendentemente rápido.sqrt
imprecision. It is because it uses the running mean estimate. To see when this will break, tryxs <- sort(rnorm(n.testitems))
When I try this with your code (after fixing it to returna.dev / n
), I get relative errors on the order of 9%-16%. So this method is not permutation invariant, which could cause havoc...