⏱️ Lectura: 11 min

Un compresor de archivos y un modelo de lenguaje como GPT resuelven, en el fondo, el mismo problema matemático: predecir qué símbolo viene después. Esa es la tesis central de un post publicado en el blog técnico de ngrok, la empresa detrás del túnel HTTP homónimo, que reconstruye desde cero cómo funciona la compresión de datos para llegar a esa conclusión.

📑 En este artículo
  1. TL;DR
  2. Qué pasó
  3. Contexto e historia
  4. Detalles técnicos: la anatomía de un compresor
    1. Codificación aritmética: un archivo, un número
    2. Comparando técnicas de compresión
  5. Cómo probarlo vos mismo
  6. Impacto y análisis
  7. Qué sigue
  8. Preguntas frecuentes
    1. ¿Qué es la codificación aritmética?
    2. ¿Por qué la minificación no cuenta como compresión real?
    3. ¿Qué relación hay entre comprimir datos y entrenar un LLM?
    4. ¿Qué es el Hutter Prize?
    5. ¿Sirve comprimir dos veces el mismo archivo?
  9. Referencias

El hallazgo no es nuevo entre investigadores de teoría de la información, pero el post lo explica con ejemplos accesibles para cualquier desarrollador: desde el run-length encoding más básico hasta la codificación aritmética que usan compresores como Brotli y zstd.

TL;DR

  • Ngrok publicó un post que explica que la compresión de datos y los LLM resuelven el mismo problema: predecir el próximo símbolo.
  • El ejemplo de run-length encoding del post reduce una cadena de 224 bits a 96 bits, un 57% menos.
  • Minificar un script de 156 caracteres a 62 caracteres (60% menos) no cuenta como compresión real, según el post.
  • Todo compresor moderno combina tres etapas: transform, modelo de probabilidades y codificador de entropía.
  • La codificación aritmética representa un archivo completo como un único número dentro del intervalo [0, 1).
  • El Hutter Prize premia desde 2006 la mejor compresión de un snapshot de Wikipedia en texto plano.
  • gzip, Brotli y zstd ya vienen instalados o disponibles de forma nativa en Linux, macOS y Windows.

Qué pasó

El artículo, publicado en el blog de ngrok.com, arranca con un ejemplo de minificación de código JavaScript: una función que suma los números de una lista. El código fuente ocupa 156 caracteres; tras quitar comentarios, espacios y acortar los nombres de variables a una letra, el resultado ocupa 62 caracteres, un 60% menos. El post aclara algo importante ahí mismo: la minificación casi nunca se menciona en el campo de la compresión de datos real, porque solo elimina sintaxis que las máquinas no necesitan, sin aprovechar la redundancia del contenido.

Para mostrar la diferencia, el post usa la cadena AAAAAAAAABBBBCCDAAADDDDDDDDD: nueve \”A\”, cuatro \”B\”, dos \”C\”, una \”D\”, tres \”A\” más y nueve \”D\” más. Codificada carácter por carácter en ASCII de 8 bits, esa cadena de 28 caracteres pesa 224 bits. Si en cambio se codifica cada racha de símbolos como (carácter, repeticiones), el resultado es A9B4C2D1A3D9: 12 caracteres, 96 bits, un 57% más chica. Esa técnica se llama run-length encoding (RLE), y es apenas el punto de partida: compresores reales como gzip, Brotli o zstd combinan varias técnicas a la vez.

Ilustración de compresión de datos y bloques de bits
El ejemplo de ngrok reduce 224 bits a 96 con una sola técnica: run-length encoding. Foto de Mika Baumeister en Unsplash

Contexto e historia

La idea de que comprimir es predecir no nace en 2026: tiene raíces en la teoría de la información que Claude Shannon formalizó en 1948. Shannon demostró que el número mínimo de bits necesarios para representar un símbolo depende de su probabilidad: los símbolos frecuentes necesitan pocos bits, los raros necesitan más. Esa relación es la base matemática de toda la familia de compresores modernos, desde la codificación de Huffman (1952) hasta los transformers que hoy generan texto.

La conexión explícita entre compresión y modelos de lenguaje también tiene un antecedente conocido en la investigación en inteligencia artificial: el Hutter Prize, creado en 2006 por Marcus Hutter, premia a quien logre comprimir mejor un snapshot de 1 GB de Wikipedia en texto plano (enwik9). La premisa del concurso es la misma que plantea el post de ngrok: comprimir texto humano cerca del límite teórico exige, en la práctica, modelar el lenguaje casi tan bien como lo haría un sistema que entiende lo que lee.

Detalles técnicos: la anatomía de un compresor

