TRL documentation

Integración de PEFT

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.17.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Integración de PEFT

TRL admite métodos de PEFT (ajuste fino de parámetros eficientes) para el entrenamiento de modelos eficiente en memoria. PEFT permite realizar el ajuste fino de modelos de lenguaje grandes entrenando solo un pequeño número de parámetros adicionales mientras se mantiene el modelo base congelado, lo que reduce significativamente los costos computacionales y los requisitos de memoria.

Esta guía explica cómo usar PEFT con diferentes entrenadores de TRL, incluidas las técnicas de LoRA, QLoRA y prompt tuning.

Para un ejemplo completo y funcional, consulte el cuaderno de SFT con LoRA/QLoRA.

Instalación

Para usar PEFT con TRL, instale las dependencias necesarias:

pip install trl[peft]

Para el soporte de QLoRA (cuantización de 4 bits y 8 bits), instale también:

pip install bitsandbytes

Inicio rápido

Todos los entrenadores de TRL admiten PEFT a través del argumento peft_config. La forma más sencilla de habilitar PEFT es utilizar la interfaz de línea de comandos con la bandera --use_peft:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

Alternativamente, puede pasar una configuración de PEFT directamente en su código de Python:

from peft import LoraConfig
from trl import SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training - note the higher learning rate for LoRA (10x base rate)
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate (2.0e-5) for LoRA
    ...
)

# Create trainer with PEFT
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset,
    peft_config=peft_config,
)

Tres formas de configurar PEFT

TRL ofrece tres métodos diferentes para configurar PEFT, cada uno adecuado para distintos casos de uso:

1. Uso de banderas de CLI (el más simple)

La forma más sencilla de habilitar PEFT es usar la bandera --use_peft con la interfaz de línea de comandos. Este método es ideal para experimentos rápidos y configuraciones estándar:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --output_dir Qwen2-0.5B-SFT-LoRA

Ventajas: Configuración rápida, no requiere código

Desventajas: Limitado a LoRA, menos opciones de personalización

2. Pasar peft_config a Trainer (Recomendado)

Para tener más control, pase una configuración de PEFT directamente al entrenador. Este es el enfoque recomendado para la mayoría de los casos de uso:

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # Pass config here
)

Ventajas: Control total, admite todos los métodos de PEFT (LoRA, Prompt Tuning, etc.)

Desventajas: Requiere código de Python

3. Aplicar PEFT directamente al modelo (avanzado)

Para obtener la máxima flexibilidad, puedes aplicar PEFT a tu modelo antes de pasarlo al trainer:

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
from trl import SFTConfig, SFTTrainer

# Load base model
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Apply PEFT configuration
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)
model = get_peft_model(model, peft_config)

# Pass PEFT-wrapped model to trainer
trainer = SFTTrainer(
    model=model,  # Already has PEFT applied
    args=training_args,
    train_dataset=dataset,
    # Note: no peft_config needed here
)

Ventajas: Control máximo, útil para arquitecturas de modelos personalizadas o configuraciones complejas

Desventajas: Más verboso, requiere comprender los detalles internos de PEFT

Consideraciones sobre la tasa de aprendizaje

Al utilizar LoRA u otros métodos PEFT, normalmente se necesita emplear una taxa de aprendizaje más alta (aproximadamente 10 veces) en comparación con el ajuste fino completo. Esto se debe a que los métodos PEFT entrenan solo una pequeña fracción de los parámetros, lo que requiere una tasa de aprendizaje mayor para lograr actualizaciones de parámetros similares.

Tasas de aprendizaje recomendadas:

TrainerAjuste fino completoCon LoRA (10x)
SFT2.0e-52.0e-4
DPO5.0e-75.0e-6
GRPO1.0e-61.0e-5
Ajuste de promptsN/Ade 1.0e-2 a 3.0e-2

¿Por qué 10x? Los adaptadores LoRA tienen significativamente menos parámetros entrenables que el modelo completo. Una tasa de aprendizaje más alta compensa esta reducción en el número de parámetros, garantizando un entrenamiento efectivo. Para una explicación detallada, consulte esta publicación de blog.

