TRL 文档
DPO Trainer
并获得增强的文档体验
开始使用
DPO Trainer
概述
TRL 支持 DPO Trainer,用于从偏好数据中训练语言模型,如 Direct Preference Optimization: Your Language Model is Secretly a Reward Model 论文中所述,作者包括 Rafael Rafailov、Archit Sharma、Eric Mitchell、Stefano Ermon、Christopher D. Manning 和 Chelsea Finn。
该论文的摘要如下:
虽然大规模无监督语言模型 (LM) 学习了广泛的世界知识和一些推理技能,但由于其训练的完全无监督性质,实现对其行为的精确控制非常困难。现有的获得这种可操纵性的方法收集人类对模型生成相对质量的标签,并微调无监督 LM 以与这些偏好对齐,通常使用来自人类反馈的强化学习 (RLHF)。然而,RLHF 是一个复杂且通常不稳定的过程,首先拟合反映人类偏好的奖励模型,然后使用强化学习微调大型无监督 LM,以最大化此估计的奖励,而不会偏离原始模型太远。在本文中,我们介绍了 RLHF 中奖励模型的新参数化,该参数化能够在闭合形式中提取相应的最优策略,使我们能够仅通过简单的分类损失来解决标准的 RLHF 问题。由此产生的算法,我们称之为直接偏好优化 (DPO),是稳定、高性能且计算轻量级的,消除了在微调期间从 LM 中采样或执行重要的超参数调整的需要。我们的实验表明,DPO 可以微调 LM 以与人类偏好对齐,效果与现有方法相当或更好。值得注意的是,使用 DPO 进行微调在控制生成情感的能力方面超过了基于 PPO 的 RLHF,并在摘要和单轮对话中匹配或提高了响应质量,同时实现和训练起来也大大简化。
第一步是训练 SFT 模型,以确保我们训练的数据对于 DPO 算法是分布内的。
然后,通过 DPO 微调语言模型包括两个步骤,并且比 PPO 更容易
- 数据收集:收集一个 偏好数据集,其中包含给定提示的正负选择生成对。
- 优化:直接最大化 DPO 损失的对数似然。
下图说明了此过程(来自 DPO 论文的图 1)
在 原始论文中阅读有关 DPO 算法的更多信息。
快速开始
此示例演示了如何使用 DPO 方法训练模型。我们使用 Qwen 0.5B 模型 作为基础模型。我们使用来自 UltraFeedback 数据集的偏好数据。您可以在此处的数据集中查看数据
以下是训练模型的脚本
# train_dpo.py
from datasets import load_dataset
from trl import DPOConfig, DPOTrainer
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 = DPOConfig(output_dir="Qwen2-0.5B-DPO", logging_steps=10)
trainer = DPOTrainer(model=model, args=training_args, processing_class=tokenizer, train_dataset=train_dataset)
trainer.train()
使用以下命令执行脚本
accelerate launch train_dpo.py
分布式在 8 个 GPU 上,训练大约需要 3 分钟。您可以通过检查奖励图来验证训练进度。奖励边际的增加趋势表明模型正在改进,并随着时间的推移生成更好的响应。
要查看 训练后的模型 的性能,您可以使用 Transformers Chat CLI。
$ transformers-cli chat --model_name_or_path trl-lib/Qwen2-0.5B-DPO
<quentin_gallouedec>:
What is the best programming language?
<trl-lib/Qwen2-0.5B-DPO>:
The best programming language for specific applications can vary depending on the use case and knowledge level of the programmer. Here are some general factors that can be used as input to choose the best programming language:
1 Ease of use: Some programming languages are more user-friendly than others, such as Python, Java, or Ruby. Python is popular due to its simplicity and great scalability.
2 Versatility: The ability to work with a wide range of data structures and frameworks can define the language as versatile.
3 Ease of learning: Different programming languages have different learning curves, so users must be willing to take some time to master one.
4 Community support: The broader community of developers and enthusiasts in the selected programming language can provide great support and resources.
5 Reusability: Languages that emphasize code reuse and can be easily modifiable can be more suitable for software development.
The best programming language based on these factors is subjective and depends on what the programmer intends to accomplish.
预期数据集类型
DPO 需要一个 偏好数据集。DPOTrainer 同时支持 对话式 和 标准 数据集格式。当提供对话式数据集时,训练器将自动将聊天模板应用于数据集。
虽然 DPOTrainer 同时支持显式和隐式提示,但我们建议使用显式提示。如果提供隐式提示数据集,训练器将自动从 "chosen"
和 "rejected"
列中提取提示。有关更多信息,请参阅 偏好样式 部分。
视觉-语言模型的特殊注意事项
DPOTrainer 支持微调视觉-语言模型 (VLM)。对于这些模型,需要视觉数据集。要了解有关视觉数据集特定格式的更多信息,请参阅 视觉数据集格式 部分。
此外,与使用 tokenizer
的标准基于文本的模型不同,对于 VLM,您应该将 tokenizer
替换为 processor
。
- model = AutoModelForCausalLM.from_pretrained(model_id)
+ model = AutoModelForVision2Seq.from_pretrained(model_id)
- tokenizer = AutoTokenizer.from_pretrained(model_id)
+ processor = AutoProcessor.from_pretrained(model_id)
trainer = DPOTrainer(
model,
args=training_args,
train_dataset=train_dataset,
- processing_class=tokenizer,
+ processing_class=processor,
)
有关微调视觉-语言模型的完整示例,请参阅 examples/scripts/dpo_vlm.py
中的脚本。
示例脚本
我们提供了一个示例脚本,用于使用 DPO 方法训练模型。该脚本可在 trl/scripts/dpo.py
中找到
要使用 Qwen2 0.5B 模型 在 UltraFeedback 数据集上测试 DPO 脚本,请运行以下命令
accelerate launch trl/scripts/dpo.py \ --model_name_or_path Qwen/Qwen2-0.5B-Instruct \ --dataset_name trl-lib/ultrafeedback_binarized \ --num_train_epochs 1 \ --logging_steps 25 \ --output_dir Qwen2-0.5B-DPO
记录的指标
在训练和评估期间,我们记录以下奖励指标
rewards/chosen
:策略模型和参考模型对于选择的响应的对数概率之间的平均差异,按 beta 缩放rewards/rejected
:策略模型和参考模型对于拒绝的响应的对数概率之间的平均差异,按 beta 缩放rewards/accuracies
:选择的奖励 > 对应拒绝的奖励的平均频率rewards/margins
:选择的奖励与对应拒绝的奖励之间的平均差异
损失函数
DPO 算法支持多种损失函数。可以使用 DPOConfig 中的 loss_type
参数设置损失函数。支持以下损失函数
loss_type= | 描述 |
---|---|
"sigmoid" (默认) | 给定偏好数据,我们可以根据 Bradley-Terry 模型拟合二元分类器,实际上 DPO 作者提出了通过 logsigmoid 对归一化似然的 sigmoid 损失,以拟合逻辑回归。 |
"hinge" | RSO 作者建议在 SLiC 论文中使用来自归一化似然的 hinge 损失。在这种情况下,beta 是边距的倒数。 |
"ipo" | IPO 作者提供了对 DPO 算法的更深层次的理论理解,并识别了过度拟合问题,并提出了替代损失。在这种情况下,beta 是选择的完成对与拒绝的完成对的对数似然比之间的差距的倒数,因此 beta 越小,此差距越大。根据论文,损失是在完成的对数似然上平均的(与仅求和的 DPO 不同)。 |
"exo_pair" | EXO 作者建议最小化反向 KL 而不是 DPO 的负对数 sigmoid 损失,后者对应于前向 KL。设置非零 label_smoothing (默认 1e-3 )会导致 EXO 在成对偏好上的简化版本(参见 EXO 论文的等式 (16))。完整版本的 EXO 使用 SFT 策略生成的 K>2 完成,当 K 足够大时,它将成为 PPO 目标的无偏估计量(直到一个常数)。 |
"nca_pair" | NCA 作者表明,NCA 优化每个响应的绝对似然性,而不是相对似然性。 |
"robust" | Robust DPO 作者提出了 DPO 损失的无偏估计,该估计对数据中的偏好噪声具有鲁棒性。与 cDPO 类似,它假设偏好标签在一定概率下是有噪声的。在这种方法中,DPOConfig 中的 label_smoothing 参数用于模拟现有标签噪声的概率。要应用此保守损失,请将 label_smoothing 设置为大于 0.0 的值(介于 0.0 和 0.5 之间;默认值为 0.0) |
"bco_pair" | BCO 作者训练了一个二元分类器,其 logit 用作奖励,以便分类器将 {prompt, chosen completion} 对映射到 1,将 {prompt, rejected completion} 对映射到 0。对于不成对的数据,我们建议使用专用的 BCOTrainer。 |
"sppo_hard" | SPPO 作者声称,SPPO 能够通过迭代地将选择的奖励推高至 1/2,并将拒绝的奖励推低至 -1/2 来迭代地解决纳什均衡,并可以缓解数据稀疏性问题。该实现通过采用硬标签概率来近似此算法,为获胜者分配 1,为失败者分配 0。 |
"aot" 或 loss_type="aot_pair" | AOT 作者建议使用通过最优传输的分布偏好对齐。传统上,对齐算法在样本级别使用成对偏好,这不能确保在分布级别上对齐。另一方面,AOT 可以通过使正样本的奖励分布在负样本分布上在第一阶随机占优来对齐 LLM 上的成对或不成对偏好数据。具体来说,loss_type="aot" 适用于成对数据集,其中每个提示都包含选择的和拒绝的响应;loss_type="aot_pair" 适用于不成对的数据集。简而言之,loss_type="aot" 确保对齐模型的选择与拒绝的对数似然比具有比参考模型的比率更高的分位数。loss_type="aot_pair" 确保选择的奖励在所有分位数上都高于拒绝的奖励。请注意,在这两种情况下,分位数都是通过排序获得的。为了充分利用 AOT 算法的优势,最大化每 GPU 批次大小非常重要。 |
"apo_zero" 或 loss_type="apo_down" | APO 方法引入了对齐目标的“锚定”版本。有两种变体:apo_zero 和 apo_down 。当模型性能不如获胜输出时,apo_zero 损失会增加获胜输出的可能性,同时降低失败输出的可能性,使其适用。另一方面,apo_down 会降低获胜输出和失败输出的可能性,但更强调降低失败输出的可能性。当模型优于获胜输出时,此变体更有效。 |
"discopop" | DiscoPOP 论文使用 LLM 来发现更有效的离线偏好优化损失。在论文中,提出的 DiscoPOP 损失(这是一种对数比率调制损失)在不同的任务(IMDb 正面文本生成、Reddit TLDR 摘要和 Alpaca Eval 2.0)上优于其他优化损失。 |
标签平滑
cDPO 是对 DPO 损失的一种调整,我们假设偏好标签在一定概率下是有噪声的。在这种方法中,DPOConfig 中的 label_smoothing
参数用于模拟现有标签噪声的概率。要应用此保守损失,请将 label_smoothing
设置为大于 0.0 的值(介于 0.0 和 0.5 之间;默认值为 0.0)。
同步参考模型
TR-DPO 论文建议在 DPO 训练期间,每经过 ref_model_sync_steps
步 SGD 后,使用权重 ref_model_mixup_alpha
同步参考模型权重。要切换此回调,请在 DPOConfig 中使用 sync_ref_model=True
。
RPO 损失
RPO 论文使用与此 论文 中的 RPO 损失相关的损失实现了一种迭代偏好调整算法,该算法本质上包括对选定的偏好进行加权 SFT 损失以及 DPO 损失。要使用此损失,请在 DPOConfig 中将 rpo_alpha
设置为适当的值。该论文建议将此权重设置为 1.0
。
WPO 损失
WPO 论文通过根据当前策略下的概率重新加权偏好对,使离线策略数据更接近在线策略数据。要使用此方法,请在 DPOConfig 中将 use_weighting
标志设置为 True
。
对于专家混合模型:启用辅助损失
如果负载在专家之间大致均匀分布,则 MOE 模型效率最高。
为了确保我们在偏好调整期间以类似的方式训练 MOE 模型,将来自负载均衡器的辅助损失添加到最终损失中是有益的。
通过在模型配置中设置 output_router_logits=True
(例如 MixtralConfig
)来启用此选项。
要缩放辅助损失对总损失的贡献程度,请在模型配置中使用超参数 router_aux_loss_coef=...
(默认值:0.001
)。
使用 unsloth 加速 DPO 微调
您可以使用 unsloth
库进一步加速 QLoRA / LoRA(速度快 2 倍,内存减少 60%),该库与 SFTTrainer
完全兼容。目前,unsloth
仅支持 Llama(Yi、TinyLlama、Qwen、Deepseek 等)和 Mistral 架构。下面列出了一些 DPO 的基准测试
GPU | 模型 | 数据集 | 🤗 | 🤗 + Flash Attention 2 | 🦥 Unsloth | 🦥 节省 VRAM |
---|---|---|---|---|---|---|
A100 40G | Zephyr 7b | Ultra Chat | 1x | 1.24x | 1.88x | -11.6% |
Tesla T4 | Zephyr 7b | Ultra Chat | 1x | 1.09x | 1.55x | -18.6% |
首先根据 官方文档 安装 unsloth
。安装完成后,您可以通过非常简单的方式将 unsloth 集成到您的工作流程中;您只需要加载 FastLanguageModel
,而不是加载 AutoModelForCausalLM
,如下所示
from datasets import load_dataset
from trl import DPOConfig, DPOTrainer
- from transformers import AutoModelForCausalLM, AutoTokenizer
+ from unsloth import FastLanguageModel
- model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
- tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
+ model, tokenizer = FastLanguageModel.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
+ model = FastLanguageModel.get_peft_model(model)
train_dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train")
- training_args = DPOConfig(output_dir="Qwen2-0.5B-DPO", logging_steps=10)
+ training_args = DPOConfig(output_dir="Qwen2-0.5B-DPO", logging_steps=10, bf16=True)
trainer = DPOTrainer(model=model, args=training_args, processing_class=tokenizer, train_dataset=train_dataset)
trainer.train()
保存的模型与 Hugging Face 的 transformers 库完全兼容。在 官方仓库 中了解更多关于 unsloth 的信息。
使用 PEFT 的参考模型注意事项
当使用 PEFT 时,关于参考模型如何工作,您有三个主要选项(以及几个变体),假设您想要使用 DPO 进一步增强的模型是使用 (Q)LoRA 进行调整的。
- 简单地创建模型的两个实例,每个实例加载您的适配器 - 工作正常,但效率非常低。
- 将适配器合并到基础模型中,在顶部创建另一个适配器,然后将
ref_model
参数留空,在这种情况下,DPOTrainer 将卸载适配器以进行参考推断 - 高效,但存在下面讨论的潜在缺点。 - 使用不同的名称两次加载适配器,然后在训练期间使用
set_adapter
在要进行 DPO 的适配器和参考适配器之间切换 - 与方法 2 相比效率稍低(约适配器大小的 VRAM 开销),但避免了陷阱。
在 DPO 之前合并 QLoRA 的缺点(方法 2)
正如 Benjamin Marie 建议的那样,合并 QLoRA 适配器的最佳选择是首先对基础模型进行反量化,然后合并适配器。类似于 此脚本。
但是,在使用此方法之后,您将拥有一个未量化的基础模型。因此,要将 QLoRA 用于 DPO,您将需要重新量化合并后的模型或使用未量化的合并(导致更高的内存需求)。
使用选项 3 - 两次加载适配器
为了避免选项 2 的缺点,您可以将微调后的适配器加载到模型中两次,使用不同的名称,并在 DPOTrainer 中设置模型/参考适配器名称。
例如
# Load the base model.
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
llm_int8_threshold=6.0,
llm_int8_has_fp16_weight=False,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
)
model = AutoModelForCausalLM.from_pretrained(
"mistralai/mixtral-8x7b-v0.1",
load_in_4bit=True,
quantization_config=bnb_config,
attn_implementation="flash_attention_2",
torch_dtype=torch.bfloat16,
device_map="auto",
)
model.config.use_cache = False
# Load the adapter.
model = PeftModel.from_pretrained(
model,
"/path/to/peft",
is_trainable=True,
adapter_name="train",
)
# Load the adapter a second time, with a different name, which will be our reference model.
model.load_adapter("/path/to/peft", adapter_name="reference")
# Initialize the trainer, without a ref_model param.
training_args = DPOConfig(
model_adapter_name="train",
ref_adapter_name="reference",
)
dpo_trainer = DPOTrainer(
model,
args=training_args,
...
)
DPOTrainer
class trl.DPOTrainer
< source >( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.modules.module.Module, str, NoneType] = None ref_model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.modules.module.Module, str, NoneType] = None args: typing.Optional[trl.trainer.dpo_config.DPOConfig] = None data_collator: typing.Optional[transformers.data.data_collator.DataCollator] = None train_dataset: typing.Optional[datasets.arrow_dataset.Dataset] = None eval_dataset: typing.Union[datasets.arrow_dataset.Dataset, dict[str, datasets.arrow_dataset.Dataset], NoneType] = None processing_class: typing.Union[transformers.tokenization_utils_base.PreTrainedTokenizerBase, transformers.image_processing_utils.BaseImageProcessor, transformers.feature_extraction_utils.FeatureExtractionMixin, transformers.processing_utils.ProcessorMixin, NoneType] = None model_init: typing.Optional[typing.Callable[[], transformers.modeling_utils.PreTrainedModel]] = None compute_metrics: typing.Optional[typing.Callable[[transformers.trainer_utils.EvalLoopOutput], dict]] = None callbacks: typing.Optional[list[transformers.trainer_callback.TrainerCallback]] = None optimizers: tuple = (None, None) preprocess_logits_for_metrics: typing.Optional[typing.Callable[[torch.Tensor, torch.Tensor], torch.Tensor]] = None peft_config: typing.Optional[dict] = None )
参数
- model (
transformers.PreTrainedModel
) — 要训练的模型,最好是AutoModelForSequenceClassification
。 - ref_model (
PreTrainedModelWrapper
) — 带有因果语言建模头的 Hugging Face transformer 模型。用于隐式奖励计算和损失。如果未提供参考模型,训练器将创建一个与要优化的模型具有相同架构的参考模型。 - args (
DPOConfig
) — 用于训练的 DPO 配置参数。 - data_collator (
transformers.DataCollator
) — 用于训练的数据整理器。如果未指定,将使用默认数据整理器 (DataCollatorForPreference
),它将根据成对序列的数据集将序列填充到批次中序列的最大长度。 - train_dataset (
datasets.Dataset
) — 用于训练的数据集。 - eval_dataset (
datasets.Dataset
) — 用于评估的数据集。 - processing_class (
PreTrainedTokenizerBase
或BaseImageProcessor
或FeatureExtractionMixin
或ProcessorMixin
, 可选) — 用于处理数据的处理类。如果提供,将用于自动处理模型的输入,并将与模型一起保存,以便更容易地重新运行中断的训练或重用微调后的模型。这取代了现在已弃用的tokenizer
参数。 - model_init (
Callable[[], transformers.PreTrainedModel]
) — 用于训练的模型初始化器。如果未指定,将使用默认模型初始化器。 - compute_metrics (
Callable[[EvalPrediction], dict]
, 可选) — 用于计算指标的函数。必须接受EvalPrediction
并返回一个将字符串映射到指标值的字典。 - 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 (
dict
, 默认为None
) — 用于训练的 PEFT 配置。如果您传递 PEFT 配置,模型将被包装在 PEFT 模型中。
初始化 DPOTrainer。
计算参考模型对于 DPO 特定数据集的单个填充批次的对数概率。
在给定的输入批次上运行给定的模型,将选择的和拒绝的输入连接在一起。
我们这样做是为了避免执行两次前向传递,因为对于 FSDP 来说速度更快。
concatenated_inputs
< source >( batch: dict padding_value: int ) → dict[str, torch.LongTensor]
参数
- batch (
dict[str, Union[list, torch.LongTensor]]
) — 输入数据批次。该批次必须包含以下键:"prompt_input_ids"
: 形状为(batch_size, prompt_length)
的张量,表示提示输入 ID。"chosen_input_ids"
: 形状为(batch_size, chosen_length)
的张量,表示选择的完成输入 ID。"rejected_input_ids"
: 形状为(batch_size, rejected_length)
的张量,表示拒绝的完成输入 ID。"prompt_pixel_values"
(可选): 像素值的张量(如果可用)。"prompt_pixel_attention_mask"
(可选): 像素注意力掩码的张量(如果可用)。
- padding_value (
int
) — 用于连接完成序列(chosen_input_ids
和rejected_input_ids
)的填充值。
返回值
dict[str, torch.LongTensor]
包含以下内容的字典
"prompt_input_ids"
: 连接的提示输入 ID,形状为(2 * batch_size, prompt_length)
。"completion_input_ids"
: 连接的选择的和拒绝的完成输入 ID,形状为(2 * batch_size, max_completion_length)
。"prompt_attention_mask"
: 连接的提示注意力掩码,形状为(2 * batch_size, prompt_length)
。"completion_attention_mask"
: 连接的选择的和拒绝的注意力掩码,形状为(2 * batch_size, max_completion_length)
。"pixel_values"
(可选): 连接的像素值(如果存在"prompt_pixel_values"
)。"pixel_attention_mask"
(可选): 连接的像素注意力掩码(如果存在"prompt_pixel_attention_mask"
)。
将批次中的 chosen
和 rejected
输入连接到提示序列和完成序列的单个张量中。
注意:完成输入 ID 和注意力掩码被填充到选择或拒绝序列的最大完成长度。
create_model_card
< 源代码 >( model_name: typing.Optional[str] = None dataset_name: typing.Optional[str] = None tags: typing.Union[str, list[str], NoneType] = None )
使用 Trainer
可用的信息创建模型卡片的草稿。
dpo_loss
< 源代码 >( chosen_logps: FloatTensor rejected_logps: FloatTensor ref_chosen_logps: FloatTensor ref_rejected_logps: FloatTensor ) → 包含三个张量的元组
参数
- chosen_logps (
torch.FloatTensor
) — 模型对于选择的响应的对数概率。形状:(batch_size,)
。 - rejected_logps (
torch.FloatTensor
) — 模型对于拒绝的响应的对数概率。形状:(batch_size,)
。 - ref_chosen_logps (
torch.FloatTensor
) — 参考模型对于选择的响应的对数概率。形状:(batch_size,)
。 - ref_rejected_logps (
torch.FloatTensor
) — 参考模型对于拒绝的响应的对数概率。形状:(batch_size,)
。
返回值
包含三个张量的元组
(losses, chosen_rewards, rejected_rewards)
。 losses 张量包含批次中每个样本的 DPO 损失。 chosen_rewards
和 rejected_rewards
张量分别包含选择和拒绝的响应的奖励。
计算一批策略和参考模型对数概率的 DPO 损失。
evaluation_loop
< 源代码 >( dataloader: DataLoader description: str prediction_loss_only: typing.Optional[bool] = None ignore_keys: typing.Optional[list[str]] = None metric_key_prefix: str = 'eval' )
重写内置的评估循环以存储每个批次的指标。预测/评估循环,由 Trainer.evaluate()
和 Trainer.predict()
共享。
有标签或无标签均可使用。
从模型和参考模型为给定的输入批次生成样本。
get_batch_loss_metrics
< 源代码 >( model batch: dict train_eval: typing.Literal['train', 'eval'] = 'train' )
计算给定输入批次的 DPO 损失和其他指标,用于训练或测试。
get_eval_dataloader
< 源代码 >( eval_dataset: typing.Optional[datasets.arrow_dataset.Dataset] = None )
参数
- eval_dataset (
torch.utils.data.Dataset
, 可选) — 如果提供,将覆盖self.eval_dataset
。 如果它是 Dataset,则会自动删除model.forward()
方法不接受的列。 它必须实现__len__
。
返回评估 ~torch.utils.data.DataLoader
。
transformers.src.transformers.trainer.get_eval_dataloader 的子类,用于预计算 ref_log_probs
。
返回训练 ~torch.utils.data.DataLoader
。
transformers.src.transformers.trainer.get_train_dataloader 的子类,用于预计算 ref_log_probs
。
log
< 源代码 >( logs: dict start_time: typing.Optional[float] = None )
在监视训练的各种对象上记录 logs
,包括存储的指标。
用于处理空参考模型(即,peft 适配器操作)的上下文管理器。
process_row
< 源代码 >( features processing_class max_prompt_length max_completion_length add_special_tokens )
与 tokenize_row
相同,但用于视觉模型。 有关更多信息,请参阅 tokenize_row
。
tokenize_row
< 源代码 >( features processing_class max_prompt_length max_completion_length add_special_tokens ) → dict[str, list[int]]
参数
- features (
dict[str, str]
) — 数据集的行,应包含键"prompt"
、"chosen"
和"rejected"
。 - processing_class (
PreTrainedTokenizerBase
) — 用于处理数据的处理类。 - max_prompt_length (
int
或None
) — 提示序列的最大长度。如果为None
,则不截断提示序列。 - max_completion_length (
int
或None
) — 完成序列的最大长度。如果为None
,则不截断完成序列。 - add_special_tokens (
bool
) — 是否向序列添加特殊 token。通常用于编码器-解码器模型。如果为True
,则提示序列将前置一个 bos token 并附加一个 eos token。在任何情况下,完成序列都将附加一个 eos token。
返回值
dict[str, list[int]]
带有键 "prompt_input_ids"
、"chosen_input_ids"
和 “rejected_input_ids”
的 Tokenized 序列。
Tokenize 数据集的一行。
示例
>>> from transformers import GPT2Tokenizer
>>> tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
>>> features = {"prompt": "The sky is", "chosen": " blue", "rejected": " green"}
>>> DPOTrainer.tokenize_row(
... features, tokenizer, max_prompt_length=3, max_completion_length=3, add_special_tokens=False
... )
{'prompt_input_ids': [464, 6766, 318], 'chosen_input_ids': [4171, 50256], 'rejected_input_ids': [4077, 50256]}
DPOConfig
class trl.DPOConfig
< source >( output_dir: typing.Optional[str] = None overwrite_output_dir: bool = False do_train: bool = False do_eval: bool = False do_predict: bool = False eval_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'no' prediction_loss_only: bool = False per_device_train_batch_size: int = 8 per_device_eval_batch_size: int = 8 per_gpu_train_batch_size: typing.Optional[int] = None per_gpu_eval_batch_size: typing.Optional[int] = None gradient_accumulation_steps: int = 1 eval_accumulation_steps: typing.Optional[int] = None eval_delay: typing.Optional[float] = 0 torch_empty_cache_steps: typing.Optional[int] = None learning_rate: float = 1e-06 weight_decay: float = 0.0 adam_beta1: float = 0.9 adam_beta2: float = 0.999 adam_epsilon: float = 1e-08 max_grad_norm: float = 1.0 num_train_epochs: float = 3.0 max_steps: int = -1 lr_scheduler_type: typing.Union[transformers.trainer_utils.SchedulerType, str] = 'linear' lr_scheduler_kwargs: typing.Union[dict, str, NoneType] = <factory> warmup_ratio: float = 0.0 warmup_steps: int = 0 log_level: typing.Optional[str] = 'passive' log_level_replica: typing.Optional[str] = 'warning' log_on_each_node: bool = True logging_dir: typing.Optional[str] = None logging_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'steps' logging_first_step: bool = False logging_steps: float = 500 logging_nan_inf_filter: bool = True save_strategy: typing.Union[transformers.trainer_utils.SaveStrategy, str] = 'steps' save_steps: float = 500 save_total_limit: typing.Optional[int] = None save_safetensors: typing.Optional[bool] = True save_on_each_node: bool = False save_only_model: bool = False restore_callback_states_from_checkpoint: bool = False no_cuda: bool = False use_cpu: bool = False use_mps_device: bool = False seed: int = 42 data_seed: typing.Optional[int] = None jit_mode_eval: bool = False use_ipex: bool = False bf16: bool = False fp16: bool = False fp16_opt_level: str = 'O1' half_precision_backend: str = 'auto' bf16_full_eval: bool = False fp16_full_eval: bool = False tf32: typing.Optional[bool] = None local_rank: int = -1 ddp_backend: typing.Optional[str] = None tpu_num_cores: typing.Optional[int] = None tpu_metrics_debug: bool = False debug: typing.Union[str, list[transformers.debug_utils.DebugOption]] = '' dataloader_drop_last: bool = False eval_steps: typing.Optional[float] = None dataloader_num_workers: int = 0 dataloader_prefetch_factor: typing.Optional[int] = None past_index: int = -1 run_name: typing.Optional[str] = None disable_tqdm: typing.Optional[bool] = None remove_unused_columns: typing.Optional[bool] = True label_names: typing.Optional[list[str]] = None load_best_model_at_end: typing.Optional[bool] = False metric_for_best_model: typing.Optional[str] = None greater_is_better: typing.Optional[bool] = None ignore_data_skip: bool = False fsdp: typing.Union[list[transformers.trainer_utils.FSDPOption], str, NoneType] = '' fsdp_min_num_params: int = 0 fsdp_config: typing.Union[dict, str, NoneType] = None tp_size: typing.Optional[int] = 0 fsdp_transformer_layer_cls_to_wrap: typing.Optional[str] = None accelerator_config: typing.Union[dict, str, NoneType] = None deepspeed: typing.Union[dict, str, NoneType] = None label_smoothing_factor: float = 0.0 optim: typing.Union[transformers.training_args.OptimizerNames, str] = 'adamw_torch' optim_args: typing.Optional[str] = None adafactor: bool = False group_by_length: bool = False length_column_name: typing.Optional[str] = 'length' report_to: typing.Union[NoneType, str, list[str]] = None ddp_find_unused_parameters: typing.Optional[bool] = None ddp_bucket_cap_mb: typing.Optional[int] = None ddp_broadcast_buffers: typing.Optional[bool] = None dataloader_pin_memory: bool = True dataloader_persistent_workers: bool = False skip_memory_metrics: bool = True use_legacy_prediction_loop: bool = False push_to_hub: bool = False resume_from_checkpoint: typing.Optional[str] = None hub_model_id: typing.Optional[str] = None hub_strategy: typing.Union[transformers.trainer_utils.HubStrategy, str] = 'every_save' hub_token: typing.Optional[str] = None hub_private_repo: typing.Optional[bool] = None hub_always_push: bool = False gradient_checkpointing: bool = False gradient_checkpointing_kwargs: typing.Union[dict, str, NoneType] = None include_inputs_for_metrics: bool = False include_for_metrics: list = <factory> eval_do_concat_batches: bool = True fp16_backend: str = 'auto' push_to_hub_model_id: typing.Optional[str] = None push_to_hub_organization: typing.Optional[str] = None push_to_hub_token: typing.Optional[str] = None mp_parameters: str = '' auto_find_batch_size: bool = False full_determinism: bool = False torchdynamo: typing.Optional[str] = None ray_scope: typing.Optional[str] = 'last' ddp_timeout: typing.Optional[int] = 1800 torch_compile: bool = False torch_compile_backend: typing.Optional[str] = None torch_compile_mode: typing.Optional[str] = None include_tokens_per_second: typing.Optional[bool] = False include_num_input_tokens_seen: typing.Optional[bool] = False neftune_noise_alpha: typing.Optional[float] = None optim_target_modules: typing.Union[NoneType, str, list[str]] = None batch_eval_metrics: bool = False eval_on_start: bool = False use_liger_kernel: typing.Optional[bool] = False eval_use_gather_object: typing.Optional[bool] = False average_tokens_across_devices: typing.Optional[bool] = False model_init_kwargs: typing.Optional[dict[str, typing.Any]] = None ref_model_init_kwargs: typing.Optional[dict[str, typing.Any]] = None model_adapter_name: typing.Optional[str] = None ref_adapter_name: typing.Optional[str] = None force_use_ref_model: bool = False disable_dropout: bool = True use_logits_to_keep: bool = False dataset_num_proc: typing.Optional[int] = None padding_value: typing.Optional[int] = None label_pad_token_id: int = -100 max_prompt_length: typing.Optional[int] = 512 max_completion_length: typing.Optional[int] = None max_length: typing.Optional[int] = 1024 truncation_mode: str = 'keep_end' padding_free: bool = False precompute_ref_log_probs: bool = False precompute_ref_batch_size: typing.Optional[int] = None tools: typing.Optional[list[typing.Union[dict, typing.Callable]]] = None loss_type: str = 'sigmoid' beta: float = 0.1 f_divergence_type: FDivergenceType = <FDivergenceType.REVERSE_KL: 'reverse_kl'> f_alpha_divergence_coef: float = 1.0 reference_free: bool = False label_smoothing: float = 0.0 use_weighting: bool = False rpo_alpha: typing.Optional[float] = None discopop_tau: float = 0.05 sync_ref_model: bool = False ref_model_mixup_alpha: float = 0.6 ref_model_sync_steps: int = 512 generate_during_eval: bool = False use_num_logits_to_keep: typing.Optional[bool] = None )
控制模型和参考模型的参数
- model_init_kwargs (
dict[str, Any]
或None
, 可选, 默认为None
) —AutoModelForCausalLM.from_pretrained
的关键字参数,当 DPOTrainer 的model
参数以字符串形式提供时使用。 - ref_model_init_kwargs (
dict[str, Any]
或None
, 可选, 默认为None
) — 当 DPOTrainer 的ref_model
参数以字符串形式提供时,用于AutoModelForCausalLM.from_pretrained
的关键字参数。 - model_adapter_name (
str
或None
, 可选, 默认为None
) — 使用带有多个适配器的 LoRA 时,训练目标 PEFT 适配器的名称。 - ref_adapter_name (
str
或None
, 可选, 默认为None
) — 使用带有多个适配器的 LoRA 时,参考 PEFT 适配器的名称。 - force_use_ref_model (
bool
, 可选, 默认为False
) — 如果您提供 PEFT 模型作为活动模型,并希望对ref_model
使用不同的模型,请将此标志设置为True
。 - disable_dropout (
bool
, 可选, 默认为True
) — 是否禁用模型和参考模型中的 dropout。 - use_logits_to_keep (
bool
, 可选, 默认为False
) — 如果为True
,则在前向传播中仅计算指定数量的 logits。这对于节省内存和加速训练非常有用,特别是当处理非常长的提示且标签被忽略 (-100) 时,无需计算所有 tokens 的 logits。
控制数据预处理的参数
- dataset_num_proc (
int
或None
, 可选, 默认为None
) — 用于处理数据集的进程数。 - padding_value (
int
或None
, 可选, 默认为None
) — 要使用的填充值。如果为None
,则使用 tokenizer 的填充值。 - label_pad_token_id (
int
, 可选, 默认为-100
) — 用于标签的填充值。 - max_prompt_length (
int
或None
, 可选, 默认为512
) — 提示的最大长度。 - max_completion_length (
int
或None
, 可选, 默认为None
) — 完成的最大长度。 - max_length (
int
或None
, 可选, 默认为1024
) — 完整序列(提示 + 完成)的最大长度。 - truncation_mode (
str
, 可选, 默认为"keep_end"
) — 当序列超过max_length
时使用的截断模式。可能的值为"keep_end"
和"keep_start"
。 - padding_free (
bool
, 可选, 默认为False
) — 是否执行无填充的前向传播,通过将批次中的所有序列展平为单个连续序列。这通过消除填充开销来减少内存使用。目前,这仅在使用flash_attention_2
注意力实现时受支持,它可以有效地处理展平的批次结构。 - precompute_ref_log_probs (
bool
, 可选, 默认为False
) — 是否预先计算来自参考模型的对数概率。将此设置为True
允许在训练期间无需参考模型即可进行训练,这有助于减少 GPU 内存使用。如果设置为False
(默认),则将在训练期间使用参考模型来动态计算对数概率。 - precompute_ref_batch_size (
int
或None
, 可选, 默认为None
) — 预计算参考模型对数概率时要使用的批次大小。这可以设置为高于训练批次大小以加速预处理。如果为None
,则训练默认为per_device_train_batch_size
,评估默认为per_device_eval_batch_size
。 - tools (
Optional[list[Union[dict, Callable]]]
, 可选, 默认为None
) — 模型可以访问的工具列表(可调用函数)。如果模板不支持函数调用,则此参数无效。
控制训练的参数
- learning_rate (
float
, 可选, 默认为1e-6
) —AdamW
优化器的初始学习率。默认值替换了TrainingArguments
的默认值。 - loss_type (
str
, 可选, 默认为"sigmoid"
) — 要使用的损失类型。可能的值为:"sigmoid"
: 来自原始 DPO 论文的 sigmoid 损失。"hinge"
: 来自 SLiC 论文的归一化似然的 hinge 损失。"ipo"
: 来自 IPO 论文的 IPO 损失。"exo_pair"
: 来自 EXO 论文的成对 EXO 损失。"nca_pair"
: 来自 NCA 论文的成对 NCA 损失。"robust"
: 来自 Robust DPO 论文的对偏好噪声鲁棒的 DPO 损失的无偏估计。"bco_pair"
: 来自 BCO 论文的成对 BCO 损失。"sppo_hard"
: 来自 SPPO 论文的带有硬标签的 SPPO 损失。"aot"
: 来自 AOT 论文的配对数据集的 AOT 损失。"aot_pair"
: 来自 AOT 论文的非配对数据集的 AOT 损失。"discopop"
: 来自 DiscoPOP 论文的 DiscoPOP(又名 Log-Ratio Modulated Loss, LRML)损失。"apo_zero"
: 来自 APO 论文的 APO-zero 损失。"apo_down"
: 来自 APO 论文的 APO-down 损失。
- beta (
float
, 可选, 默认为0.1
) — 控制与参考模型偏差的参数。较高的 β 意味着与参考模型的偏差较小。对于 IPO 损失 (loss_type="ipo"
),β 是 论文 中表示为 τ 的正则化参数。 - f_divergence_type (
str
, 可选, 默认为FDivergenceType.REVERSE_KL
) — 用于计算策略和参考模型之间散度的 f-散度正则化函数类型。 - f_alpha_divergence_coef (
float
, 可选, 默认为1.0
) — α-散度 u^-α 正则化函数中 DPO 损失的 α 系数。 - reference_free (
bool
, 可选, 默认为False
) — 是否忽略提供的参考模型,并隐式使用为所有响应分配相等概率的参考模型。 - label_smoothing (
float
, 可选, 默认为0.0
) — 来自 cDPO 报告和 Robust DPO 论文的 Robust DPO 标签平滑参数,应介于0.0
和0.5
之间。 - use_weighting (
bool
, 可选, 默认为False
) — 是否对损失进行加权,如 WPO 论文中所述。 - rpo_alpha (
float
, 可选, 默认为None
) — 来自 RPO 论文 (v3) 的 α 参数,它控制损失中 NLL 项的权重。如果为None
,则不应用加权,损失与 DPO 损失相同。论文建议rpo_alpha=1.0
。 - discopop_tau (
float
, optional, defaults to0.05
) — 来自 DiscoPOP 论文的 τ/温度参数,它控制对数比率调制损失的形状。 该论文建议默认值discopop_tau=0.05
。 - sync_ref_model (
bool
, optional, defaults toFalse
) — 是否每隔ref_model_sync_steps
步将参考模型与活动模型同步,使用ref_model_mixup_alpha
参数。 此同步源自 TR-DPO 论文。 - ref_model_mixup_alpha (
float
, optional, defaults to0.6
) — 来自 TR-DPO 论文的 α 参数,它控制更新期间当前策略和先前参考策略之间的混合程度。 参考策略根据以下公式更新:π_ref = α * π_θ + (1 - α) * π_ref_prev
。 要使用此参数,您必须设置sync_ref_model=True
。 - ref_model_sync_steps (
int
, optional, defaults to512
) — 来自 TR-DPO 论文的 τ 参数,它确定当前策略与参考策略同步的频率。 要使用此参数,您必须设置sync_ref_model=True
。
控制日志记录的参数
DPOTrainer 的配置类。
使用 HfArgumentParser
我们可以将此类转换为可在命令行中指定的 argparse 参数。
DataCollatorForPreference
类 trl.trainer.dpo_trainer.DataCollatorForPreference
< 源码 >( pad_token_id: int return_tensors: str = 'pt' )
用于偏好数据的数据整理器。 如果输入长度不完全相同,则会动态填充到批次的最大长度。
示例
>>> from trl import DataCollatorForPreference
>>> collator = DataCollatorForPreference(pad_token_id=0)
>>> examples = [
... {"prompt_input_ids": [1, 2, 3], "chosen_input_ids": [4, 5], "rejected_input_ids": [6]},
... {"prompt_input_ids": [7, 8], "chosen_input_ids": [9, 10], "rejected_input_ids": [11, 12, 13]}
... ]
>>> collator(examples)
{'prompt_input_ids': tensor([[1, 2, 3],
[0, 7, 8]]),
'prompt_attention_mask': tensor([[1, 1, 1],
[0, 1, 1]]),
'chosen_input_ids': tensor([[ 4, 5],
[ 9, 10]]),
'chosen_attention_mask': tensor([[1, 1],
[1, 1]]),
'rejected_input_ids': tensor([[ 6, 0, 0],
[11, 12, 13]]),
'rejected_attention_mask': tensor([[1, 0, 0],
[1, 1, 1]])
}