Según el post, un compresor moderno tiene tres piezas: transforms (transformaciones de preprocesamiento, como el RLE del ejemplo anterior), modelos (que asignan una probabilidad a cada símbolo posible) y codificadores de entropía (que convierten esas probabilidades en el flujo de bits final). Las transformaciones no siempre reducen el tamaño de los datos: a veces reorganizan la información para crear más redundancia, que luego el modelo y el codificador de entropía aprovechan.

El modelo es la pieza que decide cuánto se puede comprimir. Para la cadena de ejemplo, cada símbolo tiene esta probabilidad, calculada dividiendo su frecuencia entre el total de caracteres:

SímboloOcurrenciasProbabilidad
A120.429
D100.357
B40.143
C20.071

El codificador de entropía toma esas probabilidades y produce el bitstream final: cuanto más segura está la predicción del modelo, menos bits necesita para representar cada símbolo. Ahí está la clave que conecta compresión con predicción: un buen modelo predictivo comprime mejor, sea que prediga el siguiente carácter de un archivo de texto o el siguiente token de una conversación.

Codificación aritmética: un archivo, un número

El método que mejor ilustra esta idea es la codificación aritmética. En vez de asignar un código de longitud fija o variable a cada símbolo (como hace Huffman), representa el archivo completo como un único número dentro del intervalo [0, 1). Cada símbolo nuevo achica ese intervalo proporcionalmente a su probabilidad: los símbolos frecuentes lo achican poco (necesitan pocos bits extra), los símbolos raros lo achican mucho (necesitan más bits).

Un ejemplo simplificado en Python, calculando el rango acumulado para la cadena ABABAAC con las probabilidades A=4/7, B=2/7, C=1/7:

