TRL documentation

Intégration 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

Intégration de PEFT

TRL prend en charge les méthodes PEFT (Parameter-Efficient Fine-Tuning) pour un entraînement de modèles efficace en mémoire. PEFT permet d'ajuster finement de grands modèles de langage en n'entraînant qu'un petit nombre de paramètres supplémentaires tout en gardant le modèle de base figé, réduisant ainsi considérablement les coûts de calcul et les besoins en mémoire.

Ce guide explique comment utiliser PEFT avec différents formateurs TRL, y compris les techniques LoRA, QLoRA et prompt tuning.

Pour un exemple complet et fonctionnel, consultez le notebook SFT avec LoRA/QLoRA.

Installation

Pour utiliser PEFT avec TRL, installez les dépendances requises :

pip install trl[peft]

Pour la prise en charge de QLoRA (quantification 4 bits et 8 bits), installez également :

pip install bitsandbytes

Démarrage rapide

Tous les formateurs TRL prennent en charge PEFT via l'argument peft_config. La manière la plus simple d'activer PEFT consiste à utiliser l'interface en ligne de commande avec le drapeau --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

Sinon, vous pouvez passer une configuration PEFT directement dans votre code 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,
)

Trois façons de configurer PEFT

TRL propose trois méthodes différentes pour configurer PEFT, chacune adaptée à des cas d’usage distincts :

1. Utilisation des drapeaux CLI (le plus simple)

La façon la plus simple d’activer PEFT est d’utiliser le drapeau --use_peft avec l’interface en ligne de commande. Cette méthode est idéale pour des expériences rapides et des configurations standard :

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

Avantages : Configuration rapide, aucun code requis

Inconvénients : Limité à LoRA, moins d'options de personnalisation

2. Passer peft_config à Trainer (Recommandé)

Pour un contrôle plus fin, passez une configuration PEFT directement au formateur. C'est l'approche recommandée pour la plupart des cas d'utilisation :

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
)

Avantages : Contrôle total, prend en charge toutes les méthodes PEFT (LoRA, Prompt Tuning, etc.)

Inconvénients : Nécessite du code Python

3. Application de PEFT directement au modèle (avancé)

Pour une flexibilité maximale, vous pouvez appliquer PEFT à votre modèle avant de le passer à l'entraîneur :

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
)

Avantages : Contrôle maximal, utile pour les architectures de modèles personnalisées ou les configurations complexes

Inconvénients : Plus verbeux, nécessite une compréhension des mécanismes internes de PEFT

Considérations sur le taux d'apprentissage

Lors de l'utilisation de LoRA ou d'autres méthodes PEFT, il est généralement nécessaire d'utiliser un taux d'apprentissage plus élevé (environ 10 fois supérieur) par rapport à l'ajustement fin complet. Cela s'explique par le fait que les méthodes PEFT n'entraînent qu'une petite fraction des paramètres, ce qui exige un taux d'apprentissage plus important pour obtenir des mises à jour de paramètres similaires.

Taux d'apprentissage recommandés :

TrainerAjustement completAvec LoRA (10x)
SFT2.0e-52.0e-4
DPO5.0e-75.0e-6
GRPO1.0e-61.0e-5
Prompt TuningN/Ade 1.0e-2 à 3.0e-2

Pourquoi 10x ? Les adaptateurs LoRA comportent nettement moins de paramètres entraînables que le modèle complet. Un taux d'apprentissage plus élevé compense ce nombre réduit de paramètres, garantissant ainsi un entraînement efficace. Pour une explication détaillée, consultez ce billet de blog.

Pour de bonnes pratiques supplémentaires sur l'utilisation efficace de LoRA, consultez la documentation LoRA Without Regret.

PEFT avec différents formateurs

Les formateurs de TRL prennent en charge les configurations PEFT pour divers paradigmes d'entraînement. Vous trouverez ci-dessous des exemples détaillés pour chaque formateur principal.

sft
dpo
grpo

Ajustement fin supervisé (SFT)

Le SFTTrainer est utilisé pour l’ajustement fin supervisé sur des jeux de données d’instructions.