Para obtener más mejores prácticas sobre el uso efectivo de LoRA, consulte la documentación de LoRA Without Regret.

PEFT con diferentes entrenadores

Los entrenadores de TRL admiten configuraciones de PEFT para diversos paradigmas de entrenamiento. A continuación se muestran ejemplos detallados para cada entrenador principal.

sft
dpo
grpo

Ajuste fino supervisado (SFT)

El SFTTrainer se utiliza para el ajuste fino supervisado en conjuntos de datos de instrucciones.

Con LoRA

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --learning_rate 2.0e-4 \
    --num_train_epochs 1 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

Ejemplo en Python

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj"],  # optional: specify target modules
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for LoRA
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model="Qwen/Qwen2-0.5B",  # can pass model name or loaded model
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)
trainer.train()

QLoRA: Adaptación de bajo rango cuantizada

QLoRA combina la cuantización de 4 bits con LoRA para permitir el ajuste fino de modelos muy grandes en hardware de consumo. Esta técnica puede reducir los requisitos de memoria hasta 4 veces en comparación con LoRA estándar.

Cómo funciona QLoRA

  1. Cuantización de 4 bits: El modelo base se carga en precisión de 4 bits usando bitsandbytes
  2. Pesos congelados: Los pesos del modelo cuantizado permanecen congelados durante el entrenamiento
  3. Adaptadores LoRA: Solo los parámetros del adaptador LoRA se entrenan con mayor precisión
  4. Eficiencia de memoria: Permite el ajuste fino de modelos como Llama-70B en una sola GPU de consumo

Usar QLoRA con TRL

Simplemente combine load_in_4bit=True con la configuración de PEFT:

Línea de comandos

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --dataset_name trl-lib/Capybara \
    --load_in_4bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --output_dir Llama-2-7b-QLoRA

Ejemplo en Python

Pasa quantization_config directamente al trainer junto con peft_config: el trainer carga y cuantiza el modelo por ti. El mismo argumento quantization_config está disponible en SFTTrainer, DPOTrainer, GRPOTrainer y RLOOTrainer.

import torch

from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer

# Configure 4-bit quantization
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for QLoRA
    ...
)

# Create trainer with quantization and PEFT config
trainer = SFTTrainer(
    model="meta-llama/Llama-2-7b-hf",
    args=training_args,
    train_dataset=dataset,
    quantization_config=bnb_config,
    peft_config=peft_config,
)

trainer.train()

Opciones de configuración de QLoRA

La BitsAndBytesConfig ofrece varias opciones para optimizar la memoria y el rendimiento:

import torch

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",  # or "fp4"
    bnb_4bit_compute_dtype=torch.bfloat16,  # Compute dtype for 4-bit base models
    bnb_4bit_use_double_quant=True,  # Nested quantization for additional memory savings
)

Parámetros de configuración:

  • bnb_4bit_quant_type: Tipo de datos de cuantización ("nf4" o "fp4"). Se recomienda NF4.
  • bnb_4bit_compute_dtype: El dtype utilizado para el cálculo. Utilice bfloat16 para una mayor estabilidad en el entrenamiento.
  • bnb_4bit_use_double_quant: Habilita la cuantización anidada para ahorrar aproximadamente 0,4 bits adicionales por parámetro.

Cuantización de 8 bits

Para una precisión ligeramente mayor con un ahorro de memoria reducido, puedes usar cuantización de 8 bits:

from transformers import BitsAndBytesConfig, AutoModelForCausalLM

bnb_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

O mediante la línea de comandos:

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --load_in_8bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

Puntos de control pre-cuantizados

Algunos puntos de control se publican cuantizados, como gpt-oss en MXFP4 o Mistral Medium 3.5 en FP8. Estos pesos no se pueden entrenar in situ, por lo que, al pasar un punto de control de este tipo por nombre, el entrenador lo carga descuantizado, con o sin peft_config. El modelo ocupa entonces la memoria de sus pesos descuantizados, por ejemplo, unos 42 GB en bfloat16 para gpt-oss-20b, frente a 13 GB de su punto de control en MXFP4. Para cargarlo en bfloat16, como cualquier otro modelo:

