RWKV高级教程:预训练、继续预训练、全量微调、词表构建

本文假设你已经掌握了全参数微调的基本知识,参见:https://rwkv.cn/RWKV-Fine-Tuning/Full-ft-Simple。

RWKV预训练教程

0.1B v6/v7预训练示例

环境安装

克隆RWKV-LM仓库后,需要安装正确的依赖。

请使用Python 3.12版本。除了最新版的pytorch外,建议:

pip install pytorch-lightning==1.9.5 deepspeed==0.14.5 transformers ninja einops tqdm wandb datasets tokenizers

请注意,pytorch-lightning不支持版本2.0以上的pydantic,而deepspeed 0.14.5是最后一个支持pydantic 1.x的版本。由于pytorch-lightning更高版本的代码执行顺序不一致,这可能会导致报错。

代码下载

git clone https://github.com/BlinkDL/RWKV-LM
cd RWKV-LM/RWKV-v5
chmod +x ./demo-training-prepare.sh
chmod +x ./demo-training-run.sh

数据集下载和模型初始化

在demo-training-prepare.sh里有

#!/bin/bash
#######################################################################################################################
#
# This will generate the initial model, and save it to the output folder
#
#######################################################################################################################
#
# Please firstly create data folder & Download minipile (1498226207 tokens, around 3GB)
# mkdir -p data
# wget --continue -O data/minipile.idx https://huggingface.co/datasets/BlinkDL/minipile-tokenized/resolve/main/rwkv_vocab_v20230424/minipile.idx
# wget --continue -O data/minipile.bin https://huggingface.co/datasets/BlinkDL/minipile-tokenized/resolve/main/rwkv_vocab_v20230424/minipile.bin
#
#######################################################################################################################
#
# MODEL_TYPE="x052" # x052 => rwkv-5.2 (rwkv-5 final)
MODEL_TYPE="x060" # x060 => rwkv-6.0
# MODEL_TYPE="mamba" # pip install mamba_ssm --upgrade
#
N_LAYER="12"
N_EMBD="768"
#
CTX_LEN="512" # !!! change magic_prime if you change ctx_len !!!
PROJ_DIR="out/L"$N_LAYER"-D"$N_EMBD"-"$MODEL_TYPE # set output folder
#
#######################################################################################################################
#
# magic_prime = the largest 3n+2 prime smaller than datalen/ctxlen-1 (= 1498226207/512-1 = 2926222.06 in this case) = 2926181 in this case
# use https://www.dcode.fr/prime-numbers-search
#
python train.py --wandb "" --proj_dir $PROJ_DIR \
 --data_file "data/minipile" --data_type "binidx" --vocab_size 65536 --my_testing $MODEL_TYPE \
 --ctx_len $CTX_LEN --my_pile_stage 1 --epoch_count 1 --epoch_begin 0 \
 --epoch_save 1 --weight_decay 0 --head_size_a 64 \
 --num_nodes 1 --micro_bsz 1 --n_layer $N_LAYER --n_embd $N_EMBD --pre_ffn 0 --head_qk 0 --my_exit_tokens 1498226207 --magic_prime 2926181 \
 --lr_init 1e-5 --lr_final 1e-5 --warmup_steps 10 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 --my_pile_edecay 0 \
 --accelerator cpu --devices 1 --precision bf16 --strategy deepspeed_stage_2 --grad_cp 1

其中,第9、10和11行是用来下载数据集的,把注释去掉以便下载数据集:

mkdir -p data
wget --continue -O data/minipile.idx https://huggingface.co/datasets/BlinkDL/minipile-tokenized/resolve/main/rwkv_vocab_v20230424/minipile.idx
wget --continue -O data/minipile.bin https://huggingface.co/datasets/BlinkDL/minipile-tokenized/resolve/main/rwkv_vocab_v20230424/minipile.bin

