QLoRA: Entrenamiento de un modelo de LLM en una GPU de 16 GB
¿Te interesa entrenar un modelo de lenguaje de gran escala (LLM) en una GPU de 16 GB, pero no tienes mucha experiencia técnica? ¡No te preocupes! Con técnicas como QLoRA es posible reducir la memoria que usan estos modelos y hacerlos funcionar en equipos con menos recursos, todo sin perder precisión ni rendimiento.
En esta guía, te explico paso a paso y con ejemplos sencillos cómo lograrlo.
¿Qué es QLoRA y por qué es Útil?
Entrenar modelos grandes de lenguaje (LLMs) requiere de mucha memoria, algo que normalmente solo está disponible en equipos muy potentes.
Sin embargo, con QLoRA podemos reducir ese consumo de memoria, haciéndolo posible en GPUs de menor capacidad, como una de 16 GB.
QLoRA combina dos técnicas clave:
- Cuantización (Quantization): Reduce el tamaño del modelo convirtiendo los datos a un formato más pequeño (como de 4 bits en lugar de los 32 bits habituales).
- Adaptación de Baja Dimensión (LoRA): Ajusta solo una parte específica del modelo (en lugar de todo), lo cual reduce mucho el uso de memoria durante el entrenamiento.
Herramientas Necesarias
Antes de comenzar, asegúrate de tener lo siguiente:
- CUDA: Un sistema que permite que tu GPU haga cálculos complejos. Si tienes una GPU compatible, normalmente ya viene con CUDA.
- PyTorch o TensorFlow: Estos son marcos para manejar los modelos de IA. Usaremos PyTorch en los ejemplos.
- BitsAndBytes (bnb): Una herramienta que permite aplicar la técnica de cuantización.
- Transformers y Accelerate de Hugging Face: Bibliotecas para descargar y gestionar modelos, optimizándolos para funcionar en múltiples dispositivos.
Instalación de Herramientas
Abre tu terminal y ejecuta los siguientes comandos para instalar lo necesario:
pip install torch transformers accelerate bitsandbytes
También es recomendable instalar DeepSpeed, una biblioteca que ayuda a reducir el uso de memoria en tareas más complejas:
pip install deepspeed
Paso 1: Configurar QLoRA para reducir el tamaño del Modelo
El primer paso es descargar un modelo LLM preentrenado y prepararlo para que use menos memoria. Usaremos un modelo conocido (como GPT-2
de OpenAI) para simplificar.
Ejemplo: Cargar un Modelo en 4 Bits
from transformers import AutoModelForCausalLM, AutoTokenizer
import bitsandbytes as bnb
# Seleccionar el modelo y cargar el tokenizador
modelo_nombre = "gpt2" # Puedes probar con otros modelos de Transformers
tokenizer = AutoTokenizer.from_pretrained(modelo_nombre)
# Cargar el modelo en 4 bits para ahorrar memoria
modelo = AutoModelForCausalLM.from_pretrained(
modelo_nombre,
load_in_4bit=True, # Indicamos que queremos cargar el modelo en 4 bits
device_map="auto", # Distribuye el modelo de forma automática
quantization_config=bnb.nn.QuantizationConfig(quant_type="nf4") # Configuración de cuantización
)
Con load_in_4bit=True
, el modelo solo usa 4 bits para cada parámetro, reduciendo significativamente el uso de memoria. Esto significa que podemos trabajar con modelos más grandes en una GPU de 16 GB.
Paso 2: Aplicar Adaptación de Baja Dimensión (LoRA)
La técnica LoRA permite ajustar solo una parte del modelo, lo que significa que solo entrenamos los parámetros esenciales, ahorrando mucha memoria y tiempo.
Primero, instalemos peft, una biblioteca de Hugging Face que ayuda a aplicar LoRA fácilmente:
pip install peft
Ejemplo de Configuración LoRA en el Modelo
from peft import LoraConfig, get_peft_model
# Configuración básica de LoRA
config_lora = LoraConfig(
r=8, # Tamaño reducido para la parte que vamos a entrenar
lora_alpha=32, # Tasa de aprendizaje (controla qué tan rápido aprende el modelo)
target_modules=["q_proj", "v_proj"], # Las capas específicas a entrenar
lora_dropout=0.1, # Probabilidad de ignorar algunos valores (evita el sobreajuste)
bias="none" # No entrenamos el parámetro "bias" (para reducir más la memoria)
)
# Aplicamos LoRA al modelo ya cargado en 4 bits
modelo_lora = get_peft_model(modelo, config_lora)
modelo_lora.print_trainable_parameters() # Ver los parámetros que estamos entrenando
LoRA nos permite entrenar solo las capas más importantes del modelo, las que realmente influencian el resultado final.
Google desarrolla una IA que tomará el control del navegador webEsto significa que podemos entrenar sin que la GPU se quede sin memoria.
Paso 3: Preparación de los Datos
Necesitamos un conjunto de datos para entrenar el modelo. Imaginemos que vamos a usar el modelo para responder preguntas en un estilo de conversación similar al de Wikipedia.
Para esto, cargamos y preparamos datos de ejemplo.
Ejemplo de Preparación de Datos
from transformers import DataCollatorForLanguageModeling
from datasets import load_dataset
# Cargar un conjunto de datos de texto como Wikipedia
dataset = load_dataset("wikitext", "wikitext-2-raw-v1", split="train")
# Tokenización: Convertimos el texto a un formato que el modelo pueda entender
dataset = dataset.map(lambda e: tokenizer(e['text'], truncation=True, padding="max_length"), batched=True)
# Crear un "colacionador" que organiza los datos de entrada
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
Este ejemplo usa Wikitext, un conjunto de datos similar a la Wikipedia.
Lo tokenizamos para que el modelo pueda procesarlo más fácilmente.
Paso 4: Entrenamiento del Modelo
Para entrenar el modelo, usamos un optimizador (AdamW) y configuramos algunos parámetros clave como el tamaño del lote (batch size) y el número de épocas (epochs).
Estos determinan cuántas veces el modelo verá cada dato para aprender mejor.
Ejemplo de Configuración de Entrenamiento
from transformers import Trainer, TrainingArguments
# Configuración del entrenamiento
args_entrenamiento = TrainingArguments(
output_dir="./resultado_lora",
per_device_train_batch_size=1, # Tamaño de lote pequeño para no sobrecargar la memoria
gradient_accumulation_steps=8, # Acumular gradientes para reducir la memoria
learning_rate=2e-4,
num_train_epochs=3, # Entrenar por 3 épocas
logging_steps=10,
fp16=True, # Activar precisión en FP16 para reducir aún más la memoria
optim="paged_adamw_32bit" # Optimizador adaptado para modelos grandes
)
# Crear el objeto de entrenamiento con el modelo y los datos
trainer = Trainer(
model=modelo_lora,
args=args_entrenamiento,
train_dataset=dataset,
data_collator=data_collator
)
# Iniciar el entrenamiento
trainer.train()
En este paso, estamos entrenando el modelo en "modo FP16", una técnica que también reduce la cantidad de memoria utilizada al almacenar los datos en formato de 16 bits en lugar de 32 bits.
Explicación de los Parámetros
per_device_train_batch_size=1
: Indica que el modelo verá un dato a la vez. Aunque es más lento, ayuda a que el modelo no ocupe toda la memoria de la GPU.gradient_accumulation_steps=8
: Acumula gradientes para procesarlos cada 8 pasos, reduciendo el uso de memoria.num_train_epochs=3
: Define cuántas veces el modelo revisará los datos completos para aprender de ellos.
Paso 5: Evaluar el Modelo
Para verificar que el modelo realmente aprendió, es importante evaluarlo y ver cómo responde en comparación con los datos de prueba.
resultados = trainer.evaluate()
print(resultados)
En definitiva, entrenar un LLM en una GPU de 16 GB puede ser complicado, pero con técnicas como QLoRA, que usa la cuantización en 4 bits y adaptación de baja dimensión (LoRA), es totalmente posible.
Estas técnicas reducen el consumo de memoria sin sacrificar el rendimiento del modelo, permitiéndonos entrenar y usar grandes modelos en equipos más modestos.
Ahora tienes una guía sencilla para empezar a entrenar modelos grandes de lenguaje en una GPU pequeña.
Con un poco de práctica, puedes aplicar estos conocimientos en otros proyectos de IA y personalizar modelos para aplicaciones específicas.
Una IA revela misterioso detalle oculto en una obra maestra de Rafael¡Manos a la obra y descubre el potencial de los LLMs en tu proyecto!
Deja una respuesta
Entradas Relacionadas