>_ DevTrendses

Idioma

Inicio

Lenguajes

Secciones

Frontend Backend Móvil DevOps AI / ML GameDev Blockchain Embebidos Seguridad
Python

Cómo Entrenar Modelos Multimodales Pesados Sin un Zoológico de Scripts

Gemini_Generated_Image_s42giss42giss42g

Si alguna vez has intentado hacer fine-tuning de un modelo multimodal nuevo como Qwen2.5-VL o ejecutar un preentrenamiento de un generador de video basado en difusión, probablemente recuerdas esa sensación de desesperación. En un repositorio, el entrenamiento falla debido a conflictos de versiones entre PyTorch y FlashAttention. En otro, el autor escribió un pipeline de datos personalizado que carga 500 GB de imágenes directamente en la RAM. En un tercero, FSDP se congela completamente en el segundo paso de optimización.

Cada nueva arquitectura trae su propio script de entrenamiento, sus propios trucos para ahorrar memoria y sus propios workarounds para paralelismo. El equipo del laboratorio EvolvingLMMs-Lab decidió reunir toda esta experiencia dispersa en un solo lugar. Así nació el repositorio lmms-engine.

Es un motor modular para el entrenamiento escalable de modelos multimodales. Se encarga del trabajo pesado del entrenamiento distribuido, el empaquetamiento de secuencias y las optimizaciones de kernels de bajo nivel, dejándote solo con una configuración y datos.

Qué Hay Dentro y Para Quién Es

El framework fue desarrollado principalmente para investigadores e ingenieros de ML que trabajan con redes multimodales pesadas. Mientras que los LLMs de texto regulares pueden hacer fine-tuning cómodamente con herramientas como Axolotl o LLaMA-Factory, las imágenes, el audio y el video son otra historia.

Los inputs multimodales crean longitudes de contexto masivas. Un solo frame de alta resolución o un par de segundos de video se expanden fácilmente en decenas de miles de tokens visuales. En ese punto, el Data Parallel estándar alcanza rápidamente los límites de memoria GPU.

El motor resuelve esto con una combinación de técnicas modernas de paralelismo y optimizaciones a nivel de GPU. La lista de modelos soportados es impresionante:

  • Modelos Vision-Language: Qwen2.5-VL, Qwen3-VL, Qwen3-VL MoE, LLaVA-OneVision
  • MoE multimodal con soporte de audio y video: Qwen2.5-Omni, Qwen3-Omni MoE, Aero
  • Arquitecturas generativas y de difusión: WanVideo (1.3B y 14B parámetros), SiT (Scalable Interpolant Transformers), dLLM
  • Sistemas universales de comprensión y generación de imágenes: BAGEL

Cuatro Soluciones de Ingeniería Bajo el Capó

Los creadores del proyecto claramente se inspiraron en la idea del minimalismo: el código está escrito de forma compacta, sin magia abstracta innecesaria, en PyTorch puro con integraciones para bibliotecas de vanguardia.

1. FSDP2 y Ulysses Sequence Parallel

Para distribuir pesos, el motor depende de la nueva implementación de Fully Sharded Data Parallel v2 (FSDP2) basada en DTensor. A diferencia del FSDP antiguo, la segunda versión se compone mucho más limpiamente con otros tipos de paralelismo.

Cuando 10,000+ tokens visuales entran en el contexto, la memoria GPU se agota instantáneamente. Ahí es donde entra Ulysses Sequence Parallel (USP). Divide la secuencia de tokens entre varias GPUs dentro de un solo nodo. En el config, esto se configura con una sola línea:

trainer_args:
  sp_ulysses_degree: 2

2. Empaquetamiento de Secuencias Sin Padding Innecesario

Un dolor de cabeza clásico en el entrenamiento multimodal son los tamaños variables de imágenes y textos en un solo batch. Si haces padding de muestras cortas con tokens de relleno, la GPU pasa hasta la mitad del tiempo en cálculos inútiles de ceros.

