|
| 1 | +# PaddleNLP 大模型新手指南-预训练 |
| 2 | +本教程将从新手视角出发,讲解如何使用 PaddleNLP 进行大语言模型(LLM)预训练。我们以 Qwen2.5-0.5B 模型为例,运行在百度星河平台(AI Studio)上,完整展示数据准备、模型构建、训练启动及调优建议。 |
| 3 | + |
| 4 | +我们在 Ai Studio 上同步公开了项目,也可以点击[链接](https://aistudio.baidu.com/projectdetail/9038113)在线体验大模型预训练。 |
| 5 | + |
| 6 | +目标: |
| 7 | +- 了解预训练任务基本流程 |
| 8 | +- 能运行 PaddleNLP 提供的训练脚本 |
| 9 | +- 会在自己的数据上复现训练过程 |
| 10 | + |
| 11 | +## 1. 依赖安装 |
| 12 | +首先安装 PaddlePaddle 和 PaddleNLP 的[最新版本](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/linux-pip.html): |
| 13 | + |
| 14 | + |
| 15 | +```python |
| 16 | +# 安装PaddlePaddle最新版本 |
| 17 | +python -m pip install --pre paddlepaddle-gpu -i https://www.paddlepaddle.org.cn/packages/nightly/cu118/ |
| 18 | +``` |
| 19 | + |
| 20 | + |
| 21 | +```python |
| 22 | +# Clone PaddleNLP仓库,训练/微调/对齐/量化的脚本都在仓库的llm/目录下 |
| 23 | +git clone https://github.com/PaddlePaddle/PaddleNLP.git |
| 24 | +``` |
| 25 | + |
| 26 | +## 2. 数据准备 |
| 27 | +大模型的预训练任务目标是让模型学习语言的结构和语义,因此数据通常是大规模的自然语言文本,如: |
| 28 | +* 新闻、小说、百科 |
| 29 | + |
| 30 | +* 网络论坛、问答内容 |
| 31 | + |
| 32 | +这里的训练数据与我们常见的<数据,标签>的监督学习所用的数据并不相同。我们使用[OpenWebTextCorpus](https://skylion007.github.io/OpenWebTextCorpus/)作为本次预训练的数据。 |
| 33 | + |
| 34 | +以[PaddleNLP 预训练数据流程](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm/tools/preprocess)中的样例分析: |
| 35 | + |
| 36 | +``` |
| 37 | +飞桨是功能完备、开源开放的产业级深度学习平台。 |
| 38 | +飞桨拥有核心训练和推理框架、基础模型库。 |
| 39 | +PaddleNLP是自然语言处理领域的优秀工具。 |
| 40 | +``` |
| 41 | +大模型的预训练数据就是这样的自然语言文本。大模型的预训练是一种无监督训练,基本的思想是根据之前的词语来预测下一个词,以第一句举例: |
| 42 | +``` |
| 43 | +(输入)飞桨是功能完备、开源开放的产业级深度学习 -> (输出)平台 |
| 44 | +``` |
| 45 | +不需要额外的标注数据。 |
| 46 | + |
| 47 | +我们通过下面的命令下载已经预处理过的数据。 |
| 48 | + |
| 49 | + |
| 50 | +```python |
| 51 | +# llama 模型数据下载 |
| 52 | +wget https://bj.bcebos.com/paddlenlp/models/transformers/llama/data/llama_openwebtext_100k.bin |
| 53 | +wget https://bj.bcebos.com/paddlenlp/models/transformers/llama/data/llama_openwebtext_100k.idx |
| 54 | +``` |
| 55 | + |
| 56 | + |
| 57 | +```python |
| 58 | +mkdir data |
| 59 | +mv llama_openwebtext_100k.bin ./data |
| 60 | +mv llama_openwebtext_100k.idx ./data |
| 61 | +``` |
| 62 | + |
| 63 | +### 数据处理 |
| 64 | +我们下载的数据是经过处理的数据,虽然我们本次不需要自己处理,但是可以简单了解一下数据的格式。 |
| 65 | +* 原始数据:用换行符隔开的句子。 |
| 66 | +* json/jsonl:两者区别是 jsonl 是每行一个句子,json 完整格式相对复杂一些。```{"text": "PaddleNLP是自然语言..."}``` |
| 67 | +* 分词(可选):```PaddleNLP 是 自然语言处理领域 的 优秀工具。``` |
| 68 | +* 转换为 ID:每个词会转换为一个数字 ID,最终形成一个 mmap(memory-mapped file)文件。bin 的二进制文件里面是所有文本的数字 ID,idx 文件里面是每句话的起始位置。 |
| 69 | + |
| 70 | +详细数据处理可以参考[PaddleNLP 预训练数据流程](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm/tools/preprocess)。 |
| 71 | + |
| 72 | +## 3. 模型训练 |
| 73 | +PaddleNLP 实现了一个对常用开源大模型便捷的预训练方式,本次我们使用 Qwen2.5-0.5B 进行实验。从 PaddleNLP 支持的[模型列表](https://paddlenlp.readthedocs.io/zh/latest/llm/docs/pretrain.html#model-weight)将制定模型配置文件作为参数输入训练脚本即可开展训练。 |
| 74 | + |
| 75 | + |
| 76 | +```python |
| 77 | +# 16G 显存可训练 |
| 78 | +python -u ~/PaddleNLP/llm/run_pretrain.py ~/PaddleNLP/llm/config/qwen/pretrain_argument_0p5b.json |
| 79 | +``` |
| 80 | + |
| 81 | +看到下面的提示说明已经开始进行训练了: |
| 82 | +``` |
| 83 | +[2025-05-18 10:13:15,353] [ INFO] - loss: 12.0635252, learning_rate: 2e-06, global_step: 1, current_memory_allocated: 7.549170255661011, current_memory_reserved: 7.753237724304199, max_memory_allocated: 7.549170255661011, max_memory_reserved: 7.753237724304199, interval_runtime: 1.1518, interval_samples_per_second: 0.8682, interval_tokens_per_second_per_device: 889.0448, interval_hardware_tflops_per_device: 2.77, interval_steps_per_second: 0.8682, progress_or_epoch: 0.0 |
| 84 | +[2025-05-18 10:13:15,607] [ INFO] - loss: 12.05887604, learning_rate: 3e-06, global_step: 2, current_memory_allocated: 7.549170255661011, current_memory_reserved: 12.4834623336792, max_memory_allocated: 12.307440280914307, max_memory_reserved: 12.4834623336792, interval_runtime: 0.2556, interval_samples_per_second: 3.913, interval_tokens_per_second_per_device: 4006.9441, interval_hardware_tflops_per_device: 12.49, interval_steps_per_second: 3.913, progress_or_epoch: 0.0 |
| 85 | +``` |
| 86 | + |
| 87 | +### FAQ1:显存不足 |
| 88 | +如果在训练时候看到类似的错误信息: |
| 89 | +``` |
| 90 | +RuntimeError: CUDA out of memory. ...... |
| 91 | +``` |
| 92 | + |
| 93 | +说明训练所需的显存超过了当前显卡提供的最大显存,说明此时我们无法按照默认设置进行单卡训练,解决方式有如下几种: |
| 94 | +* 更换拥有更大显存的显卡 |
| 95 | +* 使用模型量化或一些机制来节省显存 |
| 96 | +* 多卡并行训练 |
| 97 | + |
| 98 | +我们重点介绍一下除了更换显卡之外的另外两种解决方案。 |
| 99 | + |
| 100 | +### 3.1 节省显存 |
| 101 | +#### 模型量化 |
| 102 | +模型量化(Quantization)是指将模型中的权重和激活值从高精度(如 FP32)压缩为低精度(如 INT8 或 FP16),以减小模型大小、加快推理速度、降低内存/显存占用。这部分将在模型量化的指南当中进行介绍。 |
| 103 | + |
| 104 | +#### 其他机制 |
| 105 | +在模型的 config 文件中,修改以下参数: |
| 106 | +``` |
| 107 | + "use_flash_attention": false, |
| 108 | + "use_fused_rms_norm": false, |
| 109 | + ...... |
| 110 | + "recompute": false, |
| 111 | +``` |
| 112 | + |
| 113 | +**注意:** |
| 114 | +1. Flash attention 对于显卡的硬件架构有要求,需要在 V100、H100等显卡上面才能开启,建议使用 cuda11.8及以上环境; |
| 115 | +2. use_fused_rms_norm 需要安装自定义算子。如果安装后仍然找不到算子,需要额外设置 PYTHONPATH。 |
| 116 | + |
| 117 | +### 3.2 高性能/多卡/多机训练 |
| 118 | +单张显卡的显存/性能不足可以通过多卡的并行来进行解决,我们常见的大模型也是在很多张显卡上面进行并行训练的。飞桨大模型套件支持4D 并行,在实际使用上也很便捷。相比于单卡训练,主要的区别在于输入了多张显卡的编号。 |
| 119 | + |
| 120 | + |
| 121 | +```python |
| 122 | +# 编译自定义算子,可选 |
| 123 | +cd ../slm/model_zoo/gpt-3/external_ops/ && python3 setup.py install && cd - |
| 124 | +# 多卡模型预训练参考: |
| 125 | +python -u -m paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" run_pretrain.py ./config/llama/pretrain_argument.json |
| 126 | +# 多机训练参考: 占用45G显存左右 |
| 127 | +python -u -m paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" --master=192.168.1.1:8090 --nnodes=2 run_pretrain.py ./config/llama/pretrain_argument.json |
| 128 | + |
| 129 | +``` |
| 130 | + |
| 131 | +### 3.3 训练结果 |
| 132 | +当训练结束时,可以看到下面的输出: |
| 133 | +``` |
| 134 | +[2025-05-18 10:49:13,774] [ INFO] - Saving model checkpoint to ./checkpoints/pretrain_ckpts |
| 135 | +[2025-05-18 10:49:13,775] [ INFO] - tokenizer config file saved in ./checkpoints/pretrain_ckpts/tokenizer_config.json |
| 136 | +[2025-05-18 10:49:13,776] [ INFO] - Special tokens file saved in ./checkpoints/pretrain_ckpts/special_tokens_map.json |
| 137 | +[2025-05-18 10:49:13,776] [ INFO] - added tokens file saved in ./checkpoints/pretrain_ckpts/added_tokens.json |
| 138 | +[2025-05-18 10:49:13,803] [ WARNING] - Asynchronous saving is not supported for single card environment currently. |
| 139 | +[2025-05-18 10:49:15,691] [ INFO] - Configuration saved in ./checkpoints/pretrain_ckpts/config.json |
| 140 | +[2025-05-18 10:49:15,694] [ INFO] - Configuration saved in ./checkpoints/pretrain_ckpts/generation_config.json |
| 141 | +[2025-05-18 10:49:15,695] [ INFO] - ***** train metrics ***** |
| 142 | +[2025-05-18 10:49:15,695] [ INFO] - progress_or_epoch = 0.0868 |
| 143 | +[2025-05-18 10:49:15,695] [ INFO] - train_loss = 5.4334 |
| 144 | +[2025-05-18 10:49:15,695] [ INFO] - train_runtime = 0:35:59.57 |
| 145 | +[2025-05-18 10:49:15,696] [ INFO] - train_samples_per_second = 4.6305 |
| 146 | +[2025-05-18 10:49:15,696] [ INFO] - train_steps_per_second = 4.6305 |
| 147 | +[2025-05-18 10:49:15,697] [ INFO] - ***** Running Prediction ***** |
| 148 | +[2025-05-18 10:49:15,697] [ INFO] - Num examples = 258 |
| 149 | +[2025-05-18 10:49:15,697] [ INFO] - Total prediction steps = 129 |
| 150 | +[2025-05-18 10:49:15,697] [ INFO] - Pre device batch size = 2 |
| 151 | +[2025-05-18 10:49:15,697] [ INFO] - Total Batch size = 2 |
| 152 | +[2025-05-18 10:49:28,420] [ INFO] - ***** test metrics ***** |
| 153 | +[2025-05-18 10:49:28,420] [ INFO] - test_loss = 4.8691 |
| 154 | +[2025-05-18 10:49:28,420] [ INFO] - test_runtime = 0:00:12.72 |
| 155 | +[2025-05-18 10:49:28,420] [ INFO] - test_samples_per_second = 20.2781 |
| 156 | +[2025-05-18 10:49:28,420] [ INFO] - test_steps_per_second = 10.1391 |
| 157 | +Effective Tokens per second: 4741.68 |
| 158 | +ips: 4741.68 tokens/s |
| 159 | +``` |
| 160 | +说明我们已经成功训练并且将训练后的模型参数进行了保存,在 ```checkpoints/pretrain_ckpts```目录下。我们可以简单浏览一下目录,看看预训练后的模型文件是什么样子。 |
| 161 | + |
| 162 | + |
| 163 | +```python |
| 164 | +ls -l checkpoints/pretrain_ckpts/ |
| 165 | +``` |
| 166 | + |
| 167 | +| 分类 | 代表文件 | 作用 | |
| 168 | +| ----------- | --------------------------------------------------- | -------------------- | |
| 169 | +| 模型结构 | `config.json` | 定义模型维度、层数等超参数 | |
| 170 | +| 模型权重 | `model-*.safetensors` + index 文件 | 保存 Transformer 模型的参数 | |
| 171 | +| 分词器 | `vocab.json`, `merges.txt`, `tokenizer_config.json` | 定义 tokenizer 行为和词表 | |
| 172 | +| 特殊 token 信息 | `added_tokens.json`, `special_tokens_map.json` | 管理新增或特殊 token | |
| 173 | +| 训练状态 | `trainer_state.json`, `training_args.bin` | 记录训练进度和参数 | |
| 174 | +| 评估结果 | `all_results.json`, `train_results.json` | 保存训练评估指标结果 | |
| 175 | +| TensorBoard | `runs/` | 可视化训练曲线 | |
| 176 | +| 检查点 | `checkpoint-*/` | 每 N 步保存的快照 | |
0 commit comments