simbolos = [\"A\", \"B\", \"C\"]
probabilidades = {\"A\": 4/7, \"B\": 2/7, \"C\": 1/7}

def construir_rangos(probabilidades):
    rangos = {}
    acumulado = 0.0
    for simbolo, prob in probabilidades.items():
        rangos[simbolo] = (acumulado, acumulado + prob)
        acumulado += prob
    return rangos

rangos = construir_rangos(probabilidades)
for simbolo, (inicio, fin) in rangos.items():
    print(f\"{simbolo}: [{inicio:.3f}, {fin:.3f})\")

Ese fragmento imprime el subintervalo inicial de cada símbolo: A ocupa [0.000, 0.571), B ocupa [0.571, 0.857) y C ocupa [0.857, 1.000). Codificar la cadena completa consiste en repetir el proceso símbolo a símbolo, reduciendo el intervalo cada vez, hasta quedarse con un único número que representa toda la secuencia.

flowchart LR
    A[\"Datos originales\"] --> B[\"Transform (RLE, BWT, etc.)\"]
    B --> C[\"Modelo de probabilidades\"]
    C --> D[\"Codificador de entropia\"]
    D --> E[\"Bitstream comprimido\"]

Comparando técnicas de compresión

TécnicaCuándo usarlaVentajaLimitación
Run-length encoding (RLE)Datos con rachas largas del mismo símbolo (bitmaps simples, faxes)Muy simple y rápidaNo comprime datos sin rachas repetidas
Codificación de HuffmanCuando cada símbolo tiene una frecuencia fija y conocidaÓptima para códigos de longitud entera de bitsNo puede usar fracciones de bit por símbolo
Codificación aritméticaCuando se necesita exprimir cada fracción de bit posibleSe acerca al límite teórico de ShannonMás costosa de calcular que Huffman
Compresores modernos (gzip, Brotli, zstd)Uso general: logs, HTTP, archivos, backupsCombinan transform, modelo y codificador de entropía automáticamenteCasi no ganan nada sobre datos ya comprimidos o cifrados

Servidor procesando bloques de datos comprimidos
Los compresores modernos combinan transform, modelo y codificador de entropía en una sola pasada. Foto de Steve A Johnson en Unsplash

Cómo probarlo vos mismo

No hace falta instalar nada raro: gzip ya vive en la mayoría de los sistemas operativos. Podés comparar en minutos la relación entre compresión y qué tan predecible es un archivo.

Linux:

# Genera un archivo de texto repetitivo (muy predecible)
yes \"el mismo texto una y otra vez\" | head -n 5000 > repetitivo.txt

# Genera un archivo aleatorio (nada predecible)
head -c 200000 /dev/urandom > aleatorio.bin

gzip -k -9 repetitivo.txt
gzip -k -9 aleatorio.bin

ls -la repetitivo.txt.gz aleatorio.bin.gz

macOS: los mismos comandos funcionan tal cual, porque macOS trae gzip y /dev/urandom por defecto en su terminal.

Windows: con PowerShell no hace falta instalar nada extra; podés usar la compresión nativa del sistema:

# PowerShell
\"el mismo texto una y otra vez \" * 5000 | Out-File repetitivo.txt
Compress-Archive -Path repetitivo.txt -DestinationPath repetitivo.zip
Get-Item repetitivo.zip | Select-Object Length

Al comparar el tamaño final vas a ver que el archivo repetitivo se comprime muchísimo más que el aleatorio, aunque los dos midan lo mismo sin comprimir. La razón es la que explica el post de ngrok: el archivo repetitivo es fácil de predecir símbolo a símbolo, y el aleatorio no lo es en absoluto.

Impacto y análisis

La relación entre compresión y predicción no es solo una curiosidad teórica: explica por qué los modelos de lenguaje entrenados con más datos y más parámetros suelen comprimir texto mejor que los compresores tradicionales. Un LLM que predice el siguiente token con alta confianza está haciendo, en esencia, el mismo trabajo que hace el modelo dentro de un compresor clásico, solo que con muchísimas más variables de contexto.

Esto tiene una consecuencia práctica para quien trabaja con datos todos los días: elegir el compresor correcto depende de qué tan predecible es el contenido. Logs con formato repetitivo, JSON con claves fijas o código fuente con patrones consistentes se prestan mucho mejor a la compresión de datos que archivos ya comprimidos (imágenes JPEG, video, o el resultado de un cifrado), que ya son casi indistinguibles del ruido aleatorio.

💭 Clave: intentar comprimir un archivo ya comprimido (un .zip dentro de otro .zip) casi nunca ahorra espacio, porque ya no queda redundancia que un modelo pueda predecir.

Qué sigue

El post de ngrok anticipa una segunda entrega centrada en cuantización, la técnica que aplica esta misma lógica de compresión para reducir el tamaño de los modelos de lenguaje grandes sin perder demasiada capacidad predictiva. Es el mismo principio aplicado en la dirección opuesta: en vez de comprimir un archivo con ayuda de un modelo, se comprime el propio modelo.

💡 Tip: si programás en Node.js o Python, podés inspeccionar cuánto reduce cada algoritmo un archivo propio con el módulo zlib (Node) o gzip/lzma (Python), sin instalar nada adicional.
⚠️ Ojo: ninguna de estas técnicas mejora la compresión de datos que ya vienen comprimidos o cifrados: ahí el modelo no tiene nada que predecir.

Probalo vos: corré gzip -9 sobre un log real de tu proyecto y compará el tamaño resultante contra un archivo binario cualquiera, para ver en la práctica la diferencia entre datos predecibles y datos que no lo son.

📖 Resumen en Telegram: Ver resumen

Preguntas frecuentes

¿Qué es la codificación aritmética?

Es un método de compresión que representa un archivo completo como un único número dentro del intervalo [0, 1), en vez de asignar un código separado a cada símbolo. Cuanto mejor prediga el modelo cada símbolo, menos bits necesita el número final.

¿Por qué la minificación no cuenta como compresión real?

Porque solo elimina sintaxis que las máquinas no necesitan (espacios, comentarios, nombres largos), sin aprovechar la redundancia estadística de los datos. La compresión de datos real usa un modelo de probabilidades para predecir símbolos.

¿Qué relación hay entre comprimir datos y entrenar un LLM?

Ambos resuelven el mismo problema matemático: predecir el siguiente símbolo (carácter, byte o token) a partir del contexto anterior. Un modelo que predice mejor comprime mejor, y viceversa.

¿Qué es el Hutter Prize?

Es un concurso creado en 2006 por Marcus Hutter que premia a quien logre comprimir mejor un snapshot de Wikipedia en texto plano, bajo la premisa de que comprimir texto humano cerca del límite exige modelar el lenguaje.

¿Sirve comprimir dos veces el mismo archivo?

Casi nunca. Un archivo ya comprimido se parece estadísticamente a ruido aleatorio: no le queda la redundancia que un modelo necesita para predecir símbolos, así que una segunda pasada de compresión no ahorra espacio.

Referencias

  • ngrok.com: el post original, \”Compression is prediction\”, que expone la relación entre compresores y modelos de lenguaje.
  • en.wikipedia.org: artículo sobre codificación aritmética, el método que representa un archivo completo como un único número.
  • en.wikipedia.org: descripción del Hutter Prize, el concurso que premia la compresión de texto de Wikipedia desde 2006.
  • en.wikipedia.org: biografía de Claude Shannon, creador de la teoría de la información que sustenta toda la compresión moderna.

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Markus Spiske en Unsplash


Andrés Morales

Desarrollador e investigador en inteligencia artificial. Escribe sobre modelos de lenguaje, frameworks, herramientas para devs y lanzamientos open source. Cubre papers de ML, ecosistema de startups tech y tendencias de programación.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.