【verl】快速入门:在 GSM8K 数据集上进行 PPO 训练

快速入门:在 GSM8K 数据集上进行 PPO 训练 — verl documentation

1.基本信息

  1. 目标:训练一个LLM,用基于函数的奖励处理GSM8k任务。
  2. 数据集:GSM8k是一个数学问题集. prompt是小学数学问题,LLM被要求解决数学问题。

2.步骤

1.准备数据集

对数据集进行预处理(parquet 格式),以便它包含计算 RL 奖励的必要字段,且读取速度更快。

python3 examples/data_preprocess/gsm8k.py --local_dir ~/data/gsm8k

运行报错,提示很多模块缺失。看起来与之前安装依赖项时的报错有关,一部分原因是GitHub难以直接访问,所以此时还缺了很多模块;依次重新安装;torch始终安装失败,显示空间不足。把pip换成conda,安装成功。

显示无法访问某个文件,但文件存在,路径也是正确的。

Original error was: libcblas.so.3: cannot open shared object file: No such file or directory

根据gpt的回答,这个问题常见于:

  • 从非 Conda 安装源装了 NumPy,缺少系统依赖;
  • 使用系统 Python / Miniconda 时,某些 .so 文件缺失;
  • 安装了错的 BLAS 库(如 MKL 和 OpenBLAS 冲突);

因此推荐用 Conda 管理这些低层依赖,尤其是 NumPy、SciPy、PyTorch 这类依赖 C 库的包。

一行命令修复所有相关数学库:

conda install -n verl -c conda-forge numpy scipy blas=*=openblas

更新 NumPy 到官方支持版本:

conda install numpy -n verl

再次运行后发现不再报相同的错误。仍然有部分模块缺失,继续补充安装;pip不行换conda,conda不行换pip,都出现解决不了的问题就重新创建conda环境,最终不再出现模块缺失报错。

ConnectionError: Couldn't reach 'openai/gsm8k' on the Hub (LocalEntryNotFoundError)

国内很难直接访问Hugging Face,只能把数据集下载到本地,再从本地加载。

(verl) XX@XX:/XX$ python3 examples/data_preprocess/gsm8k.py
Generating train split: 100%|██████████████████████████████████| 7473/7473 [00:00<00:00, 224025.17 examples/s]
Generating test split: 100%|███████████████████████████████████| 1319/1319 [00:00<00:00, 222331.99 examples/s]
Map: 100%|██████████████████████████████████████████████████████| 7473/7473 [00:00<00:00, 21730.41 examples/s]
Map: 100%|██████████████████████████████████████████████████████| 1319/1319 [00:00<00:00, 21416.08 examples/s]
Creating parquet from Arrow format: 100%|██████████████████████████████████████| 8/8 [00:00<00:00, 302.72ba/s]
Creating parquet from Arrow format: 100%|██████████████████████████████████████| 2/2 [00:00<00:00, 401.87ba/s]

这个脚本的作用是将 GSM8K 数据集处理成结构化格式,并保存为 .parquet 文件到local_dir下。脚本中设置local_dir为home目录下:

 为了方便起见,在verl文件夹下创建一个新的文件夹用于存放parquet文件,把前面已经得到的文件删掉。