from trl import SFTConfig

training_args = SFTConfig(model_init_kwargs={"dtype": "bfloat16"})

Los puntos de control FP8 requieren transformers 5.0.0 o posterior.

Prompt Tuning

El ajuste de prompts (prompt tuning) es otra técnica de PEFT que aprende prompts suaves (incrustaciones continuas) que se antepone a la entrada, manteniendo el modelo completo congelado. Esto resulta especialmente eficaz para modelos grandes.

Cómo funciona el ajuste de prompts

  1. Virtual Tokens: Añade incrustaciones continuas aprendibles (tokens virtuales) a la entrada
  2. Modelo congelado: Todo el modelo base permanece congelado
  3. Indicadores específicos de la tarea: Cada tarea aprende sus propios incrustados de indicador
  4. Eficiencia extrema: solo se entrenan los embeddings del prompt (típicamente 8-20 tokens)

Usar Prompt Tuning con TRL

from peft import PromptTuningConfig, PromptTuningInit, TaskType
from trl import SFTConfig, SFTTrainer

# Configure Prompt Tuning
peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,
    prompt_tuning_init=PromptTuningInit.TEXT,
    num_virtual_tokens=8,
    prompt_tuning_init_text="Classify if the tweet is a complaint or not:",
    tokenizer_name_or_path="Qwen/Qwen2-0.5B",
)

# Configure training with higher learning rate for Prompt Tuning
training_args = SFTConfig(
    learning_rate=2.0e-2,  # Prompt Tuning typically uses 1e-2 to 3e-2
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)

trainer.train()

Configuración de Prompt Tuning

from peft import PromptTuningConfig, PromptTuningInit, TaskType

peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,  # Task type
    prompt_tuning_init=PromptTuningInit.TEXT,  # Initialize from text
    num_virtual_tokens=8,  # Number of virtual tokens
    prompt_tuning_init_text="Your initialization text here",
    tokenizer_name_or_path="model_name",
)

Parámetros de configuración:

  • task_type: El tipo de tarea (TaskType.CAUSAL_LM para modelado de lenguaje)
  • prompt_tuning_init: Método de inicialización (TEXT, RANDOM)
  • num_virtual_tokens: Número de tokens virtuales que se añadirán al principio (normalmente 8-20)
  • prompt_tuning_init_text: Texto para inicializar los tokens virtuales (cuando se usa la inicialización TEXT)
  • tokenizer_name_or_path: Tokenizador para inicializar desde texto

Prompt Tuning frente a LoRA

CaracterísticaPrompt TuningLoRA
Parámetros entrenados~0.001%~0.1-1%
Uso de memoriaMínimoBajo
Velocidad de entrenamientoMás rápidoRápido
Modificación de modelosNingunoCapas de adaptador
Mejor paraModelos grandes, muchas tareasAjuste fino general
Tasa de aprendizajeMás alto (1e-2 a 3e-2)Estándar (1e-4 a 3e-4)

Configuraciones avanzadas de PEFT

Parámetros de configuración de LoRA

from peft import LoraConfig

peft_config = LoraConfig(
    r=16,  # LoRA rank
    lora_alpha=32,  # LoRA scaling factor
    lora_dropout=0.05,  # Dropout probability
    bias="none",  # Bias training strategy
    task_type="CAUSAL_LM",  # Task type
    target_modules=["q_proj", "v_proj"],  # Modules to apply LoRA
    modules_to_save=None,  # Additional modules to train
)

Parámetros clave:

  • r: rango de LoRA (valores típicos: 8, 16, 32, 64). Un rango más alto implica más parámetros, pero puede ofrecer un mejor rendimiento.
  • lora_alpha: Factor de escala (típicamente 2 veces el rango). Controla la magnitud de las actualizaciones de LoRA.
  • lora_dropout: Probabilidad de dropout para las capas de LoRA (típico: 0.05-0.1).
  • target_modules: Módulos a los que se aplicará LoRA. Opciones habituales:
    • ["q_proj", "v_proj"]: Consulta y valor de atención (eficiente en memoria)
    • ["q_proj", "k_proj", "v_proj", "o_proj"]: Todas las proyecciones de atención
    • ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]: Todas las capas lineales
  • modules_to_save: Módulos adicionales para entrenar por completo (p. ej., ["embed_tokens", "lm_head"])