Avec 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

Exemple 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 : Adaptation de rang faible quantifiée

QLoRA combine la quantification sur 4 bits avec LoRA pour permettre l'ajustement fin de très grands modèles sur du matériel grand public. Cette technique peut réduire les besoins en mémoire jusqu'à 4 fois par rapport à LoRA standard.

Fonctionnement de QLoRA

  1. Quantification 4 bits : le modèle de base est chargé en précision 4 bits à l'aide de bitsandbytes
  2. Poids figés : Les poids du modèle quantifié restent figés pendant l'entraînement
  3. Adaptateurs LoRA : Seuls les paramètres de l'adaptateur LoRA sont entraînés en haute précision
  4. Efficacité mémoire : Permet l'ajustement fin de modèles comme Llama-70B sur un seul GPU grand public

Utiliser QLoRA avec TRL

Il suffit de combiner load_in_4bit=True avec la configuration PEFT :

Ligne de commande

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

Exemple en Python

Passez quantization_config directement au trainer en même temps que peft_config — le trainer charge et quantise le modèle pour vous. L'argument quantization_config est également disponible sur SFTTrainer, DPOTrainer, GRPOTrainer et 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()

Options de configuration de QLoRA

La BitsAndBytesConfig offre plusieurs options pour optimiser la mémoire et les performances :

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
)

Paramètres de configuration :

  • bnb_4bit_quant_type : Type de données de quantification ("nf4" ou "fp4"). NF4 est recommandé.
  • bnb_4bit_compute_dtype : le dtype utilisé pour le calcul. Utilisez bfloat16 pour une meilleure stabilité de l'entraînement.
  • bnb_4bit_use_double_quant : Active la quantification imbriquée pour économiser environ 0,4 bit supplémentaire par paramètre.

Quantification 8 bits

Pour une précision légèrement supérieure au détriment des économies de mémoire, vous pouvez utiliser la quantification 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",
)

Ou via la ligne de commande :

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

Points de contrôle pré-quantifiés

Certains points de contrôle sont publiés quantifiés, comme gpt-oss en MXFP4 ou Mistral Medium 3.5 en FP8. Ces poids ne peuvent pas être entraînés sur place, donc lorsque vous passez un tel point de contrôle par son nom, l’entraîneur le charge déquantifié, avec ou sans peft_config. Le modèle occupe alors la mémoire de ses poids déquantifiés, par exemple environ 42 Go en bfloat16 pour gpt-oss-20b, contre 13 Go pour son point de contrôle MXFP4. Pour le charger en bfloat16, comme pour tout autre modèle :

from trl import SFTConfig

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

Les points de contrôle FP8 nécessitent transformers 5.0.0 ou une version ultérieure.

Prompt Tuning

Le prompt tuning est une autre technique PEFT qui apprend des prompts doux (embeddings continus) préfixés à l'entrée, tout en gardant le modèle entier figé. Cette approche est particulièrement efficace pour les grands modèles.

Fonctionnement du Prompt Tuning

  1. Jetons virtuels : Ajoute des plongements continus apprenables (jetons virtuels) à l'entrée
  2. Modèle figé : l'intégralité du modèle de base reste figée
  3. Invites spécifiques à la tâche : chaque tâche apprend ses propres embeddings d'invite
  4. Efficacité extrême : Seuls les embeddings du prompt sont entraînés (généralement 8 à 20 jetons)

Utiliser le Prompt Tuning avec 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()

Configuration du 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",
)

Paramètres de configuration :

  • task_type : le type de tâche (TaskType.CAUSAL_LM pour la modélisation de langage)
  • prompt_tuning_init : Méthode d'initialisation (TEXT, RANDOM)
  • num_virtual_tokens : Nombre de jetons virtuels à préfixer (généralement 8 à 20)
  • prompt_tuning_init_text : Texte pour initialiser les jetons virtuels (lors de l'utilisation de l'initialisation TEXT)
  • tokenizer_name_or_path : Tokenizer pour l’initialisation à partir de texte

Prompt Tuning et LoRA