ls -lh ~/data/gsm8k/*.parquet #列出指定目录下的文件
rm ~/data/gsm8k/*.parquet #删除指定文件

 2.下载模型以进行后续训练

python3 -c "import transformers; transformers.pipeline('text-generation', model='Qwen/Qwen2.5-0.5B-Instruct')"

同理,hug的模型也需要下载到本地。为了方便查看进度,先只下载指针文件,再拉取。

GIT_LFS_SKIP_SMUDGE=1 git clone https://hf-mirror.com/Qwen/Qwen2.5-0.5B-Instruct
cd Qwen2.5-0.5B-Instruct/
git lfs pull

Error: Failed to call git rev-parse --git-dir: exit status 128 
Not in a git repository.

说明当前的目录 xx/Qwen2.5-0.5B-Instruct 并不是一个有效的 Git 仓库,也就是说.git/ 目录可能缺失或被意外删除了。但这里的问题是Git 检测到当前仓库的拥有者(owner)与当前的用户不一致,出于安全考虑拒绝操作。Git 的提示也给出了解决方法:

git config --global --add safe.directory /xx/Qwen2.5-0.5B-Instruct

再git lfs pull即可。故修改这一步的代码为:

python3 -c "import transformers; transformers.pipeline('text-generation', model='/xx/Qwen2.5-0.5B-Instruct')"

这里出现了一个问题,显示Device set to use cpu。运行代码import torch;
print(torch.cuda.is_available())输出false,说明当前 Python 环境下 PyTorch 无法检测到 GPU。可能是pytorch版本不对,需要重装一下。

 总是显示磁盘空间不足。最后解决:用 --no-cache-dir,禁止pip缓存 .whl文件,减少磁盘占用

pip install --no-cache-dir torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

Device set to use cuda:0 #正常了

 3.使用 instruct 模型执行 PPO 训练

奖励模型/函数

使用一个预定义的基于规则的奖励模型。强制模型在解答中使用 #### 符号后给出最终答案。我们通过正则表达式匹配,从参考解答和模型输出中提取最终答案。对于奖励的分配方式如下:如果答案正确,则奖励为1;如果答案错误,则奖励为 0.0;如果没有答案,则奖励为 0。

更多详情参考 verl/utils/reward_score/gsm8k.py。

训练脚本

#!/bin/bash
PYTHONUNBUFFERED=1 python3 -m verl.trainer.main_ppo \ #设置 Python 输出不缓存,实时显示输出?
  data.train_files=/x/data/gsm8k/train.parquet \ #训练数据集
  data.val_files=/x/data/gsm8k/test.parquet \ #验证数据集
  data.train_batch_size=256 \
  data.max_prompt_length=512 \
  data.max_response_length=256 \
  actor_rollout_ref.model.path=/xx/Qwen2.5-0.5B-Instruct \ #用于初始化actor模型的预训练模型路径
  actor_rollout_ref.actor.optim.lr=1e-6 \
  actor_rollout_ref.actor.ppo_mini_batch_size=64 \
  actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=4 \
  actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=8 \
  actor_rollout_ref.rollout.tensor_model_parallel_size=1 \
  actor_rollout_ref.rollout.gpu_memory_utilization=0.4 \
  actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=4 \
  critic.optim.lr=1e-5 \
  critic.model.path=Qwen/Qwen2.5-0.5B-Instruct \
  critic.ppo_micro_batch_size_per_gpu=4 \
  algorithm.kl_ctrl.kl_coef=0.001 \
  trainer.logger=['console'] \
  trainer.val_before_train=False \
  trainer.default_hdfs_dir=null \
  trainer.n_gpus_per_node=1 \
  trainer.nnodes=1 \
  trainer.save_freq=10 \
  trainer.test_freq=10 \
  trainer.total_epochs=15 2>&1 | tee verl_demo.log

把所有代码直接粘到命令行,没法跑通,所以单独写了一个demo.sh。运行发现有缺很多module,继续补充安装。安装模块的时候老出现这样的报错:

 根据gpt的回答,这个问题常常出现在cuda版本上。查看nvcc:

nvcc -V

各种各样的问题。。。反正不兼容。重装conda环境,逐条运行安装脚本里的命令试一下;反正报错不一样了,就当这个问题解决了。

一番努力之后跑起来了,但一直报磁盘空间不足的错误。更改tmp的默认路径当前目录下:

mkdir -p /xx/tmp/ray
export RAY_TMPDIR=/xx/tmp/ray

看起来跑动了,每个step下都有一长串:

step总数为435;应该是由样本数、训练epoch数计算得到的(train_epoch从15改到5,435-->145)。不知为什么改了之后跑的时候会冒出来几个文件夹,文件夹里有代码文件。(尝试删掉了,暂时没出大问题) 

训练得到的结果存在文件夹:

4.跑通examples里的grpo算法

运行examples/grpo_trainer/下的脚本run_qwen2-7b.sh;和PPO同理,修改脚本中模型和数据的路径。出现报错:

raise HFValidationError( huggingface_hub.errors.HFValidationError: Repo id must be in the form 'repo_name' or 'namespace/repo_name':

经反复检查,纯粹是路径写错了。又出现了磁盘空间不足的问题,重复前面ppo中提到的设置。

运行出现cuda out of memory报错,调整参数(向ppo的例子靠拢)直到可以顺利跑动。具体来说改了以下部分:

    data.train_batch_size=1024-->256 \

    data.max_response_length=1024-->256 \

    actor_rollout_ref.actor.ppo_mini_batch_size=256-->64 \

    actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=40-->4 \

    actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=40-->4 \

    actor_rollout_ref.rollout.n=5-->3 \

    trainer.total_epochs=15-->3 $@

 代码可以正常运行;结果如下:

### VERILOG 中的共卡实现及相关仿真 在嵌入式系统开发中,“共卡”通常指的是共享资源或多任务协作机制的设计。对于基于 Verilog 的 FPGA 设计而言,共卡的概念可能涉及多个模块之间的资源共享、同步控制以及任务调度等问题[^1]。 #### 1. **Verilog中的资源共享** 在FPGA设计中,如果多个模块需要访问同一个硬件资源(如SD卡控制器),可以通过仲裁逻辑来管理这些请求。例如,在SD卡读写操作中,可以引入一个状态机用于协调不同任务间的访问顺序: ```verilog // 定义状态机类型 typedef enum logic [1:0] {IDLE, READ_CMD, WRITE_CMD} state_t; module ResourceArbiter ( input wire clk, input wire reset, output reg grant_read, output reg grant_write ); reg [1:0] current_state; always @(posedge clk or posedge reset) begin if (reset) begin current_state <= IDLE; grant_read <= 0; grant_write <= 0; end else begin case(current_state) IDLE : begin if(read_request && !write_request) begin current_state <= READ_CMD; grant_read <= 1; end else if(!read_request && write_request) begin current_state <= WRITE_CMD; grant_write <= 1; end end READ_CMD : begin // 执行读操作完成后返回空闲态 if(operation_complete) begin current_state <= IDLE; grant_read <= 0; end end WRITE_CMD : begin // 执行写操作完成后返回空闲态 if(operation_complete) begin current_state <= IDLE; grant_write <= 0; end end endcase end end endmodule ``` 此代码片段展示了一个简单的资源仲裁器如何通过状态机分配读/写权限给不同的任务[^1]。 #### 2. **FPGA中共卡仿真的方法** 当涉及到复杂的多任务场景时,利用 `$readmemb` 或者 `$readmemh` 可以为内存加载初始数据以便于模拟实际运行环境下的行为模式[^2]。下面是一个具体的例子说明如何设置测试平台以支持这种类型的仿真: ```verilog initial begin $readmemb("data_file.txt", memory_array); // 加载外部文件作为输入数据 // 设置其他初始化条件... #100; // 等待一段时间让系统稳定下来后再启动具体的操作流程 start_task_1(); start_task_2(); #500; // 继续等待直到所有任务都完成 $display("Simulation finished."); $finish; end ``` 这里假设 `memory_array` 是一块内部RAM区域用来保存即将由各个子任务处理的数据集;而 `"data_file.txt"` 则包含了预定义好的二进制或者十六进制数值序列供程序调用。 #### 3. **总结** 综上所述,在VERILOG 和 FPGA 开发过程中遇到所谓的“共卡”问题实际上就是指怎样有效地管理和优化有限物理器件上的并发活动。这不仅考验开发者对目标架构的理解程度同时也对其编程技巧提出了较高要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值