TRL documentation
ORPO 训练器
ORPO 训练器
概述
ORPO: Monolithic Preference Optimization without Reference Model 由 Jiwoo Hong、Noah Lee 和 James Thorne 提出了 Odds Ratio Preference Optimization (ORPO)。
该论文的摘要如下:
尽管近期针对语言模型的偏好对齐算法已展现出令人鼓舞的成果,但监督微调(SFT)对于实现成功收敛仍然至关重要。在本文中,我们研究了 SFT 在偏好对齐背景下的关键作用,并强调,对不受欢迎的生成风格施加轻微的惩罚即可实现偏好对齐的 SFT。在此基础上,我们提出了一种简单且具有创新性的、无需参考模型的单体赔率比偏好优化算法 ORPO,从而消除了额外偏好对齐阶段的必要性。我们通过实证和理论两方面证明,在从 125M 到 7B 的不同规模下,赔率比是 SFT 期间对比受欢迎与不受欢迎风格的合理选择。具体而言,仅使用 UltraFeedback 数据集,通过 ORPO 对 Phi-2 (2.7B)、Llama-2 (7B) 和 Mistral (7B) 进行微调,其性能便超越了拥有超过 7B 和 13B 参数的最先进语言模型:在 AlpacaEval_{2.0} 上最高达到 12.20%(图 1),在 IFEval(指令级宽松标准)上达到 66.19%(表 6),在 MT-Bench 上达到 7.32(图 12)。我们发布了 Mistral-ORPO-alpha (7B) 和 Mistral-ORPO-beta (7B) 的代码和模型检查点。
它研究了 SFT 在偏好对齐背景下的关键作用。该方法利用偏好数据,认为对不受欢迎的生成施加轻微惩罚,同时通过附加到 NLL 损失上的简单对数几率比项,对选定的响应施加强适应信号,就足以实现偏好对齐的 SFT。
因此,ORPO 是一种无需参考模型的偏好优化算法,它消除了额外偏好对齐阶段的必要性,从而节省了计算资源和内存。
官方代码可在 xfactlab/orpo 中找到。
此训练后方法由 Kashif Rasul、Lewis Tunstall 和 Alvaro Bartolome 贡献。
快速入门
本示例演示了如何使用 ORPO 方法训练模型。我们使用 Qwen 0.5B 模型 作为基础模型。我们使用来自 UltraFeedback 数据集 的偏好数据。您可以在这里查看该数据集的数据:
以下是用于训练模型的脚本:
# 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()使用以下命令执行该脚本:
torchrun --nproc_per_node 8 train_orpo.py
在 8 个 GPU 上分布式训练,大约需要 30 分钟。您可以通过查看奖励曲线来验证训练进度。奖励差值呈上升趋势表明模型正在改进,并随时间推移生成更好的响应。