FonctionnalitéPrompt TuningLoRA
Paramètres entraînés~0.001%~0.1-1%
Utilisation de la mémoireMinimalFaible
Vitesse d'entraînementLe plus rapideRapide
Modification de modèleAucunCouches d'adaptation
Idéal pourGrands modèles, nombreuses tâchesAjustement fin général
Taux d'apprentissagePlus élevé (1e-2 à 3e-2)Standard (1e-4 à 3e-4)

Configurations avancées de PEFT

Paramètres de configuration 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
)

Paramètres clés :

  • r : rang de LoRA (valeurs typiques : 8, 16, 32, 64). Un rang plus élevé signifie plus de paramètres, mais potentiellement de meilleures performances.
  • lora_alpha : Facteur d'échelle (généralement 2 fois le rang). Contrôle l'amplitude des mises à jour LoRA.
  • lora_dropout : Probabilité de dropout pour les couches LoRA (typique : 0,05-0,1).
  • target_modules: Modules auxquels appliquer LoRA. Choix courants :
    • ["q_proj", "v_proj"] : requête et valeur d'attention (efficace en mémoire)
    • ["q_proj", "k_proj", "v_proj", "o_proj"] : Toutes les projections d'attention
    • ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"] : Toutes les couches linéaires
  • modules_to_save : Modules supplémentaires à entraîner entièrement (par exemple, ["embed_tokens", "lm_head"])

Sélection du module cible

Vous pouvez spécifier les modules auxquels appliquer LoRA. Schémas courants :

# 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"]

Utilisation des arguments de ligne de commande

Les scripts TRL acceptent les paramètres PEFT via la ligne de commande :

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

Drapeaux disponibles :

  • --use_peft : Activer PEFT
  • --lora_r : rang de LoRA (par défaut : 16)
  • --lora_alpha : alpha de LoRA (par défaut : 32)
  • --lora_dropout : dropout de LoRA (par défaut : 0.05)
  • --lora_target_modules : Modules cibles (séparés par des espaces)
  • --lora_modules_to_save : Modules supplémentaires à entraîner
  • --use_rslora : Activer Rank-Stabilized LoRA
  • --use_dora : Activer Weight-Decomposed LoRA (DoRA)
  • --load_in_4bit : Active la quantification en 4 bits (QLoRA)
  • --load_in_8bit : Activer la quantification en 8 bits

Enregistrer et charger des modèles PEFT

Enregistrement

Après l’entraînement, enregistrez vos adaptateurs PEFT :

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

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

Cela n'enregistre que les poids de l'adaptateur (quelques Mo) plutôt que le modèle complet (plusieurs Go).

Chargement

Charger un modèle PEFT pour l’inférence :

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()

Pousser vers le Hub

Vous pouvez facilement partager vos adaptateurs PEFT sur le 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")

Entraînement multi-GPU

PEFT fonctionne parfaitement avec la prise en charge multi-GPU de TRL via accelerate :

# Configure accelerate
accelerate config

# Launch training
accelerate launch 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

Pour QLoRA avec plusieurs GPU, le modèle de base est automatiquement fragmenté :

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

Parallélisme de pipeline naïf (NPP) pour les grands modèles

Pour les très grands modèles (>60B paramètres), TRL prend en charge le parallélisme de pipeline naïf (Naive Pipeline Parallelism, NPP), qui répartit le modèle et les adaptateurs sur plusieurs GPU. Les activations et les gradients sont communiqués entre les GPU, en prenant en charge le type de données int8 ainsi que d'autres types.

NPP

Comment utiliser NPP

Chargez votre modèle avec un device_map personnalisé pour le répartir sur plusieurs appareils :

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,
)
  • Gardez le module lm_head sur la première GPU (device 0) pour éviter les erreurs
  • Consultez ce tutoriel sur les mappages de périphériques pour une configuration appropriée
  • Exécuter les scripts d’entraînement directement (sans accelerate launch) : python script.py
  • Le parallélisme de données n'est pas encore pris en charge avec NPP

Ressources

Exemples et notebooks TRL

Documentation

Articles de recherche

Update on GitHub