TRL documentation

ORPO Trainer

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

ORPO Trainer

model badge model badge

Aperçu

Odds Ratio Preference Optimization (ORPO) a été introduit dans ORPO: Monolithic Preference Optimization without Reference Model par Jiwoo Hong, Noah Lee et James Thorne.

L'abstract de l'article est le suivant :

Bien que les algorithmes récents d’alignement par préférences pour les modèles de langage aient démontré des résultats prometteurs, l’ajustement supervisé (SFT) reste impératif pour atteindre une convergence réussie. Dans cet article, nous étudions le rôle crucial du SFT dans le contexte de l’alignement par préférences, en soulignant qu’une pénalité mineure pour le style de génération défavorisé est suffisante pour un SFT aligné par préférences. Sur cette base, nous introduisons un algorithme monolithique simple et novateur d’optimisation du rapport de préférence par cotes, sans modèle de référence, ORPO, qui élimine la nécessité d’une phase supplémentaire d’alignement par préférences. Nous démontrons, tant empiriquement que théoriquement, que le rapport de cotes est un choix judicieux pour contraster les styles favorisés et défavorisés lors du SFT, sur des tailles variées allant de 125M à 7B. Plus précisément, l’ajustement de Phi-2 (2.7B), Llama-2 (7B) et Mistral (7B) avec ORPO sur UltraFeedback seul surpasse les performances des modèles de langage de pointe possédant plus de 7B et 13B paramètres : atteignant jusqu’à 12.20% sur AlpacaEval_{2.0} (Figure 1), 66.19% sur IFEval (niveau d’instruction lâche, Tableau 6) et 7.32 sur MT-Bench (Figure 12). Nous publions le code et les points de contrôle des modèles pour Mistral-ORPO-alpha (7B) et Mistral-ORPO-beta (7B).

Elle étudie le rôle crucial du SFT dans le contexte de l'alignement des préférences. En utilisant des données de préférence, la méthode postule qu'une pénalité mineure pour la génération défavorisée, associée à un fort signal d'adaptation vers la réponse choisie via un simple terme de rapport de log-vraisemblance ajouté à la perte NLL, est suffisant pour un SFT aligné sur les préférences.

Ainsi, ORPO est un algorithme d'optimisation des préférences sans modèle de référence, qui élimine la nécessité d'une phase supplémentaire d'alignement des préférences, ce qui permet d'économiser des ressources de calcul et de mémoire.

Le code officiel peut être trouvé dans xfactlab/orpo.

Cette méthode de post-entraînement a été proposée par Kashif Rasul, Lewis Tunstall et Alvaro Bartolome.

Démarrage rapide

Cet exemple montre comment entraîner un modèle à l'aide de la méthode ORPO. Nous utilisons le modèle Qwen 0.5B comme modèle de base. Nous utilisons les données de préférence issues du jeu de données UltraFeedback. Vous pouvez consulter les données du jeu de données ici :

Voici le script pour entraîner le modèle :

# train_orpo.py
from datasets import load_dataset
from trl.experimental.orpo import ORPOConfig, ORPOTrainer
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
train_dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train")

training_args = ORPOConfig(output_dir="Qwen2-0.5B-ORPO")
trainer = ORPOTrainer(model=model, args=training_args, processing_class=tokenizer, train_dataset=train_dataset)
trainer.train()

Exécutez le script à l'aide de la commande suivante :

torchrun --nproc_per_node 8 train_orpo.py

Réparti sur 8 GPU, l’entraînement prend environ 30 minutes. Vous pouvez vérifier la progression de l’entraînement en consultant le graphique de la récompense. Une tendance à la hausse de la marge de récompense indique que le modèle s’améliore et génère de meilleures réponses au fil du temps.

orpo qwen2 reward margin

Pour voir les performances du modèle entraîné, vous pouvez utiliser le Transformers Chat CLI.

$ transformers chat trl-lib/Qwen2-0.5B-ORPO
<quentin_gallouedec>:
What is the best programming language?

<trl-lib/Qwen2-0.5B-ORPO>:
It's challenging to determine the best programming language as no one language is perfect, as the complexity of a task and the type of project are significant factors. Some popular languages include Java, Python, JavaScript, and
C++. If you have specific needs or requirements for a specific project, it's important to choose the language that best suits those needs.