要查看训练后的模型的表现,您可以使用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.
预期的数据集类型
ORPO 需要一个偏好数据集。experimental.orpo.ORPOTrainer 同时支持对话式和标准数据集格式。当提供对话式数据集时,训练器会自动将聊天模板应用于该数据集。
尽管 experimental.orpo.ORPOTrainer 同时支持显式和隐式提示,但我们建议使用显式提示。如果提供的是隐式提示数据集,训练器会自动从 "chosen" 和 "rejected" 列中提取提示。有关更多信息,请参阅 偏好风格 部分。
使用技巧
对于混合专家模型:启用辅助损失
当负载在专家之间大致均匀分布时,MOE 的效率最高。
为了确保在偏好调优期间以类似的方式训练 MOE,将负载均衡器的辅助损失添加到最终损失中是有益的。
通过在模型配置中设置 output_router_logits=True(例如 MixtralConfig)来启用此选项。
要调整辅助损失对总损失的贡献程度,请在模型配置中使用超参数 router_aux_loss_coef=...(默认值:0.001)。
记录的指标
在训练和评估过程中,我们记录以下指标:
rewards/chosen:策略模型对已选响应的平均对数概率,按 beta 缩放rewards/rejected:策略模型对拒绝响应的平均对数概率,乘以 betarewards/accuracies:所选奖励大于对应被拒绝奖励的频率均值rewards/margins:所选奖励与对应被拒绝奖励之间的平均差值log_odds_chosen:所选响应相对于被拒绝响应的平均对数几率比log_odds_ratio:log(sigmoid(log_odds_chosen))的均值nll_loss:损失函数中 SFT 部分在所选回复上的平均负对数似然损失
ORPOTrainer
类 trl.experimental.orpo.ORPOTrainer
< source >( 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 )
参数
- model (PreTrainedModel) — 要训练的模型,最好是 AutoModelForSequenceClassification。
- args (experimental.orpo.ORPOConfig) — 用于训练的 ORPO 配置参数。
- data_collator (
DataCollator) — 用于训练的数据整理器。如果指定为 None,则使用默认的数据整理器(experimental.utils.DPODataCollatorWithPadding),该整理器会将序列填充到批次中序列的最大长度,适用于成对序列的数据集。 - train_dataset (Dataset) — 用于训练的 dataset。
- eval_dataset (Dataset) — 用于评估的数据集。
- processing_class (PreTrainedTokenizerBase、BaseImageProcessor、FeatureExtractionMixin 或 ProcessorMixin,可选) — 用于处理数据的处理类。如果提供,将用于自动处理模型的输入,并随模型一起保存,以便更容易地重新运行中断的训练或复用微调后的模型。
- model_init (
Callable[[], transformers.PreTrainedModel]) — 用于训练的模型初始化器。如果指定为 None,则使用默认的模型初始化器。 - callbacks (
list[transformers.TrainerCallback]) — 训练时使用的回调。 - optimizers (
tuple[torch.optim.Optimizer, torch.optim.lr_scheduler.LambdaLR]) — 用于训练的优化器和调度器。 - preprocess_logits_for_metrics (
Callable[[torch.Tensor, torch.Tensor], torch.Tensor]) — 用于在计算指标之前对 logits 进行预处理的函数。 - peft_config (PeftConfig, 可选) — 用于训练的 PEFT 配置。如果传入 PEFT 配置,模型将被包装为一个 PEFT 模型。
- compute_metrics (
Callable[[EvalPrediction], dict], 可选) — 用于计算指标的函数。必须接受一个EvalPrediction并返回一个从字符串到指标值的字典。
初始化 ORPOTrainer。
训练
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
参数
- resume_from_checkpoint (
str或bool,可选) — 如果为str,则为之前Trainer实例保存的检查点的本地路径。如果为bool且等于True,则加载之前Trainer实例保存在 args.output_dir 中的最后一个检查点。如果存在,训练将从此处加载的模型/优化器/调度器状态中恢复。 - trial (
optuna.Trial或dict[str, Any],可选) — 用于超参数搜索的试验运行或超参数字典。 - ignore_keys_for_eval (
list[str],可选) — 在训练期间收集预测结果以进行评估时,应忽略的模型输出(如果输出是字典)中的键列表。
返回值
~trainer_utils.TrainOutput
包含全局步数、训练损失和指标的 Object。
主要训练入口。
将保存模型,以便您可以使用 from_pretrained() 重新加载它。
仅从主进程保存。
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
将 self.model 和 self.processing_class 上传到 🤗 模型库中的仓库 self.args.hub_model_id。
ORPOConfig
类 trl.experimental.orpo.ORPOConfig
< source >( 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 = 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 )
参数
- max_length (
int或None,可选,默认为1024) — 批次中序列(提示 + 补全)的最大长度。如果您想使用默认的数据整理器,则必须提供此参数。 - max_completion_length (
int, 可选) — 补全的最大长度。如果您希望使用默认的数据整理器(data collator)且您的模型是编码器-解码器(encoder-decoder)模型,则此参数为必填项。 - beta (
float,可选,默认为0.1) — 控制 ORPO 损失中相对比率损失权重的参数。在 论文中,它用 λ 表示。在 代码中,它用alpha表示。 - disable_dropout (
bool,可选,默认为True) — 是否禁用模型中的 dropout。 - padding_value (
int,可选) — 要使用的填充值。如果为None,则使用分词器的填充值。 - generate_during_eval (
bool,可选,默认为False) — 如果为True,则在评估期间生成模型补全并将其记录到 W&B 或 Comet。 - is_encoder_decoder (
bool, 可选) — 当使用model_init参数(可调用对象)来实例化模型,而不是使用model参数时, 您需要指定该可调用对象返回的模型是否为编码器-解码器模型。 - model_init_kwargs (
dict[str, Any], 可选) — 从字符串实例化模型时传递给AutoModelForCausalLM.from_pretrained的关键字参数。revision值在加载处理类时也会使用。 - trust_remote_code (
bool,可选,默认为False) — 是否允许加载从 Hub 提供自定义 Python 代码的模型。该参数会传递给 from_pretrained。 - dataset_num_proc (
int, 可选) — 用于处理数据集的进程数。
experimental.orpo.ORPOTrainer 的配置类。
此类仅包含 ORPO 训练特有的参数。完整的训练参数列表,请参阅 TrainingArguments 文档。请注意,此类中的默认值可能与 TrainingArguments 中的不同。
使用 HfArgumentParser,我们可以将该类转换为 argparse 参数,从而在命令行中指定。
这些参数的默认值与 TrainingArguments 不同:
logging_steps:默认值为10,而非500。gradient_checkpointing:默认值为True,而非False。bf16:如果未设置fp16,则默认值为True,而不是False。learning_rate:默认值为1e-6,而非5e-5。