直接偏好对齐算法(DPO、IPO、KTO)实验效果对比、超参搜索
作者: NLP前沿 来源: NLP前沿
https://huggingface.co/blog/pref-tuning
introduction
这篇文章是关于对三种热门的LLM对齐算法进行实证评估:Direct Preference Optimization (DPO)、Identity Preference Optimisation (IPO)和Kahneman-Tversky Optimisation (KTO)。我们在两个经过监督微调但未进行偏好对齐的高质量7b LLM上进行了实验。我们发现,虽然有一种算法明显优于其他算法,但必须调整关键超参数才能获得最佳结果。
不依赖强化学习的对齐算法
直接偏好优化(DPO)已经成为将大语言模型(LLMs)与人类或AI偏好对齐的一种有前途的替代方法。与传统的基于强化学习的对齐方法不同,DPO将对齐公式重新构建为一个简单的损失函数,可以直接在偏好数据集上进行优化 {(x,y_w,y_l)} ,其中 x 是提示词,y_w,y_l 分别是首选和不首选的回应答案。
这使得DPO在实践中变得简单易用,并已成功应用于训练诸如Zephyr和英特尔的NeuralChat等模型。
DPO的成功促使研究人员沿着两个主要方向开发新的损失函数,以推广该方法。
-
鲁棒性:DPO 的一个缺点是它往往很快在偏好数据集上过拟合。为了避免这种情况,谷歌DeepMind的研究人员引入了Identity Preference Optimisation (IPO),它在DPO损失中添加了一个正则化项,使得可以训练模型收敛而无需使用提前停止等技巧。
-
放弃配对的偏好数据:与大多数对齐方法一样,DPO 需要一组配对偏好数据 { (x, y_w, y_l) },其中标注人员根据诸如帮助性或有害性之类的标准标记哪个答案更好。实际上,创建这些数据集是一项耗时且成本高昂的工作。ContextualAI 最近提出了一个有趣的替代方案,称为 Kahneman-Tversky 优化(KTO),它完全根据已标记为“好”或“坏”的个别示例定义损失函数(例如,在聊天界面中看到的👍或👎图标)。这些标签在实践中更容易获取,KTO 是不断更新在生产环境中运行的聊天模型的一种有前途的方式。
与此同时,这些各种方法都带有超参数,其中最重要的是 β,它控制着对参考模型偏好的权重。一个自然的问题就是哪种方法和超参数能够产生最好的聊天模型? 本文旨在通过对三种方法进行实证分析来回答这个问题。我们将对关键超参数(如 β 和训练步骤)进行扫描,然后通过 MT-Bench 评估所得模型的性能(这是一个常见的基准测试来衡量聊天模型的能力)。
代码在
https://github.com/huggingface/alignment-handbook
Experimental Setup
在执行对齐实验时,有两个主要因素需要考虑:我们选择优化的模型和对齐数据集。为了获得更多独立的数据点,我们考虑了两个模型,OpenHermes-2.5-Mistral-7B 和 Zephyr-7b-beta-sft,以及两个对齐数据集 Intel 的 orca_dpo_pairs 和 ultrafeedback-binarized 数据集。
在第一个实验中,我们使用了 OpenHermes-2.5-Mistral-7B,因为它是最佳的 7B 参数聊天模型之一,尚未经过任何对齐技术。然后我们使用了 Intel 的 orca_dpo_pairs 数据集,其中包含 13,000 个提示,其中选择的响应由 GPT-4 生成,不希望的响应由 Llama-Chat 13b 生成。这是 NeuralChat 和 NeuralHermes-2.5-Mistral-7B 背后的数据集。由于 KTO 并不需要成对的偏好,我们简单地将 GPT-4 的响应视为“好”的标签,将 Llama-Chat 13b 的响应视为“坏”的标签。虽然 GPT-4 的响应很可能比 Llama-Chat 13b 更受欢迎,但也可能有一些情况下 Llama-Chat-13b 会产生更好的响应,我们认为这代表了少数例子。
第二个实验对 Zephyr-7b-beta-sft 模型执行了偏好对齐,使用了 ultrafeedback-binarized 数据集,其中包含了 66,000 个提示和选择与拒绝的响应对。这个数据集被用来训练原始的 Zephyr 模型,在当时它是 7B 模型中在众多自动化基准测试和人类评估中表现最佳的模型。
Configuring the experiments
# Model arguments
model_name_or_path: teknium/OpenHermes-2.5-Mistral-7B
torch_dtype: null
# Data training arguments
dataset_mixer:
HuggingFaceH4/orca_dpo_pairs: 1.0
dataset_splits:
- train_prefs
- test_prefs
preprocessing_num_workers: 12
# Training arguments with sensible defaults
bf16: true
beta: 0.01
loss_type: sigmoid
do_eval: true
do_train: true
evaluation_strategy: steps
eval_steps: 100
gradient_accumulation_steps: 2
gradient_checkpointing: true
gradient_checkpointing_kwargs:
use_reentrant: False
hub_model_id: HuggingFaceH4/openhermes-2.5-mistral-7b-dpo
hub_model_revision: v1.0
learning_rate: 5.0e-7
logging_steps: 10
lr_scheduler_type: cosine
max_prompt_length: 512
num_train_epochs: 1
optim: adamw_torch
output_dir: data/openhermes-2.5-mistral-7b-dpo-v1.0
per_device_train_batch_size: 8
per_device_eval_batch_size: 8
push_to_hub_revision: true
save_strategy: "steps"
save_steps: 100
save_total_limit: 1
seed: 42
warmup_ratio: 0.1
我们为 Zephyr 实验创建了一个类似的基础配置文件。聊天模板是从基础聊天模型自动推断出来的,OpenHermes-2.5 使用 ChatML 格式,而 Zephyr 使用 H4 聊天模板。或者,如果你想使用自己的聊天格式,tokenizers 库现在已经启用了使用 jinja 格式字符串来定义用户自定义的聊天模板。
# Example of the Zephyr chat template
"{% for message in messages %}\n{% if message['role'] == 'user' %}\n{{ '<|user|>\n' + message['content'] + eos_token }}\n{% elif message['role'] == 'system' %}\n{{ '<|system|>\n' + message['content'] + eos_token }}\n{% elif message['role'] == 'assistant' %}\n{{ '<|assistant|>\n' + message['content'] + eos_token }}\n{% endif %}\n{% if loop.last and add_generation_prompt %}\n{{ '<|assistant|>' }}\n{% endif %}\n{% endfor %}"
将对话格式化如下:
# <|system|>
# You are a friendly chatbot who always responds in the style of a pirate.</s>
# <|user|>
# How many helicopters can a human eat in one sitting?</s>
# <|assistant|>
# Ah, me hearty matey! But yer question be a puzzler! A human cannot eat a helicopter in one sitting, as helicopters are not edible. They be made of metal, plastic, and other materials, not food!
Hyperparameter Sweep
我们通过 调整TRL DPOTrainer 的 loss_type 参数, 训练了 DPO、IPO 和 KTO 方法,其中 beta 的取值范围为 0.01、0.1、0.2,直到 0.9。我们包括了 0.01,因为我们观察到一些对齐算法对这个参数特别敏感。所有实验都训练了一个epoch。在每次运行中,所有其他超参数都保持不变,包括随机种子。
然后,我们在 Hugging Face 集群上启动了基于上述基本配置的扫描。
#!/bin/bash
# Define an array containing the base configs we wish to fine tune
configs=("zephyr" "openhermes")
# Define an array of loss types
loss_types=("sigmoid" "kto_pair" "ipo")
# Define an array of beta values
betas=("0.01" "0.1" "0.2" "0.3" "0.4" "0.5" "0.6" "0.7" "0.8" "0.9")
# Outer loop for loss types
for config in "${configs[@]}"; do
for loss_type in "${loss_types[@]}"; do
# Inner loop for beta values
for beta in "${betas[@]}"; do
# Determine the job name and model revision based on loss type
job_name="$config_${loss_type}_beta_${beta}"
model_revision="${loss_type}-${beta}"
# Submit the job
sbatch --job-name=${job_name} recipes/launch.slurm dpo pref_align_scan config_$config deepspeed_zero3 \\
"--beta=${beta} --loss_type=${loss_type} --output_dir=data/$config-7b-align-scan-${loss_type}-beta-${beta} --hub_model_revision=${model_revision}"
done
done
done
Results
我们使用MT Bench对所有模型进行了评估,这是一个多轮对话基准测试,使用GPT-4来评判模型在写作、角色扮演、推理、数学、编码、信息提取、STEM和人文等八个不同类别中的表现。虽然不完美,但MT Bench是评估对话式LLM性能的一个很好的方式。
Zephyr-7b-beta-SFT
针对 Zephyr 模型,我们观察到在测试的所有算法中,最佳性能是在最低的 β 值 0.01 下实现的。这一结果是一致的。对社区而言,一个有趣的后续实验可能是在 0.0-0.2 范围内进行细粒度的扫描。虽然 DPO 可以实现最高的 MT Bench 分数,但我们发现 KTO(配对)在除一个结果之外的所有情况下都取得了更好的结果。IPO,虽然具有更强的理论保证,但在除一个设置之外的所有情况下似乎都比基本模型差。
我们可以分解MT Bench评估的每个算法在各个类别中的最佳结果,以确定这些模型的优势和劣势。在推理、编码和数学方面仍有很大的改进空间。
OpenHermes-7b-2.5
尽管在OpenHermes中,对每个算法的观察结果保持不变,即DPO > KTO > IPO,但β与每个算法都有很大差异。对于DPO、KTO和IPO来说,最佳的β选择分别为0.6、0.3和0.01。
OpenHermes-7b-2.5 明显是一个更强大的基础模型,在偏好对齐后 MT Bench 分数仅提高了 0.3。
Summary & Insights
在这篇文章中,我们强调了在执行偏好对齐时选择正确的超参数集的重要性。我们在配对偏好设置中经验性地证明了 DPO 优于 KTO,尽管 IPO 在理论保证方面更强,但似乎表现平平。
更多AI工具,参考Github-AiBard123,国内AiBard123