模型架构MODEL_TYPE="x060"表示v6架构,MODEL_TYPE="x070"表示v7架构。
层数和维数N_LAYER="12"表示12层,N_EMBD="768"表示768维。这会初始化一个12层和768维的小模型,总大小约0.19B。如果你想要更大的模型,可以适当增加数值,但必须满足N_EMBD是64的倍数。
上下文长度:默认为CTX_LEN="512",必须是512的倍数。
初始化命令python train.py --wandb "" ...... 这条命令会初始化一个模型,这一命令的绝大部分参数没有具体的含义。
当你对参数满意时,保存并运行:

./demo-training-prepare.sh
2 个赞

训练前准备

打开./demo-training-run.sh,看到以下内容:

#!/bin/bash
#######################################################################################################################
#
# Run demo-training-prepare.sh with the same MODEL_TYPE & N_LAYER & N_EMBD first
# Or, rename your base model to rwkv-init.pth and put it in the output folder
#
# The trainer will load the last rwkv-*.pth in the folder, such that it can continue from a stopped run
# Therefore check the log (### Loading rwkv-xxx.pth... ###), and make sure you don't have extra rwkv-*.pth there
#
#######################################################################################################################
#
# MODEL_TYPE="x052" # x052 => rwkv-5.2 (rwkv-5 final)
MODEL_TYPE="x060" # x060 => rwkv-6.0
# MODEL_TYPE="mamba" # pip install mamba_ssm --upgrade
#
N_LAYER="12"
N_EMBD="768"
#
CTX_LEN="512" # !!! change magic_prime if you change ctx_len !!!
PROJ_DIR="out/L"$N_LAYER"-D"$N_EMBD"-"$MODEL_TYPE # set output folder
#
#######################################################################################################################
#
# Note bsz & lr affects model & training performance
# Small data => use smaller bsz & slightly smaller LR
# Large data => use larger bsz & slightly larger LR
# Larger model => use smaller LR
# Finetuning => use very small LR, such as 1e-5
#
M_BSZ="16" # takes ~9G VRAM here => reduce this to save VRAM, increase this for faster speed
LR_INIT="6e-4"
LR_FINAL="6e-5"
GRAD_CP=1 # 1 => slower, save VRAM; 0 => faster, more VRAM
EPOCH_SAVE=10 # save every 10 "miniepochs" (1 miniepoch = 40320 * ctx_len tokens) => decrease if your GPU is weak
#
#######################################################################################################################
#
# magic_prime = the largest 3n+2 prime smaller than datalen/ctxlen-1 (= 1498226207/512-1 = 2926222.06 in this case) = 2926181 in this case
# use https://www.dcode.fr/prime-numbers-search
#
N_NODE=1 # number of nodes
GPU_PER_NODE=1 # number of GPUs per node
#
DS_BUCKET_MB=2 # set to 2 for consumer GPUs, set to 200 for A100 / H100 (affects speed & vram usage)
#
python train.py --load_model "0" --wandb "Test" --proj_dir $PROJ_DIR --my_testing $MODEL_TYPE \
 --ctx_len $CTX_LEN --my_pile_stage 3 --epoch_count 999999 --epoch_begin 0 \
 --data_file "data/minipile" --my_exit_tokens 1498226207 --magic_prime 2926181 \
 --num_nodes $N_NODE --micro_bsz $M_BSZ --n_layer $N_LAYER --n_embd $N_EMBD --pre_ffn 0 --head_qk 0 \
 --lr_init $LR_INIT --lr_final $LR_FINAL --warmup_steps 10 --beta1 0.9 --beta2 0.99 --adam_eps 1e-18 --my_pile_edecay 0 --data_type "binidx" --vocab_size 65536 \
 --weight_decay 0.001 --epoch_save $EPOCH_SAVE --head_size_a 64 \
 --accelerator gpu --devices $GPU_PER_NODE --precision bf16 --strategy deepspeed_stage_2 --grad_cp $GRAD_CP --enable_progress_bar True --ds_bucket_mb $DS_BUCKET_MB
