Homework 2

作业二:奖励建模与直接偏好对齐

助教会在服务器ready左右,将这份作业对应的qwen系列代码更新至仓库中。想要在自己机器上预先尝试的同学,可以先运行opt-125m的相关代码。

本次作业重点关注基于偏好数据集的对齐方法。具体包括 奖励建模(Reward Modeling) 和 直接偏好对齐微调(Direct Preference Optimization, DPO)。

提交内容包括完整代码和实验报告。注意,如果在作业中遇到问题,先尝试自己解决或和同学讨论。环境配置可以参考代码库中README的介绍。自己实在无法解决,请在align-anything仓库中提issue/disscussion询问(详细流程会在后文介绍)。

本次作业有一定工作量,建议尽早开始做。

0. align-anything部署(20%)

预估时间:1小时。

实验材料一览

模型:PKU-Alignment/Beaver-0.5B-Instruct

数据:PKU-Alignment/Align-Anything

代码:PKU-Alignment/Align-Anything

PS: 以上材料已在课程服务器上提供,如果你不想在课程服务器上完成作业,请自行将以上材料下载至你的计算设备上。

0.0 服务器登录指南

  1. 在你熟悉的编译器软件,如VS Code中,配置ssh远程连接。
  2. 在 VS Code 中,安装 Remote - SSH 和 Jupyter 插件。
  3. 点击 VS Code 左侧的 Remote Explorer 选项卡,点击配置或添加按钮,效果基本相同。

配置实例:

Host homework-2  
  HostName www.example.com  # 请将www.example.com替换为你的服务器地址
  User coder  # 请将coder替换为你的用户名
  Port 30316 # 请将30316替换为你的端口号
  IdentityFile ~/.ssh/id_rsa # 请将id_rsa替换为你的公钥文件名
  1. 随后点击远程资源管理器,点击homework-2建立连接,操作平台选择Linux,在确保公钥正确的情况下,即可连接远程服务器。

参考教程:https://server.51cto.com/article/684146.html

  1. 除VS Code外,你也可以使用命令行终端连接服务器,示例:
ssh -i ~/.ssh/id_rsa [email protected] -p 30316

0.1 代码部署指南

  1. 使用你的个人邮箱创建github账号,github地址为:https://github.com
  2. 点击PKU-Alignment/align-anything进入项目主页
  3. 点击网页右上角的Fork按钮
  4. 点击Create fork

将你fork完成的仓库克隆到服务器,随后,根据PKU-Alignment/align-anything主页中提供的安装教程完成安装。

具体的,在本课程提供的华为云服务器上,执行如下操作:

  1. 创建虚拟环境
conda create -n align-anything python==3.11
conda activate align-anything
  1. 设定环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh
  1. 安装依赖
pip3 install -e .[ascend]

到这一步,若中间过程没有报错,则说明环境配置成功。

助教已在服务器上下载好模型和数据集,以下内容仅供参考。

0.2 模型下载指南

Huggig Face是目前最被广泛使用的大模型开源社区。本次作业涉及的模型与数据集均已被上传至该平台。在完成后续操作前,请注册一个Hugging Face账号,并在个人设置页面获取hf_token,形如:hf_xxxxxxxxx。

注意,Hugging Face只会显示一次hf_token,请在生成hf_token后及时保存。

  1. huggingface-cli登陆

完成代码部署后,在虚拟环境激活的前提下,在命令行执行:

huggingface-cli login

随后终端会提示你输入hf_token,请将先前保存的内容粘贴至终端。

  1. huggingface-cli下载模型

在命令行执行:

huggingface-cli download --resume-download PKU-Alignment/Beaver-0.5B-Instruct --local-dir LOCAL_DIR

请在LOCAL_DIR参数处指定你希望模型保存的路径,例如/home/user/Beaver-0.5B-Instruct

0.3 数据集下载指南

与下载模型类似,下载数据集的命令为:

huggingface-cli download --repo-type dataset --resume-download PKU-Alignment/PKU-SafeRLHF-single-dimension --local-dir LOCAL_DIR --local-dir-use-symlinks False

关于网络问题,没办法使用HuggingFace,可以参考HF-Mirror设置

1. 奖励模型实现(40%)

  • 预估时间:5小时。
  • 训练所需时间:2小时
  • 显存占用:不超过20GB