Here are some other factors to consider when choosing a programming language for a project:

 • Language proficiency: A good programming language is more likely to be easy to understand and use, and will allow developers to collaborate on projects more efficiently.
 • Ease of use: There are tools and libraries available to make programming more accessible, so developers should choose a language that can help them get started easier.
 • Code readability: A clear and concise codebase should be easy to read and understand, especially when working with large projects.
 • Tool and framework support: There are numerous libraries available for Python, Java, and JavaScript, along with tools like IDEs and static code analysis tools.
 • Accessibility: Some languages and tools have features that make them more accessible to developers with disabilities, such as support for screen readers.
 • Version control: As your projects grow and complexity increases, version control tools can be beneficial for tracking changes.

Type de jeu de données attendu

ORPO nécessite un jeu de données de préférence. Le experimental.orpo.ORPOTrainer prend en charge les formats de jeu de données conversationnel et standard. Lorsqu’un jeu de données conversationnel est fourni, l’entraîneur applique automatiquement le modèle de chat au jeu de données.

Bien que le experimental.orpo.ORPOTrainer prenne en charge les invites explicites et implicites, nous recommandons d’utiliser des invites explicites. Si un jeu de données avec des invites implicites est fourni, l’entraîneur extrait automatiquement l’invite des colonnes "chosen" et "rejected". Pour plus d’informations, reportez-vous à la section preference style.

Conseils d'utilisation

Pour les modèles Mixture of Experts : Activer la perte auxiliaire

Les MOEs sont les plus efficaces lorsque la charge est répartie de manière à peu près égale entre les experts.
Pour nous assurer d’entraîner les MOEs de manière similaire lors de l’ajustement par préférence, il est bénéfique d’ajouter la perte auxiliaire du répartiteur de charge à la perte finale.

Cette option est activée en définissant output_router_logits=True dans la configuration du modèle (par exemple MixtralConfig).
Pour ajuster la contribution de la perte auxiliaire à la perte totale, utilisez l'hyperparamètre router_aux_loss_coef=... (valeur par défaut : 0.001) dans la configuration du modèle.

Métriques journalisées

Lors de l'entraînement et de l'évaluation, nous enregistrons les métriques suivantes :

  • rewards/chosen : les probabilités logiques moyennes du modèle de politique pour les réponses choisies, mises à l'échelle par beta
  • rewards/rejected : les probabilités logiques moyennes du modèle de politique pour les réponses rejetées, mises à l'échelle par beta
  • rewards/accuracies : moyenne de la fréquence à laquelle les récompenses choisies sont > que les récompenses rejetées correspondantes
  • rewards/margins : la différence moyenne entre les récompenses choisies et les récompenses rejetées correspondantes
  • log_odds_chosen : le rapport de cotes logarithmique moyen des réponses choisies par rapport aux réponses rejetées
  • log_odds_ratio : la moyenne de log(sigmoid(log_odds_chosen))
  • nll_loss : la perte moyenne de log-vraisemblance négative issue de la partie SFT de la perte, calculée sur les réponses choisies

ORPOTrainer

classe trl.experimental.orpo.ORPOTrainer

< >

( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.Module, str, NoneType] = Noneargs: trl.experimental.orpo.orpo_config.ORPOConfig | None = Nonedata_collator: collections.abc.Callable[[list[typing.Any]], dict[str, typing.Any]] | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | None = Noneeval_dataset: datasets.arrow_dataset.Dataset | dict[str, datasets.arrow_dataset.Dataset] | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | transformers.image_processing_utils.BaseImageProcessor | transformers.feature_extraction_utils.FeatureExtractionMixin | transformers.processing_utils.ProcessorMixin | None = Nonemodel_init: collections.abc.Callable[[], transformers.modeling_utils.PreTrainedModel] | None = Nonecallbacks: list[transformers.trainer_callback.TrainerCallback] | None = Noneoptimizers: tuple[torch.optim.Optimizer, torch.optim.lr_scheduler.LambdaLR] = (None, None)preprocess_logits_for_metrics: collections.abc.Callable[[torch.Tensor, torch.Tensor], torch.Tensor] | None = Nonepeft_config: PeftConfig | None = Nonecompute_metrics: collections.abc.Callable[[transformers.trainer_utils.EvalLoopOutput], dict] | None = None )

