- Un experimento llevó la clasificación de dígitos manuscritos de MNIST hasta cerca de 78% de precisión usando solo compresión GZIP y k-vecinos más cercanos (k-NN), mostrando que la compresión puede usarse como una herramienta de clasificación sin modelo
- Calcula la distancia de compresión normalizada (NCD) según cuánto cambia la longitud al comprimir dos muestras de imagen juntas, y la usa como métrica de similitud entre imágenes
- Cada muestra de prueba se compara con 100 muestras de entrenamiento, y la etiqueta mayoritaria de los vecinos con k=5 más cercanos se toma como predicción
- Debido al costo computacional, la precisión se midió con solo una parte de las imágenes de prueba en lugar de todo el test set; usar el conjunto completo podría dar una evaluación más precisa
- El ejemplo público todavía contiene un error de refactorización: crea una caché de longitudes comprimidas pero no la usa en el cálculo real de NCD, por lo que haría falta eliminar la caché o reflejarla en
compute_ncd
Clasificar MNIST con GZIP + k-NN
- El experimento clasifica el dataset de dígitos manuscritos MNIST con la combinación GZIP + k-NN
- El ejemplo corto de código usa la longitud del resultado de
gzip.compress(z.tobytes())como longitud comprimida, calcula la NCD y luego elige la etiqueta más frecuente entre los 5 vecinos más cercanos - Hay un ejemplo ejecutable en Jupyter Notebook
- El objetivo no es lograr la máxima precisión, sino validar de forma simple la idea de usar la compresión como una herramienta de clasificación sin modelo
- El código de menos de 10 líneas es más un elemento divertido de code golf que el núcleo del experimento
Cálculo de similitud y procedimiento de clasificación
- La NCD mide la similitud normalizando cuánto difiere el costo de comprimir dos puntos de datos juntos frente a comprimirlos por separado
- La longitud comprimida se calcula así
Cx1 = len(gzip.compress(x1.tobytes()))Cx2 = len(gzip.compress(x2.tobytes()))Cx1x2 = len(gzip.compress((x1 + x2).tobytes()))
- La fórmula de NCD tiene la forma
(Cx1x2 - min(Cx1, Cx2)) / max(Cx1, Cx2) - Para clasificar, se calcula la distancia entre cada imagen de prueba y las imágenes de entrenamiento, se ordenan de menor a mayor y se usa votación mayoritaria de las 5 más cercanas
- En el experimento, la comparación se hizo tomando 100 muestras de entrenamiento como referencia y, por el costo computacional, también se usó solo una parte del test set
Ideas de referencia y detalles a cuidar en el código
- Este enfoque se inspira en el artículo text generation from data compression y en el paper parameter free text classification
- Después de publicar el texto, también se encontró el post MNIST by ZIP de Andreas Kirsch, que en 2019 usó un método similar
- El código de ejemplo crea una caché de longitudes comprimidas para las muestras de entrenamiento, pero en el bucle real no usa esos valores
- Tanto la versión normal como la ofuscada crean
compressed_lengthsocls, pero no usan las longitudes cacheadas en el cálculo de NCD - Si se elimina la caché y se usa
training_setdirectamente, o sicompute_ncdse modifica para aprovechar esos valores, la intención del código y su implementación quedarían alineadas
- Tanto la versión normal como la ofuscada crean
1 comentarios
Opiniones de Hacker News
Al cambiar la función de distancia del código por una métrica más simple, en la clasificación de MNIST la distancia GZIP tiene menor precisión y requiere mucho más cómputo.
Distancia Gzip: aprox. 3 min, 78% de precisión / distancia euclidiana: aprox. 0.5 s, 93% / distancia de Jaccard: aprox. 0.7 s, 94% / disimilitud Dice: aprox. 0.8 s, 94%
Jaccard y Dice se miden después de binarizar las imágenes.
No conozco mucho el algoritmo GZIP, pero me parece interesante que el resultado sea tan bajo, y me pregunto si un algoritmo de compresión centrado en imágenes podría funcionar mejor.
El artículo en sí es creativo, y el código y la explicación también son buenos, pero creo que esas líneas base aportan contexto a la puntuación de gzip.
NMI skimage: aprox. 30 s, 95% de precisión / NMI numba: aprox. 0.6 s, 95% de precisión
Calculé los conteos conjuntos 2x2, la entropía y la información mutua normalizada con código
numbaque me dio ChatGPT.En lo personal me interesa el entrenamiento rápido en CIFAR10, así que este enfoque parece poder ser bastante útil también en otros dominios.
https://github.com/benjamin-recht/mnist_1_pt_2/tree/main
También probé zstandard, y Zstd(level=3) fue mucho más rápido que gzip, con aprox. 88% de precisión en 3.5 s.
Al calcular
Cx1x2, si se usa(x1-x2)*2en vez dex1+x2, zstd sube hasta 93% de precisión.Si en vez de sumar los dos arreglos se apilan uno encima del otro, el rendimiento se destruye por completo y cae por debajo de 20%, pero es interesante porque en clasificación de cadenas parece que ese método funciona bien.
Comparado con otras técnicas, Linear SVC ronda el 92%, SVC con kernel RBF el 96.4%, SVC con kernel polinómico el 94.5%, regresión logística el 89% y Naive Bayes alrededor del 81%.
Fuente: https://dmkothari.github.io/Machine-Learning-Projects/SVM_wi...
Por lo que se ve en artículos en línea, solo con K-NN parecen posibles resultados mucho mejores, así que quizás el autor se complicó más el trabajo al usar gzip.
Me gusta empezar con modelos simples y agregar complejidad después, pero muchas veces escuché “la regresión logística no sirve” incluso en problemas donde en realidad funcionaría bien.
Cuando se pregunta qué rendimiento base esperarían en MNIST, muchos estiman 20~30%.
Incluso quienes hacen machine learning suelen subestimar lo rápido que aparece el rendimiento decreciente al aumentar mucho la complejidad del modelo.
En muchos casos, si el rendimiento no era bueno con un modelo simple, también era difícil obtener un rendimiento excelente con un modelo más complejo.
El paper original que presentó el dataset MNIST también logró alrededor de 98% de precisión, y las redes neuronales actuales llegan hasta 99.87%.
https://paperswithcode.com/sota/image-classification-on-mnis...
La compresión está pensada justamente para hacer más difícil el problema original, y de hecho sigue funcionando así.
Otros modelos tienden a agregar ruido en algún punto, así que me pregunto qué pasaría si se incorporara ingeniería de características antes de gzip.
Por ejemplo, parece posible aplicar primero desenfoque gaussiano y convoluciones, y luego usar deep learning para la selección de características.
El código puede ser elegante y breve, pero 78% de precisión en MNIST es bastante malo.
Incluso un modelo dummy hecho con TensorFlow llega fácilmente a 90% de precisión, y el mejor modelo alcanza 99.87%.
Benchmark: https://paperswithcode.com/sota/image-classification-on-mnis...
Lo interesante es que se puede usar compresión para clasificar incluso sin entrenar un modelo.
Eso lleva a preguntarse si también pueden usarse otras métricas de teoría de la información más baratas y con pérdida.
To Compress or Not to Compress- Self-Supervised Learning and Information Theory: A Review
[https://arxiv.org/abs/2304.09355\)" class="ud link">https://arxiv.org/abs/2304.09355\](https://arxiv.org/abs/2304.09355\)*
Lo interesante no es si GZip alcanza el mejor rendimiento de vanguardia, sino el hecho de que clasifique medianamente bien.
Es parecido a que lo sorprendente no sea que un oso reproduzca perfectamente a Mozart, sino que pueda tocar el piano.
Aun así, es 8 veces mejor que la línea base y muestra que la compresión puede aprender representaciones.
Si se cambia
compute_ncdpor distancia euclidiana, la precisión en pruebas sube 15 puntos porcentuales y también se reduce mucho el cómputo.Basta con cambiarlo a algo como
distances = [(np.sqrt(np.sum(np.square(x1-x))), label) for x, _, label in compressed_lengths]De los libros que tratan la conexión profunda entre teoría de la información, compresión y algoritmos de aprendizaje, MacKay fue el mejor.
Para gente con formación formal quizá sea conocimiento común, pero como alguien que aprendió machine learning práctico de forma autodidacta, ver cómo este tema se conectaba incluso con campos como la física de partículas y la cosmología me produjo un intenso momento de “¡ajá!”.
Lo dejo con la esperanza de que al menos una persona llegue a la misma revelación.
Me impresionó bastante enterarme de que la compresión Lempel-Ziv original, una de las bases de gzip, no surgió simplemente como un intento de reducir tamaño, sino del estudio de la “complejidad de secuencias finitas”.
https://ieeexplore.ieee.org/document/1055501
Para ser justos, MNIST queda casi perfectamente separado con solo pasarlo por UMAP.
Hoy en día creo que hay que esforzarse bastante para tener mal desempeño en MNIST.
https://github.com/lmcinnes/umap_paper_notebooks/blob/master...
Creo que ya sería mejor retirar este dataset, y que datasets como QuickDraw tienen mucho más sentido.
No creo que sea un gran logro por sí mismo, pero igual es interesante ver que funciona.
Cuando llegue a casa agregaré al artículo que resolver MNIST es relativamente fácil.
Aun así, como la mayoría de los algoritmos simples y razonables llegan a 97% de precisión, sigue teniendo valor como herramienta educativa o como dataset Hello world.
Incluso si construyes las herramientas desde cero, tiene el tamaño adecuado para una tarea, y es un problema útil que cualquiera puede entender, como “reconocer dígitos del correo”.
Si entiendes la compresión, este enfoque también es una idea muy simple, así que podría haberse escrito el primer día en que se publicó MNIST y aun así habría obtenido 78% de precisión.
Eso me parece bastante sorprendente.
El repositorio tampoco define UMAP, pero si le creemos a ChatGPT, UMAP significa Uniform Manifold Approximation and Projection, y es una técnica de reducción de dimensionalidad y visualización usada en machine learning y análisis de datos.
Este campo lo manejo solo a nivel de hobby, pero supongo que los datos fuertemente comprimidos tienen alta entropía, como los datos cifrados.
Si se encuentran patrones en los datos comprimidos para identificar el dígito original, ¿no se deberían poder usar esos patrones para lograr una mejor compresión?
La idea es que “7 7” debería comprimirse mejor que “7 3”, y que una imagen raster de “7 7” también se comprimirá mejor que una de “7 3”.
La incompresibilidad es una característica de las operaciones criptográficas eficientes.
Ver la sección de compresión del artículo sobre complejidad de Kolmogorov: https://en.wikipedia.org/wiki/Kolmogorov_complexity#Compress...
Uno de los conceptos que me gustan de la compresión es el principio del palomar, que dice que para todo algoritmo de compresión necesariamente existen salidas más grandes que sus entradas.
También se puede intentar comprimir una carga útil cifrada bien diseñada, pero en promedio la salida será más grande que la entrada y la compresión se volverá inútil; por eso se la llama “incompresible”.
https://en.wikipedia.org/wiki/Pigeonhole_principle#Uses_and_...
Creo que hace unos años hubo un caso en el que se usaba el tamaño de las imágenes de MNIST como una “metacaracterística”, pero no logro encontrarlo enseguida.
Recuerdo que, sin siquiera mirar la imagen, solo con esa característica se obtenía una precisión de alrededor del 90%.
¿El tamaño comprimido con gzip? Si solo miras qué tan oscura es una imagen de MNIST, es decir, la proporción de píxeles oscuros, se obtiene alrededor de 20% de precisión, que es el doble de adivinar al azar, pero está muy lejos de 90%.
Sospecho que los autores de ese paper cometieron un error y por eso los resultados saltaron a los primeros puestos del benchmark.
Después de ese episodio pensé que la teoría no era consistente, pero aun así 78% de precisión solo con GZIP es impresionante.
Más allá de si este problema es una buena aplicación para trucos de compresión, quienes experimentan deberían dejar de usar
gzipy usarzlib.Si cambian la primera línea de
gzip.compressazlib.compress, obtendrán el mismo desempeño de clasificación con una velocidad 3 veces mayor.