作业目的

  • 熟悉大模型微调框架的部署;
  • 熟悉大语言模型奖励建模的作用,原理;
  • 使用给定偏好数据集完成奖励模型的训练;
  • 在提供的验证集上进行评测,并基于验证集表现进行参数调优;

算力要求

  • 该部分作业需要在GPU上运行。

学习资料

以下是一些可以参考的资料:

1.1 部署align-anything,训练奖励模型(30%)

1.1.1 偏好数据集键值转换(10%)

大语言模型对齐研究往往需要研究不同偏好数据集,而不同的偏好数据集往往包含不同的键值名称,因此需要完成偏好数据集的键值转换。例如,PKU-SafeRLHF偏好数据集的键值名称为:

{  
    "prompt": "...",  
    "reponse_0": "...",  
    "reponse_1": "...",  
    "better_response_id": "..."  
}

而align-anything在进行奖励建模时,需要的键值名称为:

{  
    "better_text": "...",  
    "worse_text": "...",  
}

align-anything提供了一套名为template的机制,位于align-anything/configs/template.py,可以完成偏好数据集的键值转换。

例如,对于PKU-SafeRLHF偏好数据集,对应的template为:

@register_template('PKUSafeRLHF')
class PKUSafeRLHF(BaseFormatter):
    system_prompt: str = ''

    def format_preference_sample(
        self, raw_sample: dict[str, Any]
    ) -> tuple[list[dict[str, Any]], list[dict[str, Any]], str]:
        metrics = raw_sample['better_response_id']
        better_response = raw_sample[f'response_{int(metrics)}']
        worse_response = raw_sample[f'response_{1-int(metrics)}']
        prompt = raw_sample['prompt']

        better_conversation = [
            {'role': 'user', 'content': prompt},
            {'role': 'assistant', 'content': better_response},
        ]

        worse_conversation = [
            {'role': 'user', 'content': prompt},
            {'role': 'assistant', 'content': worse_response},
        ]

        meta_info = {
            'better_response': better_response,
            'worse_response': worse_response,
        }

        return better_conversation, worse_conversation, meta_info

而本作业中使用的偏好数据集为Align-Anything,对应数据集的原始键值名称为:

{
    "question": "...",
    "response_1": "...",
    "response_2": "...",
    "overall_response": "...",
}

你需要实现一个名为HOMEWORK的template,并基于该template完成偏好数据集的键值转换。

1.1.2 训练奖励模型(10%)

基于上述实现好的template,使用align-anything完成奖励模型训练。

训练的脚本位于align-anything/scripts/qwen/rm.sh,而奖励模型训练的超参数位于align-anything/configs/train/text_to_text/rm.yaml。你需要在脚本中指定好初始模型路径、数据集路径以及输出路径参数。

随后,运行如下命令完成奖励模型训练:

cd align-anything/scripts  
bash qwen/rm.sh
注意: 如果需要实时检测训练过程中某些指标(如损失函数、准确率等)的变化情况,可以在训练前指定WANDB_API_KEY,在训练开始后,即可在wandb网站上实时查看训练曲线。如果在训练前忘记指定WANDB_API_KEY,可在训练结束后使用wandb sync命令将训练曲线同步到wandb网站上。更多细节可以参考:https://docs.wandb.ai/。由于服务器无法访问境外网络,在线的wandb也许会发生连接错误,我们提供了tensorboard的备选方案。你可以使用tensorboard --logdir OUTPUT_DIR命令启动本地浏览器,观察训练曲线。其中OUTPUT_DIR为你当前训练保存模型的路径。

1.1.3 评测奖励模型(10%)

运行脚本以下即可完成奖励模型评测:

cd align-anything/scripts  
bash qwen/rm_eval.sh

通过评测奖励模型在验证集上的表现,结合训练过程曲线,即可观察奖励模型是否存在过拟合等现象,从而完成参数调优。

1.1.4 使用奖励模型可视化偏好数据集(10%)

偏好数据集中包含chosen和rejected的response,它们对应了人类的高维偏好。请你使用一些可视化方法直观地呈现它们的差异性。例如,可以使用训练好的奖励模型进行评分后,可视化问答对的评分频率分布。

提示 你可能需要手动处理你的偏好数据集,拆开为单个问答分别进行奖励模型打分,具体细节也可以参考2.1.2
cd align-anything/scripts  
bash qwen/rm_score.sh

1.2 回答问题(10%)

