TRL documentation

ORPO 训练器

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

ORPO 训练器

model badge model badge

概述

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 分钟。您可以通过查看奖励曲线来验证训练进度。奖励差值呈上升趋势表明模型正在改进,并随时间推移生成更好的响应。

orpo qwen2 reward margin

要查看训练后的模型的表现,您可以使用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:策略模型对拒绝响应的平均对数概率,乘以 beta
  • rewards/accuracies:所选奖励大于对应被拒绝奖励的频率均值
  • rewards/margins:所选奖励与对应被拒绝奖励之间的平均差值
  • log_odds_chosen:所选响应相对于被拒绝响应的平均对数几率比
  • log_odds_ratio:log(sigmoid(log_odds_chosen)) 的均值
  • nll_loss:损失函数中 SFT 部分在所选回复上的平均负对数似然损失

ORPOTrainer

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

参数

  • 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。

训练

< >

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

主要训练入口。

save_model

< >

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

将保存模型,以便您可以使用 from_pretrained() 重新加载它。

仅从主进程保存。

push_to_hub

< >

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

参数

  • commit_message (str,可选,默认为 "End of training") — 推送时提交的提交信息。
  • blocking (bool,可选,默认为 True) — 是否仅在 git push 完成后才返回。
  • token (str,可选,默认为 None) — 具有写入权限的 Token,用于覆盖 Trainer 的原始参数。
  • revision (str, 可选) — 要从中提交内容的 git 版本。默认为 “main” 分支的头部。
  • kwargs (dict[str, Any],可选) — 传递给 ~Trainer.create_model_card 的额外关键字参数。

将 self.model 和 self.processing_class 上传到 🤗 模型库中的仓库 self.args.hub_model_id。

ORPOConfig

类 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 = 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。
Update on GitHub