Selección del módulo objetivo

Puede especificar a qué módulos se aplica LoRA. Patrones comunes:

# Minimal (most memory efficient)
target_modules=["q_proj", "v_proj"]

# Attention only
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]

# All linear layers (best performance, more memory)
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]

Uso de argumentos de línea de comandos

Los scripts de TRL aceptan parámetros de PEFT a través de la línea de comandos:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --lora_target_modules q_proj v_proj \
    --output_dir output

Banderas disponibles:

  • --use_peft: Habilitar PEFT
  • --lora_r: rango de LoRA (predeterminado: 16)
  • --lora_alpha: alpha de LoRA (predeterminado: 32)
  • --lora_dropout: dropout de LoRA (predeterminado: 0.05)
  • --lora_target_modules: Módulos objetivo (separados por espacios)
  • --lora_modules_to_save: Módulos adicionales para entrenar
  • --use_rslora: Habilitar LoRA con rango estabilizado
  • --use_dora: Habilita Weight-Decomposed LoRA (DoRA)
  • --load_in_4bit: Habilita la cuantización de 4 bits (QLoRA)
  • --load_in_8bit: Habilita la cuantización de 8 bits

Guardar y cargar modelos PEFT

Guardado

Después del entrenamiento, guarda tus adaptadores PEFT:

# Save the adapters
trainer.save_model("path/to/adapters")

# Or manually
model.save_pretrained("path/to/adapters")

Esto guarda solo los pesos del adaptador (unos pocos MB) en lugar del modelo completo (varios GB).

Cargando

Cargue un modelo PEFT para inferencia:

from transformers import AutoModelForCausalLM
from peft import PeftModel

# Load base model
base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Load PEFT adapters
model = PeftModel.from_pretrained(base_model, "path/to/adapters")

# Optionally merge adapters into base model for faster inference
model = model.merge_and_unload()

Subir al Hub

Puedes compartir fácilmente tus adaptadores PEFT en el Hugging Face Hub:

# Push adapters to Hub
model.push_to_hub("username/model-name-lora")

# Load from Hub
from peft import PeftModel
model = PeftModel.from_pretrained(base_model, "username/model-name-lora")

Entrenamiento con múltiples GPU

PEFT funciona a la perfección con la compatibilidad de TRL para múltiples GPU:

torchrun --nproc_per_node 8 trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

Para QLoRA con varias GPU, el modelo base se fragmenta automáticamente:

torchrun --nproc_per_node 8 trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-70b-hf \
    --load_in_4bit \
    --use_peft \
    --lora_r 32

Paralelismo de pipeline ingenuo (NPP) para modelos grandes

Para modelos muy grandes (>60B parámetros), TRL admite Naive Pipeline Parallelism (NPP), que distribuye el modelo y los adaptadores entre varias GPU. Las activaciones y los gradientes se comunican entre las GPU, admitiendo tanto int8 como otros tipos de datos.

NPP

Cómo usar NPP

Carga tu modelo con un device_map personalizado para dividirlo entre varios dispositivos:

from transformers import AutoModelForCausalLM
from peft import LoraConfig

# Create custom device map (see accelerate documentation)
device_map = {
    "model.embed_tokens": 0,
    "model.layers.0": 0,
    # ... distribute layers across GPUs
    "lm_head": 0,  # Must be on GPU 0
}

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-70b-hf",
    device_map=device_map,
    peft_config=lora_config,
)
  • Mantenga el módulo lm_head en la primera GPU (dispositivo 0) para evitar errores
  • Vea este tutorial sobre mapas de dispositivos para una configuración adecuada
  • Ejecuta los scripts de entrenamiento directamente (no con torchrun): python script.py
  • El paralelismo de datos aún no es compatible con NPP

Recursos

Ejemplos y cuadernos de TRL

Documentación

Artículos de investigación

Update on GitHub