在你的实验报告中回答下列问题:

  • 奖励建模有哪些应用?
  • 奖励建模训练可能存在哪些鲁棒性问题?
  • 如何缓解奖励建模的长度偏差?
  • 有哪些拟合多元人类偏好的奖励建模方法?

每个问题的得分上限为5%,你可以参考以下的case决定如何在报告中回答问题:

满分case

  1. case_1: 高质量地回答了2个问题(回答的内容正确而丰富,有文献支撑)
  2. case_2: 认真地回答了3-4个问题(尽管有一些错误,但看得到你的思考)

低分case

  1. case_3: 使用GPT等模型生成不相关的4个答案
  2. case_4: 答案与其他同学存在雷同

2. DPO微调(40%)

  • 预估时间:10小时。
  • 训练时间:2.5小时
  • 显存占用:不超过40GB

作业目的

  • 理解DPO的原理,熟悉使用DPO进行微调的流程,并基于给定的偏好数据集完成模型的微调;
  • 评测DPO微调模型的效果,与初始模型进行对比,理解对齐算法的作用;
  • 分析DPO的局限性,并理解其局限性背后的原因;

算力要求

该部分作业需要在GPU上运行。

2.1 使用DPO微调模型(30%)

2.1.1 运行DPO微调(15%)

基于先前实现好的template,使用align-anything完成DPO模型的训练。

训练的脚本位于align-anything/scripts/qwen/dpo.sh,而DPO模型训练的超参数位于align-anything/configs/train/text_to_text/dpo.yaml。你需要在脚本中指定好初始模型路径、数据集路径以及输出路径参数。

随后,运行如下命令完成DPO模型训练:

cd align-anything/scripts  
bash qwen/dpo.sh

2.1.2 评测DPO微调模型(15%)

大语言模型的训练效果评测往往是面向结果的评测。你需要实现以下操作:

  1. 自行完成大模型的生成脚本,以下是一个例子:
from transformers import AutoModelForCausalLM, AutoTokenizer
device = "cuda" # the device to load the model onto

model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2-7B-Instruct",
    torch_dtype="auto",
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B-Instruct")

prompt = "Give me a short introduction to large language model."
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(device)

generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=512
)
generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]

response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
  1. 基于PKU-Alignment/Align-Anything数据集中的测试集,令模型在测试集上生成回复。

  2. 观察一些case,分析DPO改变了模型的何种行为,这种改变是否与偏好数据集一致。

  3. 尝试作出一些分析与可视化,例如:

  • 使用奖励模型为DPO微调模型和初始模型生成的回答分别打分,并统计二者的得分差异性(脚本位于align-anything/scripts/qwen/rm_score.sh)。
  • 如果DPO微调模型在测试集上的表现优于初始模型,请具体观察那些得分更高的case,并分析DPO微调模型在哪些方面做出了改进。
  • 如果DPO微调模型在测试集上的表现不如初始模型,请分析原因,是DPO微调不准确,还是奖励建模不准确。

2.2 回答问题(10%)

  • 从强化学习的角度,DPO是on-policy还是off-policy的,是online的还是offline的,为什么?
  • DPO主要针对传统RLHF的哪个方面进行了优化,关键见解是什么?
  • DPO和传统RLHF相比有哪些局限性,具体体现在哪些方面?
  • 现有的研究(KTO,SimPO,ORPO等)主要从哪些方面对DPO进行优化?

每个问题的得分上限为5%,你可以参考以下的case决定如何在报告中回答问题:

满分case

  1. case_1: 高质量地回答了2个问题(回答的内容正确而丰富,有文献支撑)
  2. case_2: 认真地回答了3-4个问题(尽管有一些错误,但看得到你的思考)

低分case

  1. case_3: 使用GPT等模型生成不相关的4个答案
  2. case_4: 答案与其他同学存在雷同

2.3 学习资料

以下是一些可以参考的资料:

2.4 作业提交

需要提交的材料包括PDF发送到指定邮箱,具体要求如下:

  1. 以PDF为格式的实验报告(中英文形式都可,编写方式自由,可以根据个人偏好使用word或latex),PDF文件需要发送至[email protected]
  2. 训练和评估过程中的可视化分析、case、以及模型生成的结果(不超过10MB),放于results文件夹中。
  3. 注意最后你需要提交的内容为:实验报告(pdf格式),支撑材料(文件夹),打包为压缩文件后发送至邮箱中即可。
Previous