Introducción al Ajuste Eficiente
El ajuste fino eficiente en parámetros (PEFT, por sus siglas en inglés) ofrece metodologías optimizadas para adaptar modelos preentrenados de gran escala a tareas específicas. El enfoque tradicional, que implica actualizar la totalidad de los pesos de la red, resulta computacionalmente prohibitivo y poco práctico dado el tamaño de las arquitecturas modernas. En su lugar, técnicas como la Adaptación de Rango Bajo (LoRA) o el ajuste de prompts permiten reducir drásticamente la cantidad de parámetros entrenables, manteniendo un rendimiento competitivo.
Flujo de Entrenamiento
Definición de la Configuración LoRA
Cada técnica de PEFT se gestiona mediante una clase de configuración que centraliza los hiperparámetros. Para LoRA, utilizamos LoraConfig, donde definimos aspectos como el tipo de tarea, el rango de la matriz y la tasa de regularización.
from peft import LoraConfig, TaskType
configuracion_lora = LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=16,
lora_alpha=64,
lora_dropout=0.05
)
Carga del Modelo Base y Creación del Modelo PEFT
El proceso requiere un modelo base preentrenado, el cual se obtiene mediante la biblioteca Transformers. Es fundamental seleccionar la clase adecuada según la arquitectura (por ejemplo, AutoModelForCausalLM para modelos generativos).
import os
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
os.environ["HF_TOKEN"] = "tu_token_de_acceso_aqui"
nombre_modelo = "mistralai/Mistral-7B-v0.1"
tokenizador = AutoTokenizer.from_pretrained(nombre_modelo)
modelo_base = AutoModelForCausalLM.from_pretrained(
nombre_modelo,
torch_dtype=torch.float16,
device_map="auto"
)
Una vez cargado el modelo base, se inyectan los adaptadores LoRA utilizando la función get_peft_model. Esto congela los pesos originales y añade las matrices de rango bajo.
from peft import get_peft_model
modelo_lora = get_peft_model(modelo_base, configuracion_lora)
modelo_lora.print_trainable_parameters()
# Salida esperada: trainable params: ~41M || all params: ~7.2B || trainable%: ~0.57%
Persistencia de los Adaptadores
Tras completar el ciclo de entrenamiento, los pesos de los adaptadores (no el modelo completo) se almacenan en disco. Esto ahorra una cantidad significativa de espacio.
ruta_salida = "./adaptadores_lora_mistral"
modelo_lora.save_pretrained(ruta_salida)
Fase de Inferencia
Para realizar inferencias, se carga el modelo base y se le acoplan los adaptadores guardados previamente. La clase AutoPeftModelForCausalLM simplifica esta operación.
from peft import AutoPeftModelForCausalLM
from transformers import AutoTokenizer
import torch
ruta_adaptadores = "ybelkada/opt-350m-lora" # Ejemplo de repositorio
modelo_inferencia = AutoPeftModelForCausalLM.from_pretrained(ruta_adaptadores)
tokenizador_inferencia = AutoTokenizer.from_pretrained("facebook/opt-350m")
modelo_inferencia.eval()
texto_entrada = "The future of artificial intelligence relies on"
entradas = tokenizador_inferencia(texto_entrada, return_tensors="pt")
with torch.no_grad():
salida = modelo_inferencia.generate(
input_ids=entradas["input_ids"].to("cuda"),
max_new_tokens=30,
temperature=0.7
)
resultado = tokenizador_inferencia.batch_decode(salida.detach().cpu().numpy(), skip_special_tokens=True)[0]
print(resultado)
Parámetros Fundamentales de LoraConfig
| Parámetro | Descripción |
|---|---|
r |
Dimensión del rango de la matriz LoRA (por defecto 8). Un valor mayor aumenta la capacidad pero también los parámetros entrenables. |
target_modules |
Módulos específicos donde se aplican los adaptadores (ej. q_proj, v_proj). Si se omite, se infiere según la arquitectura. Aceptar expresiones regulares o listas. |
lora_alpha |
Factor de escala para los pesos de LoRA. Generalmente se configura como el doble de r. |
lora_dropout |
Probabilidad de dropout aplicada a las capas de LoRA para prevenir sobreajuste. |
fan_in_fan_out |
Debe ser True si la capa objetivo almacena los pesos como (fan_in, fan_out), típico en capas Conv1D como las de GPT-2. |
bias |
Controla si los sesgos se entrenan: none, all o lora_only. |
use_rslora |
Activa Rank-Stabilized LoRA, ajustando el factor de escala a lora_alpha / sqrt(r) para mejorar la estabilidad. |
modules_to_save |
Lista de módulos adicionales (fuera de los adaptadores) que deben entrenarse y guardarse, como la capa de clasificación final. |
init_lora_weights |
Estrategia de inicialización. Opciones incluyen True (Kaiming), gaussian, loftq o pissa para una convergencia más rápida. |
layers_to_transform |
Índices específicos de las capas del transformador donde se inyectará LoRA. |
Ejemplos Prácticos Adicionales
Inspección de Gradientes
Es crucial verificar qué parámetros están siendo actualizados durante el entrenamiento. Podemos iterar sobre los tensores del modelo para comprobar su atributo requires_grad.
# Verificación en el modelo base (todo congelado tras aplicar PEFT)
for nombre_param, tensor in modelo_base.named_parameters():
print(f"Base - {nombre_param}: requiere_grad = {tensor.requires_grad}")
# Verificación en el modelo con LoRA (solo adaptadores activos)
for nombre_param, tensor in modelo_lora.named_parameters():
if tensor.requires_grad:
print(f"LoRA Activo - {nombre_param}")