Los autores implementaron first-fit bin packing en combinación con FlashAttention use_rmpad. Los datos se empaquetan en secuencias largas densas sin tiempo de inactividad. Según los benchmarks de los autores, en fine-tuning de Qwen2.5-VL, la métrica de eficiencia computacional (MFU) salta del 20-25% a un impresionante 35-40%.

dataset_config:
  packing: true
  packing_strategy: first_fit
  packing_length: 32000

trainer_args:
  use_rmpad: true
  use_liger_kernel: true

3. Optimizador Muon y Kernels Triton de Liger

En lugar del familiar AdamW, el proyecto ofrece Muon. Este optimizador aplica ortogonalización Newton-Schulz a través de kernels Triton sobre matrices de peso 2D. Converge más rápido que AdamW y requiere menos memoria.

Al mismo tiempo, el motor puede intercambiar capas de modelo estándar al vuelo con kernels fusionados de la biblioteca Liger Kernel de LinkedIn. CrossEntropy, RMSNorm, RoPE y SwiGLU se fusionan en operaciones individuales, reduciendo aproximadamente 30% del consumo pico de VRAM sin pérdida de precisión.

4. Carga en Streaming de Datasets de Terabytes

Cargar arreglos masivos de videos e imágenes en memoria antes de que comience una época es imposible. El pipeline de datos en lmms-engine está construido sobre IterableDataset. Los datos se leen en stream desde formatos Arrow, JSONL o Parquet, por lo que el entrenamiento comienza inmediatamente sin esperar a que se indexen archivos de tamaño terabyte.

Cómo Funcionan el Lanzamiento y la Extensión

La instalación del proyecto se hace correctamente a través del administrador de paquetes uv, aunque los autores también proporcionan una imagen Docker lista con CUDA, FlashAttention y dependencias preinstaladas.

git clone https://github.com/EvolvingLMMs-Lab/lmms-engine.git
cd lmms-engine
uv pip install -e ".[all]"
uv pip install flash-attn --no-build-isolation
uv pip install liger-kernel

El entrenamiento comienza a través de torchrun estándar:

torchrun --nproc_per_node=8 --nnodes=1 --node_rank=0 \
  --master_addr=127.0.0.1 --master_port=12355 \
  -m lmms_engine.launch.cli config_yaml=examples/qwen3_vl/example_config.yaml

Si necesitas agregar tu propio formato de datos específico o un procesador de features personalizado, no tendrás que reescribir los internos del trainer. El código usa un patrón factory con registro a través de decorators:

from lmms_engine.datasets import register_dataset, BaseDataset

@register_dataset("my_custom_dataset")
class MyCustomDataset(BaseDataset):
    def __init__(self, config):
        super().__init__(config)

    def __getitem__(self, idx):
        # Ваша логика чтения картинки или видео
        return item

Dónde Brilla Mejor el Proyecto

El motor fue desarrollado para escenarios pesados específicos:

  1. Fine-tuning de modelos vision-language (Qwen2.5-VL, Qwen3-VL) en documentos largos, escaneos de libros y capturas de pantalla de interfaces.
  2. Entrenamiento de arquitecturas sparse Mixture-of-Experts con distribución de expertos entre GPUs (Expert Parallelism).
  3. Experimentos con difusión para generación de video basada en modelos WanVideo o SiT.
  4. Preentrenamiento de modelos ligeros de atención recurrente y lineal (FLA / DGN).

¿Vale la Pena Probar

Si tu tarea es ajustar rápidamente LoRA en un Llama de texto, lmms-engine podría parecer overkill. Pero si has alcanzado un límite de memoria al entrenar redes multimodales, estás cansado de vincular manualmente FSDP2 con secuencias largas de video, o quieres exprimir el máximo de FLOPS de tus clusters existentes, este motor te ahorrará semanas de codificación.

La forma más fácil de comenzar es con los scripts listos en la carpeta examples/: contienen configuraciones probadas en batalla para la mayoría de las arquitecturas modernas.

Proyectos relacionados