1 个赞

调整参数

如果你追求可复现性,不要动以下任何的参数,那么两次运行的结果是完全一样的。
MODEL_TYPEN_LAYERN_EMBDCTX_LENPROJ_DIR都必须和前面一致。
其他参数解读,参见 全参微调入门教程 - RWKV微调 。建议根据你的微调数据、设备性能进行调整。

参数 描述
M_BSZ=16 建议为2的幂,越大越好,显存不够为止。
EPOCH_SAVE=10 每隔多少个训练轮次保存一次训练模型
epoch_steps 不存在,会自动根据M_BSZ等参数进行计算,计算公式为 epoch_steps = 40320 / M_BSZ / N_NODE / GPU_PER_NODE
--wandb "Test" 非常建议注册一个WandB账号并在此填写你的项目名称,以便loss的观察和比较。
--data_type binidx 训练语料的文件格式,这里必须为binidx,对其他格式的支持没有通过验证。
--vocab_size 65536 词表大小,默认为 65536
--epoch_count 1 总训练轮次,预训练通常只训练一轮
--epoch_begin 0 初始训练轮次,始终是0,自动加载最新的检查点
--pre_ffn 0 将第一个time-mix层替换为channel-mix,通常保持关闭
--head_qk 0 保持默认值 0(关闭状态)
--lr_init 6e-4 初始学习率,计算公式为0.45 / N_EMBD并适当取整。 比如768维模型,初始学习率为0.45/768=0.0005859375,取整为6e-4。继续预训练的学习率和从头预训练稍有不同。
--lr_final 6e-5 最终学习率,计算公式为0.04 / N_EMBD并适当取整。
--warmup_steps 10 预热步骤,应当根据优化器和学习率的选取进行实验
--beta1 0.9 Adam 优化器 beta1 参数
--beta2 0.99 Adam 优化器 beta2 参数
--adam_eps 1e-18 Adam 优化器的 epsilon 参数,小的epsilon更稳定。
--accelerator gpu 加速器类型,必须是 gpu
--precision bf16 训练精度,默认为 bf16,也支持 “fp32”, “tf32”
--strategy deepspeed_stage_2 训练策略,deepspeed_stage_2
--grad_cp 1 梯度累积步数,0 加快训练但消耗更多显存,1 反之
--my_testing "x060" 训练的 RWKV 模型版本,必须和初始化一致

参数调整完成后,请记得保存 demo-training-run.sh 文件。
然后开启训练:

./demo-training-run.sh

训练中断了怎么办?

运行这一脚本会自动从中断的地方开始继续训练。请注意,多次中断会造成loss的损失,每次中断损失约为0.0008。

./demo-training-run.sh

策略的选择

--strategy支持的策略有deepspeed_stage_1deepspeed_stage_2deepspeed_stage_2_offloaddeepspeed_stage_3deepspeed_stage_3_offload
运行速率:
deepspeed_stage_1 > deepspeed_stage_2 > deepspeed_stage_2_offload
deepspeed_stage_2 > deepspeed_stage_3 > deepspeed_stage_3_offload
显存占用的关系同样如此:
deepspeed_stage_1 > deepspeed_stage_2 > deepspeed_stage_2_offload
deepspeed_stage_2 > deepspeed_stage_3 > deepspeed_stage_3_offload
CPU利用率:
deepspeed_stage_1 = deepspeed_stage_2 < deepspeed_stage_2_offload
deepspeed_stage_2 = deepspeed_stage_3 < deepspeed_stage_3_offload
需要注意,通常deepspeed_stage_3弱于deepspeed_stage_2_offload,但取决于你的CPU性能,如果CPU性能较差,建议deepspeed_stage_3

2 个赞

真快啊,不久前还在问的问题现在就能解决了 :+1:

刚在群问没多久就有教程了 :+1:

想请教一下,如何通过n_layer和n_embd计算模型大小呢?