Paramètres

  • model (PreTrainedModel) — Le modèle à entraîner, de préférence un AutoModelForSequenceClassification.
  • args (experimental.orpo.ORPOConfig) — Les arguments de configuration ORPO à utiliser pour l’entraînement.
  • data_collator (DataCollator) — Le collateur de données à utiliser pour l’entraînement. Si None est spécifié, le collateur de données par défaut (experimental.utils.DPODataCollatorWithPadding) sera utilisé, ce qui rembourra les séquences jusqu’à la longueur maximale des séquences du lot, étant donné un jeu de données de séquences appariées.
  • train_dataset (Dataset) — Le jeu de données à utiliser pour l’entraînement.
  • eval_dataset (Dataset) — Le jeu de données à utiliser pour l'évaluation.
  • processing_class (PreTrainedTokenizerBase, BaseImageProcessor, FeatureExtractionMixin ou ProcessorMixin, facultatif) — Classe de traitement utilisée pour traiter les données. Si fournie, elle sera utilisée pour traiter automatiquement les entrées du modèle et sera enregistrée avec le modèle afin de faciliter la reprise d'une formation interrompue ou la réutilisation du modèle affiné.
  • model_init (Callable[[], transformers.PreTrainedModel]) — L'initialiseur de modèle à utiliser pour l'entraînement. Si None est spécifié, l'initialiseur de modèle par défaut sera utilisé.
  • callbacks (list[transformers.TrainerCallback]) — Les callbacks à utiliser pour l'entraînement.
  • optimizers (tuple[torch.optim.Optimizer, torch.optim.lr_scheduler.LambdaLR]) — L’optimiseur et le planificateur à utiliser pour l’entraînement.
  • preprocess_logits_for_metrics (Callable[[torch.Tensor, torch.Tensor], torch.Tensor]) — La fonction à utiliser pour prétraiter les logits avant de calculer les métriques.
  • peft_config (PeftConfig, facultatif) — La configuration PEFT à utiliser pour l’entraînement. Si vous passez une configuration PEFT, le modèle sera encapsulé dans un modèle PEFT.
  • compute_metrics (Callable[[EvalPrediction], dict], facultatif) — La fonction à utiliser pour calculer les métriques. Elle doit prendre un EvalPrediction et renvoyer un dictionnaire de chaînes vers les valeurs des métriques.

Initialiser ORPOTrainer.

train

< >

( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput

Paramètres

  • resume_from_checkpoint (str ou bool, facultatif) — Si c'est une str, chemin local d'un point de contrôle enregistré par une instance précédente de Trainer. Si c'est un bool et vaut True, charge le dernier point de contrôle dans args.output_dir enregistré par une instance précédente de Trainer. S'il est présent, l'entraînement reprendra à partir des états du modèle/optimiseur/planificateur chargés ici.
  • trial (optuna.Trial ou dict[str, Any], facultatif) — L’exécution de l’essai ou le dictionnaire d’hyperparamètres pour la recherche d’hyperparamètres.
  • ignore_keys_for_eval (list[str], facultatif) — Une liste de clés dans la sortie de votre modèle (s’il s’agit d’un dictionnaire) qui doivent être ignorées lors de la collecte des prédictions pour l’évaluation pendant l’entraînement.

Retourne

~trainer_utils.TrainOutput

Objet contenant le nombre d'étapes globales, la perte d'entraînement et les métriques.

Point d'entrée principal de l'entraînement.

save_model

< >

( output_dir: str | None = None_internal_call: bool = False )

Enregistrera le modèle, ce qui vous permettra de le recharger à l'aide de from_pretrained().

N'enregistrera que depuis le processus principal.

push_to_hub

< >

( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = Noneprivate: bool | None = None**kwargs )

Paramètres

  • commit_message (str, facultatif, par défaut "End of training") — Message à committer lors de la poussée.
  • blocking (bool, facultatif, par défaut True) — Indique si la fonction doit ne renvoyer que lorsque le git push est terminé.
  • token (str, facultatif, par défaut None) — Jeton avec permission d’écriture pour écraser les arguments originaux du Trainer.
  • revision (str, facultatif) — La révision git à partir de laquelle effectuer le commit. Par défaut, il s'agit de la tête de la branche « main ».
  • private (bool, facultatif) — Indique s'il faut rendre le dépôt privé lors de sa création. La valeur par défaut est args.hub_private_repo. N'a aucun effet si le dépôt existe déjà.
  • kwargs (dict[str, Any], facultatif) — Arguments supplémentaires passés à ~Trainer.create_model_card.

Téléchargez self.model et self.processing_class sur le hub de modèles 🤗 dans le dépôt self.args.hub_model_id.

ORPOConfig

classe trl.experimental.orpo.ORPOConfig

< >

( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 1e-06lr_scheduler_type: transformers.trainer_utils.SchedulerType | str = 'linear'lr_scheduler_kwargs: dict | str | None = Nonewarmup_steps: float = 0optim: transformers.training_args.OptimizerNames | str = 'adamw_torch_fused'optim_args: str | None = Noneweight_decay: float = 0.0adam_beta1: float = 0.9adam_beta2: float = 0.999adam_epsilon: float = 1e-08optim_target_modules: None | str | list[str] = Nonegradient_accumulation_steps: int = 1average_tokens_across_devices: bool = Truemax_grad_norm: float = 1.0label_smoothing_factor: float = 0.0bf16: bool | None = Nonefp16: bool = Falsebf16_full_eval: bool = Falsefp16_full_eval: bool = Falsetf32: bool | None = Noneactivation_checkpointing: bool | None = Noneactivation_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonegradient_checkpointing: bool = Truegradient_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonetorch_compile: bool = Falsetorch_compile_backend: str | None = Nonetorch_compile_mode: str | None = Noneuse_liger_kernel: bool = Falseliger_kernel_config: dict[str, bool] | None = Noneuse_cache: bool = Falseneftune_noise_alpha: float | None = Nonetorch_empty_cache_steps: int | None = Noneauto_find_batch_size: bool = Falselogging_strategy: transformers.trainer_utils.IntervalStrategy | str = 'steps'logging_steps: float = 10logging_first_step: bool = Falselog_on_each_node: bool = Truelogging_nan_inf_filter: bool = Trueinclude_num_input_tokens_seen: str | bool = 'no'log_level: str = 'passive'log_level_replica: str = 'warning'disable_tqdm: bool | None = Nonereport_to: None | str | list[str] = 'none'run_name: str | None = Noneproject: str = 'huggingface'trackio_space_id: str | None = Nonetrackio_bucket_id: str | None = Nonetrackio_static_space_id: typing.Union[str, NoneType, typing.Literal[False]] = Noneeval_strategy: transformers.trainer_utils.IntervalStrategy | str = 'no'eval_steps: float | None = Noneeval_delay: float = 0per_device_eval_batch_size: int = 8prediction_loss_only: bool = Falseeval_on_start: bool = Falseeval_do_concat_batches: bool = Trueeval_use_gather_object: bool = Falseeval_accumulation_steps: int | None = Noneinclude_for_metrics: list[str] = <factory>batch_eval_metrics: bool = Falsesave_only_model: bool = Falsesave_strategy: transformers.trainer_utils.SaveStrategy | str = 'steps'save_steps: float = 500save_on_each_node: bool = Falsesave_total_limit: int | None = Noneenable_jit_checkpoint: bool = Falsepush_to_hub: bool = Falsehub_token: str | None = Nonehub_private_repo: bool | None = Nonehub_model_id: str | None = Nonehub_strategy: transformers.trainer_utils.HubStrategy | str = 'every_save'hub_always_push: bool = Falsehub_revision: str | None = Noneload_best_model_at_end: bool = Falsemetric_for_best_model: str | None = Nonegreater_is_better: bool | None = Noneignore_data_skip: bool = Falserestore_callback_states_from_checkpoint: bool = Falsefull_determinism: bool = Falseseed: int = 42data_seed: int | None = Noneuse_cpu: bool = Falseaccelerator_config: dict | str | None = Noneparallelism_config: accelerate.parallelism_config.ParallelismConfig | None = Nonedataloader_drop_last: bool = Falsedataloader_num_workers: int = 0dataloader_pin_memory: bool = Truedataloader_persistent_workers: bool = Falsedataloader_prefetch_factor: int | None = Nonedataloader_multiprocessing_context: str | None = Nonedataloader_in_order: bool = Trueremove_unused_columns: bool = Truelabel_names: list[str] | None = Nonetrain_sampling_strategy: str = 'random'length_column_name: str = 'length'ddp_find_unused_parameters: bool | None = Noneddp_bucket_cap_mb: int | None = Noneddp_broadcast_buffers: bool | None = Noneddp_static_graph: bool | None = Noneddp_backend: str | None = Noneddp_timeout: int = 1800fsdp: str | None = Nonefsdp_config: dict[str, typing.Any] | str | None = Nonedeepspeed: dict | str | None = Nonedebug: str | list[transformers.debug_utils.DebugOption] = ''skip_memory_metrics: bool = Truedo_train: bool = Falsedo_eval: bool = Falsedo_predict: bool = Falseresume_from_checkpoint: str | None = Nonelocal_rank: int = -1max_length: int | None = 1024max_completion_length: int | None = Nonebeta: float = 0.1disable_dropout: bool = Truepadding_value: int | None = Nonegenerate_during_eval: bool = Falseis_encoder_decoder: bool | None = Nonemodel_init_kwargs: dict[str, typing.Any] | str | None = Nonetrust_remote_code: bool = Falsedataset_num_proc: int | None = None )

Paramètres

  • max_length (int ou None, facultatif, par défaut 1024) — Longueur maximale des séquences (invite + complétion) dans le lot. Cet argument est requis si vous souhaitez utiliser le collateur de données par défaut.
  • max_completion_length (int, facultatif) — Longueur maximale de la complétion. Cet argument est requis si vous souhaitez utiliser le collateur de données par défaut et que votre modèle est un encodeur-décodeur.
  • beta (float, facultatif, par défaut 0.1) — Paramètre contrôlant le poids relatif de la perte de ratio dans la perte ORPO. Dans l'article, il est noté λ. Dans le code, il est noté alpha.
  • disable_dropout (bool, facultatif, valeur par défaut True) — Indique s'il faut désactiver le dropout dans le modèle.
  • padding_value (int, facultatif) — Valeur de bourrage à utiliser. Si None, la valeur de bourrage du tokeniseur est utilisée.
  • generate_during_eval (bool, facultatif, valeur par défaut False) — Si True, génère et journalise les complétions du modèle vers W&B ou Comet pendant l'évaluation.
  • is_encoder_decoder (bool, facultatif) — Lorsque vous utilisez l'argument model_init (appelable) pour instancier le modèle au lieu de l'argument model, vous devez spécifier si le modèle renvoyé par l'appelable est un modèle encoder-decoder.
  • model_init_kwargs (dict[str, Any], facultatif) — Arguments par mot-clé à passer à AutoModelForCausalLM.from_pretrained lors de l’instanciation du modèle à partir d’une chaîne de caractères. La valeur de revision est également utilisée lors du chargement de la classe de traitement.
  • trust_remote_code (bool, facultatif, valeur par défaut False) — Indique s'il faut autoriser le chargement de modèles qui incluent du code Python personnalisé depuis le Hub. Transmis à from_pretrained.
  • dataset_num_proc (int, facultatif) — Nombre de processus à utiliser pour le traitement du jeu de données.

Classe de configuration pour le experimental.orpo.ORPOTrainer.

Cette classe ne contient que les paramètres spécifiques à l’entraînement ORPO. Pour la liste complète des arguments d’entraînement, veuillez consulter la documentation de TrainingArguments. Notez que les valeurs par défaut de cette classe peuvent différer de celles de TrainingArguments.

À l’aide de HfArgumentParser, nous pouvons transformer cette classe en arguments argparse qui peuvent être spécifiés sur la ligne de commande.

Ces paramètres ont des valeurs par défaut différentes de TrainingArguments :

  • logging_steps : la valeur par défaut est 10 au lieu de 500.
  • gradient_checkpointing : la valeur par défaut est True au lieu de False.
  • bf16 : passe à True par défaut si fp16 n’est pas défini, au lieu de False.
  • learning_rate : la valeur par défaut est 1e-6 au lieu de 5e-5.
Update on GitHub