Saltar al contenido principal

Capítulo 1: Comprendiendo LoRA

La intuición detrás de la adaptación de bajo rango​

LoRA (Low-Rank Adaptation, Adaptación de Bajo Rango) es una técnica elegante que parte de una observación simple pero poderosa: no es necesario actualizar todos los parámetros para adaptar un modelo a nuevas tareas.


La idea central​

Observación clave​

Al ajustar modelos preentrenados, las actualizaciones de los pesos suelen tener un "rango intrínseco" bajo—es decir, los cambios pueden capturarse con un conjunto mucho más pequeño de parámetros.

Analogía​

Piénselo como editar un documento:

  • Ajuste fino completo: Reescribir todo el documento
  • LoRA: Añadir notas adhesivas con correcciones

El documento original (modelo base) permanece intacto, y las notas adhesivas (adaptadores LoRA) capturan los cambios.


Cómo funciona LoRA​

Ajuste fino tradicional​

En una capa de red neuronal:

h = Wx

Donde W es una matriz de pesos de tamaño (d × d).

El ajuste fino completo actualiza W directamente:

W' = W + ΔW

Donde ΔW es el cambio aprendido para todos los parámetros (d × d).

Enfoque de LoRA​

LoRA representa ΔW como el producto de dos matrices más pequeñas:

ΔW = BA

Donde:

  • B tiene tamaño (d × r)
  • A tiene tamaño (r × d)
  • r es mucho menor que d (r ≪ d)

La pasada hacia adelante se convierte en:

h = Wx + BAx = (W + BA)x

Representación visual​


Ahorro de parámetros​

Ejemplo: una matriz de pesos 4096 × 4096​

# Original weight matrix
d = 4096
original_params = d * d # 16,777,216 parameters

# LoRA with rank 16
r = 16
lora_params = d * r + r * d # 131,072 parameters

# Savings
reduction = 1 - (lora_params / original_params)
print(f"Parameter reduction: {reduction:.2%}") # 99.22%

Para un modelo completo​

ModeloOriginalLoRA (r=16)Reducción
7B7,000,000,000~4,000,00099.94%
13B13,000,000,000~8,000,00099.94%
70B70,000,000,000~40,000,00099.94%

Por qué funciona el bajo rango​

Dimensionalidad intrínseca​

La investigación muestra que las actualizaciones durante el ajuste fino tienden a situarse en un subespacio de baja dimensión:

  1. Los modelos preentrenados ya tienen representaciones ricas
  2. La adaptación a la tarea requiere "dirigir" en lugar de "reconstruir"
  3. Muchas dimensiones del espacio de pesos son redundantes para tareas específicas

Evidencia empírica​

Del artículo original de LoRA:

  • r=4 suele ser suficiente para muchas tareas
  • r=8-16 recomendado para adaptaciones complejas
  • r=64+ rara vez es necesario, con rendimientos decrecientes

Inicialización​

Matriz A: Gaussiana aleatoria​

# A is initialized with small random values
A = torch.randn(r, d) * 0.01

Matriz B: Cero​

# B is initialized to zero
B = torch.zeros(d, r)

¿Por qué esta inicialización?​

Al inicio del entrenamiento: BA = 0 × A = 0
→ La salida no cambia respecto al modelo base
→ Inicio de entrenamiento estable
→ Adaptación gradual

Qué capas seleccionar​

Arquitectura Transformer​

Attention Block:
├── Query projection (q_proj) ← Objetivo común
├── Key projection (k_proj) ← A veces objetivo
├── Value projection (v_proj) ← Objetivo común
└── Output projection (o_proj) ← A veces objetivo

Feed-Forward Block:
├── Gate projection (gate_proj) ← A veces objetivo
├── Up projection (up_proj) ← A veces objetivo
└── Down projection (down_proj) ← A veces objetivo

Configuraciones comunes​

ConfiguraciónMódulos objetivoCaso de uso
Mínimaq_proj, v_projExperimentos rápidos
Estándarq_proj, k_proj, v_proj, o_projEquilibrado
CompletaToda la atención + FFMáxima capacidad

Fusión de LoRA​

Durante la inferencia (con adaptador)​

# Two paths: base + LoRA
output = W @ x + B @ A @ x

Ligera sobrecarga por el cálculo adicional.

Fusionado (sin adaptador)​

# Merge once
W_merged = W + B @ A

# Single path at inference
output = W_merged @ x

Sin sobrecarga—idéntico a un modelo ajustado completamente.

Ejemplo de fusión​

from peft import PeftModel

# Load model with adapter
model = PeftModel.from_pretrained(base_model, "path/to/adapter")

# Merge adapter into base model
model = model.merge_and_unload()

# Now model is a regular model without adapter overhead
model.save_pretrained("merged-model")

Variantes de LoRA​

LoRA estándar​

La formulación original descrita arriba.

LoRA+​

Aplica diferentes tasas de aprendizaje a las matrices A y B.

DoRA (Weight-Decomposed Low-Rank Adaptation)​

Separa la magnitud y la dirección de los pesos.

GaLore (Gradient Low-Rank Projection)​

Proyecta los gradientes en un espacio de bajo rango.


Puntos clave​

✅ LoRA representa las actualizaciones de pesos como productos de matrices de bajo rango

✅ Solo entrena ~0.01-0.1% de los parámetros originales

✅ B inicializada en cero garantiza un inicio de entrenamiento estable

✅ Es común seleccionar proyecciones de atención (q_proj, v_proj)

✅ Puede fusionarse para no tener sobrecarga en inferencia

✅ El bajo rango funciona porque el ajuste fino tiene baja dimensionalidad intrínseca


Próximos pasos​

Continúe con Capítulo 2: Matemáticas de LoRA para las bases matemáticas.


Comprobación rápida​

Antes de continuar, asegúrese de poder responder:

  1. ¿Cómo representa LoRA las actualizaciones de pesos?
  2. ¿Por qué B se inicializa en cero?
  3. ¿Qué significa "bajo rango" en el contexto de LoRA?