Implementación de Ajuste Fino Eficiente (PEFT) y LoRA en Modelos de Lenguaje

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}")

Etiquetas: peft LoRA HuggingFace transformers PyTorch

Publicado el 7-20 12:43