# 人类对齐

本文档提供了各种人类偏好对齐算法的训练脚本。若您希望深入了解更详尽的算法信息及其选择方法，请参考[文档](https://github.com/modelscope/modelscope-classroom/blob/main/LLM-tutorial/M.%E4%BA%BA%E7%B1%BB%E5%81%8F%E5%A5%BD%E5%AF%B9%E9%BD%90%E8%AE%AD%E7%BB%83.md)


## 数据集
PPO与GRPO算法所需的数据仅为模型输入，也就是system prompt（可选）加上query。其中GRPO中的奖励函数可能需要额外的数据列，比如计算准确率需要`solution`列作为参考答案。

RM和DPO类算法如ORPO，CPO，SimPO，则需要 $(x,y_w,y_l)$ 格式的数据，其中 $x$ 表示模型输入，$y_w,y_l$ 分别表示符合人类偏好的偏好回答和不符合人类偏好的拒绝回答,比如![dpo_data](../../resources/dpo_data.png)

而KTO算法的数据比较特殊，只需要 $(x,y,\text{label})$ 格式的数据，其中 $x$ 表示模型输入，$y$ 表示模型输出，label表示回答是否符合人类偏好
比如![kto_data](../../resources/kto_data.png)

使用自定义数据集对文本模型或者多模态大模型进行RLHF训练可以参考[自定义数据集文档](../Customization/自定义数据集.md#rlhf)。

## GRPO
[论文arvix](https://arxiv.org/abs/2402.03300)

训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/grpo).

## DPO
[论文arvix](https://arxiv.org/abs/2305.18290)

超参

- beta：KL正则系数，值越大表示对偏离参考模型的惩罚越强。默认为0.1。
- loss_type：不同DPO算法变种，可选值参考[文档](https://huggingface.co/docs/trl/main/en/dpo_trainer#loss-functions)，默认为 'sigmoid'。
- (可选) loss_weights: 多种 loss 混合时的权重设置。

建议在开始 DPO 训练前，先用偏好数据集中用户偏好答案部分进行一次 SFT 训练，以确保数据分布更符合 DPO 算法的要求。

如需同时混合多个 loss（如用于 [MPO](https://arxiv.org/abs/2411.10442) 训练），可指定多个 loss_type，并通过 loss_weights 设置各自权重。

通过设置超参数 `rpo_alpha`，可在 loss 中混合一定比例的 SFT loss，从而提升训练的稳定性，默认值为 `1.`，等价于加入 loss_type sft

训练脚本参考

- [DPO脚本](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/dpo).
- [MPO脚本](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/mpo.sh).

## RM
[论文arvix](https://arxiv.org/abs/2203.02155)

RLHF中的Reward Modeling阶段

使用sft训练后的base model或者instruct model作为基底模型, 增加value head, 使用偏好数据集训练为reward model

增加的value head权重会保存在`value_head.safetensors` 或 `value_head.bin`文件中

RM损失函数如下

$
\text{loss} = -\log \sigma \left( r^{(c)} - r^{(r)} - m \right) + \lambda \left( r^{(c)} + r^{(r)} \right)^2
$

- $r^{(c)}$: 模型对 chosen response 的打分
- $r^{(r)}$: 模型对 rejected response 的打分
- $\lambda$: L2正则项系数，鼓励模型输出接近0，使用参数`center_rewards_coefficient`进行设置，来自[论文](https://arxiv.org/pdf/2307.09288), 默认为0
- $m$: margin项，鼓励模型根据不同难度的样本进行区分，需要数据集中提供`margin`列，默认为0，来自[论文](https://arxiv.org/pdf/2307.09288)


训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/rm.sh).

## PPO
[论文arvix](https://arxiv.org/abs/2203.02155)

RLHF中的PPO(proximal policy optimization)阶段, 涉及到四个模型
- model: 训练模型, sft训练后的base model或者instruct model
- ref_model: 参考模型, 默认为 model
- reward_model: 奖励模型, 由RM阶段训练得到
- value_model: 价值模型, 由reward_model初始化, 在训练中同步更新

超参

- local_rollout_forward_batch_size: 每次数据采样的批量大小, 默认为64
- whiten_rewards: 对奖励进行归一化处理, 默认为False
- kl_coef: KL散度项的系数, 默认为0.05
- cliprange: PPO策略损失函数中的clip范围, 默认为0.2
- vf_coef: 价值损失函数系数, 默认为0.1
- cliprange_value: PPO价值损失函数中的clip范围, 默认为0.2
- gamma: 累计奖励的折扣因子, 默认为1.0
- lam: [GAE](https://arxiv.org/abs/1506.02438)中的lambda系数, 默认为0.95
- num_sample_generations: 训练过程中生成的调试样本数量, 默认为10


注意: 训练base model时, 需要先sft后再进行rlhf, 指定chat template, sft_type建议使用full

训练中的指标解释参考[文档](https://huggingface.co/docs/trl/ppov2_trainer#explanation-of-the-logged-metrics)


## KTO
[论文arvix](https://arxiv.org/abs/2402.01306)

超参

- beta： KL正则系数，值越大表示对偏离参考模型的惩罚越大。默认为0.1
- desirable_weight ：损失函数中的$\lambda_D$项，偏好回答样本的损失权重, 默认为1.0
- undesirable_weight ：损失函数中的$\lambda_U$项，拒绝回答样本的损失权重，默认为1.0

用 $n_D$ 和 $n_U$ 分别表示数据集中偏好回答和拒绝回答的样本数量，对于超参 $\lambda_D$ 和 $\lambda_U$ ，作者推荐设置 $\frac{\lambda_Dn_D}{\lambda_Un_U}\in[1,\frac{4}{3}]$

训练脚本
使用 $(x,y,\text{label})$ 格式数据训练

训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/kto.sh).

## CPO
[论文arvix](https://arxiv.org/abs/2401.08417)
超参

- beta：隐含奖励前的系数，默认为0.1
- cpo_alpha: nll loss系数, 默认为1.0

训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/cpo.sh).

## ORPO
[论文arvix](https://arxiv.org/abs/2403.07691)

超参

- lambda: Odds Ratio loss系数

注意：ORPO使用参数`--beta`传入超参`lambda`

训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/orpo.sh).

## SimPO
[论文arvix](https://arxiv.org/abs/2405.14734)
超参

- beta：隐含奖励前的系数，默认为2.0
- simpo_gamma：reward margin项，默认为1.0
- cpo_alpha: 混合CPO nll loss提高训练稳定性, 默认为1.0, 设置0.0使用原始SimPO算法

训练脚本参考[这里](https://github.com/modelscope/ms-swift/tree/main/examples/train/rlhf/simpo.sh).
