floating point - Algoritmo de compresión para datos IEEE-754
floating-point compression (6)
¿Puedes hacer un delta entre valores adyacentes?
¿Hay un límite a cuánto puede cambiar un valor entre mediciones? ¿Es aceptable limitar este cambio a algún valor de tasa máxima (al costo de introducir algún ajuste)?
Obviamente, hay un límite a la precisión real de los valores del sensor térmico. ¿Necesita almacenar 64 bits de precisión o es mejor almacenar un número entero de, por ejemplo, unidades de 0.01-Kelvin?
Si puede vivir con algún error más y el aumento es relativamente suave, es mejor que ajuste una función a los datos y almacene solo algunos términos de la función.
EDITAR:
Observe un conjunto de datos típico y observe el rango de diferencias entre valores adyacentes. Luego mira qué precisión necesitas para representar esto.
p.ej. Si tiene una diferencia máxima de 1deg entre lecturas, puede almacenar cambios de 1/256 de esto en un byte. Si necesita almacenar un rango mayor o más preciso, use un corto dividido por algún factor.
Entonces la siguiente lectura sería = last_reading + (float) increment / 256.0
¿Alguien tiene una recomendación sobre un buen algoritmo de compresión que funcione bien con valores de punto flotante de doble precisión? Hemos encontrado que la representación binaria de valores de punto flotante produce tasas de compresión muy bajas con programas de compresión comunes (por ejemplo, Zip, RAR, 7-Zip, etc.).
Los datos que necesitamos para comprimir son una matriz unidimensional de valores de 8 bytes ordenados en orden monótonamente creciente. Los valores representan temperaturas en Kelvin con un intervalo típicamente inferior a 100 grados. El número de valores varía desde unos pocos cientos hasta un máximo de 64K.
Aclaraciones
Todos los valores de la matriz son distintos, aunque la repetición existe en el nivel de bytes debido a la forma en que se representan los valores de punto flotante.
Se desea un algoritmo sin pérdidas ya que se trata de datos científicos. La conversión a una representación de punto fijo con suficiente precisión (~ 5 decimales) podría ser aceptable siempre que haya una mejora significativa en la eficiencia de almacenamiento.
Actualizar
Encontré un interesante artículo sobre este tema. No estoy seguro de cómo aplicar el enfoque es a mis necesidades.
Lo primero que debe considerar: intente comprimir los datos antes de convertirlos a precisión doble. Re sus comentarios a David Thornley, a menos que sus ADC de imágenes IR tengan 24 bits significativos, los flotadores de 32 bits deberían tener una precisión más que suficiente; solo es su requisito preservar exactamente el ruido generado por el procesamiento posterior que es un problema. De no ser así, podría ser práctico aplicar ingeniería inversa a su procesamiento, al determinar la tabla de valores que genera y, en su lugar, almacenar un índice en esta tabla.
Segundo: si su algoritmo de compresión sabe que sus datos están en fragmentos de 8 bytes, será mucho más efectivo; esto se debe a que no lanzará sus bytes más significativos con los bytes menos significativos. Como un método de preprocesamiento en bruto, puede intentar prefijar cada doble con un byte distintivo (¿coma ASCII, quizás?) Antes de canalizarlo a través de un compresor basado en bytes como gzip; esto debería dar como resultado una mejor compresión total aunque el flujo intermedio sea un 12% más grande. Menos esfuerzo pero más esfuerzo sería escribir su propia compresión adaptada a esta tarea, tal vez utilizando un árbol de 8 niveles para representar los valores esperados de cada byte en su doble.
Tercero: como los datos de imagen son altamente redundantes, alguna forma de codificación delta u otra compresión relacionada con la imagen debería ahorrar algo de espacio. Sin embargo, no le ganará una cantidad terriblemente grande si exige una compresión sin pérdida, ya que el ruido de la imagen es intrínsecamente incompresible. Además, no te ayudará a lidiar con el hash pseudoaleatorio en los bits menos significativos de tus dobles, como se explicó anteriormente.
Los algoritmos de compresión viven de repeticiones y regularidades, y los números de punto flotante no funcionan bien en eso.
La primera pregunta es si puede usar valores de punto flotante de precisión simple, lo que le dará una compresión del 50% inmediatamente. Pocos termómetros tienen una precisión de siete dígitos, y el exponente representará temperaturas muy por debajo de lo que me han dicho que realmente puede obtener.
De no ser así, ¿puede filtrar sus temperaturas y redondearlas al equivalente de N dígitos (más probablemente N / .301 bits)? Eso puede introducir suficientes regularidades para ser útil.
Si realmente tiene que almacenar 64 bits de información para cada lectura de temperatura, y todos los bits son significativos y no predecibles a partir de los otros bits, entonces no puede comprimirlos.
Podría pensar en volver a codificar sus datos con un codificador de entropía (Huffman, Shannon-Fano, Arithmetic Coding). Pero esto solo proporcionará buenos resultados si tiene muchas repeticiones de los puntos de datos y si sabe qué símbolos aparecerán con qué probabilidad.
Si desea un almacenamiento de archivos de alta compresión, "Compresión de alto rendimiento de datos de punto flotante de doble precisión" de Burtscher & Patanaworabhan o "Compresión rápida y eficiente de datos de punto flotante" de Lindstrom & Isenberg puede ser de ayuda.
Si desea un acceso dinámico más rápido a expensas de una tasa de compresión más baja, entonces puede ser adecuado un wavelet de elevación 1D. Puede cuantizar los datos en enteros más pequeños especificando el número de dígitos que se conservarán. Luego use la codificación delta con un modelo predictivo seguido de una transformación con Haar o una transformación wavelet más costosa y una codificación aritmética de los coeficientes mayores que un valor específico.
Espero eso ayude
Puede obtener el algoritmo ZFP de Lindstrom aquí: https://github.com/LLNL/zfp
Todos los codificadores que enumera están orientados a bytes, y se eliminan por algunas propiedades de dobles. Por un lado, hay un diseño en el que el exponente / signo de 12 bits no juega bien con los límites de bytes, en el otro, el ruido de su entrada. La primera parte es fácil de manejar de muchas maneras, la segunda limitará la efectividad de cualquier compresión sin pérdida que le lances. Creo que incluso el mejor resultado será menos sorprendente, no conozco tus datos, pero sospecho que puedes contar con solo un 25% de ahorro, más o menos.
Desde lo alto de mi cabeza, y tal vez sea inútil porque has pensado en todo lo que está en esta lista ...
Trate el flujo como enteros de 64 bits y codifique los valores adyacentes delta. Si tiene series de valores con el mismo exponente, efectivamente lo pondrá a cero, así como posiblemente algunos bits de mantisa alta. Habrá desbordamientos, pero los datos aún necesitan solo 64 bits y la operación puede revertirse.
En esta etapa, opcionalmente, puede probar alguna predicción de entero bruto y guardar diferencias.
Si ha seguido la sugerencia anterior, tendrá casi la mitad de los valores comenzando con 000 ... y casi la mitad con FFF ... Para eliminar eso, gire el valor hacia la izquierda (ROL) en 1 bit y XOR con todos los Fs si el LSB actual es 1. El reverso es XOR con Fs si LSB es 0, entonces ROR.
Pensándolo bien, simplemente las predicciones de XORing a valores verdaderos pueden ser mejores que la diferencia, porque no tiene que hacer el paso 3 en ese momento.
Puede intentar reordenar bytes para agrupar bytes con el mismo significado. Como primero, todos los bytes más significativos, y así sucesivamente. Como mínimo, debería obtener algo así como una corrida masiva de ceros con un mínimo de pocos bits de ruido primero.
Ejecute un compresor genérico o incluso un primer RLE en la ejecución de ceros, luego un codificador de entropía, como huffman, o mejor, un codificador de rango de 7zip / LZMA.
Hay algo bueno acerca de sus datos, es monótono. Hay algo malo en tus datos: es simplemente un conjunto demasiado pequeño. ¿Cuánto quieres ahorrar, simples kilobyes? ¿Para qué? La efectividad de la compresión sufrirá mucho si a menudo hay una diferencia exponencial entre los valores adyacentes.
Si está procesando una gran cantidad de esos conjuntos de datos, debería considerar usar su similitud para comprimirlos mejor juntos, quizás intercalarlos en algún momento. Si puede vivir con alguna pérdida, la reducción a cero de algunos bytes menos significativos podría ser una buena idea, tal vez tanto en los datos de origen como en la predicción para que no vuelva a introducir ruido allí.