forked from jiuyuan/CPM-9G-8B
fix single dataset error with exhaust
This commit is contained in:
parent
ff4f028c21
commit
441c79f807
|
@ -618,6 +618,9 @@ class MixedIndexedDataset(torch.utils.data.IterableDataset):
|
||||||
self.tasks[idx].exhaust = True
|
self.tasks[idx].exhaust = True
|
||||||
self.remain -= 1
|
self.remain -= 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if step % self.update_weights_frequency == 0:
|
||||||
|
self.update_weights()
|
||||||
step += 1
|
step += 1
|
||||||
return dict(
|
return dict(
|
||||||
task_id=idx,
|
task_id=idx,
|
||||||
|
|
|
@ -603,8 +603,6 @@ class MixedIndexedDataset(torch.utils.data.IterableDataset):
|
||||||
idx = np.random.choice(len(self.weights), p=self.weights)
|
idx = np.random.choice(len(self.weights), p=self.weights)
|
||||||
|
|
||||||
data = next(self.tasks[idx])
|
data = next(self.tasks[idx])
|
||||||
if step % self.update_weights_frequency == 0:
|
|
||||||
self.update_weights()
|
|
||||||
if data is None:
|
if data is None:
|
||||||
if self.tasks[idx].allow_repeat:
|
if self.tasks[idx].allow_repeat:
|
||||||
# _runtime_ave = self.tasks[idx].ave_tokens
|
# _runtime_ave = self.tasks[idx].ave_tokens
|
||||||
|
@ -619,6 +617,9 @@ class MixedIndexedDataset(torch.utils.data.IterableDataset):
|
||||||
self.tasks[idx].exhaust = True
|
self.tasks[idx].exhaust = True
|
||||||
self.remain -= 1
|
self.remain -= 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if step % self.update_weights_frequency == 0:
|
||||||
|
self.update_weights()
|
||||||
step += 1
|
step += 1
|
||||||
|
|
||||||
return dict(
|
return dict(
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -1,317 +0,0 @@
|
||||||
# 九格大模型使用文档
|
|
||||||
## 目录
|
|
||||||
- [环境配置](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#环境配置)
|
|
||||||
- [开源模型](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#开源模型)
|
|
||||||
- [数据构建](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#数据构建)
|
|
||||||
- [模型训练](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#模型训练)
|
|
||||||
- [模型推理](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#模型推理)
|
|
||||||
- [多机训练](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_DISTRIBUTED.md)
|
|
||||||
- [FAQs](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#FAQs)
|
|
||||||
|
|
||||||
帮助您快速了解CPM-9G的使用,我们准备了一个快速入门教程,目标是基于CPM-9G基座模型通过指令微调的方式构建一个Chat模型。
|
|
||||||
## 环境配置:
|
|
||||||
[环境配置、算力资源](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ENV.md)
|
|
||||||
|
|
||||||
## 开源模型
|
|
||||||
1 8B的百亿SFT模型,v2版本是在v1基础上精度和对话能力的优化模型,下载链接:
|
|
||||||
[8b_sft_model_v1](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/checkpoints-epoch-1.tar.gz), [8b_sft_model_v2](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/sft_8b_v2.zip)
|
|
||||||
|
|
||||||
2 端侧2B模型,下载链接:
|
|
||||||
[2b—sft-model]
|
|
||||||
|
|
||||||
|
|
||||||
## 数据构建
|
|
||||||
|
|
||||||
本教程使用的数据是Alpaca Zh,一个开源中文指令微调数据集。[数据集](https://github.com/Instruction-Tuning-with-GPT-4/GPT-4-LLM/blob/main/data/alpaca_gpt4_data_zh.json)
|
|
||||||
|
|
||||||
### 数据预处理
|
|
||||||
#### 1. 准备jsonl文件
|
|
||||||
首先需要将原始数据处理位jsonl形式(每一行一个json),每行包含两个字段,分别是input和output,以下是一个例子:
|
|
||||||
{"input":"", "output": "我爱北京。"}实际预训练时,数据多为txt格式,可以参照以下过程将txt格式的文件转换为jsonl格式:
|
|
||||||
``` python
|
|
||||||
# convert_txt2jsonl.py
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
|
|
||||||
for line in sys.stdin:
|
|
||||||
if line.strip() == "":
|
|
||||||
continue
|
|
||||||
temp_json = {"input": "", "output": line.strip()}
|
|
||||||
print(json.dumps(temp_json, ensure_ascii=False))
|
|
||||||
```
|
|
||||||
使用方式为:
|
|
||||||
```js
|
|
||||||
cat pretrain.txt | python convert_txt2jsonl.py > pretrain.jsonl
|
|
||||||
```
|
|
||||||
在本Quick Start教程中,已准备好jsonl数据,路径为raw_data/alpaca_zh.jsonl,示例如下:
|
|
||||||
```json
|
|
||||||
{"input": "<用户>保持健康的三个提示。<AI>", "output": "以下是保持健康的三个提示:\n\n1. 保持身体活动。每天做适当的身体运动,如散步、跑步或游泳,能促进心血管健康,增强肌肉力量,并有助于减少体重。\n\n2. 均衡饮食。每天食用新鲜的蔬菜、水果、全谷物和脂肪含量低的蛋白质食物,避免高糖、高脂肪和加工食品,以保持健康的饮食习惯。\n\n3. 睡眠充足。睡眠对人体健康至关重要,成年人每天应保证 7-8 小时的睡眠。良好的睡眠有助于减轻压力,促进身体恢复,并提高注意力和记忆力。"}
|
|
||||||
{"input": "<用户>三原色是什么?<AI>", "output": "三原色通常指的是红色、绿色和蓝色(RGB)。它们是通过加色混合原理创建色彩的三种基础颜色。在以发光为基础的显示设备中(如电视、计算机显示器、智能手机和平板电脑显示屏), 三原色可混合产生大量色彩。其中红色和绿色可以混合生成黄色,红色和蓝色可以混合生成品红色,蓝色和绿色可以混合生成青色。当红色、绿色和蓝色按相等比例混合时,可以产生白色或灰色。\n\n此外,在印刷和绘画中,三原色指的是以颜料为基础的红、黄和蓝颜色(RYB)。这三种颜色用以通过减色混合原理来创建色彩。不过,三原色的具体定义并不唯一,不同的颜色系统可能会采用不同的三原色。"}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 数据二进制化
|
|
||||||
为了提升数据读取的效率,方便进行大规模分布式预训练,我们以二进制的形式读取训练数据。因此,在训练开始前,需要将上一步准备好的jsonl格式的数据文件二进制化,需要的代码路径为quick_start/data_binarize.py,使用前需要将环境变量设置为您的本地路径:
|
|
||||||
```js
|
|
||||||
sys.path.insert(0, "/data/public/CPM-9G/9G-Train")
|
|
||||||
```
|
|
||||||
以下是一个使用示例:
|
|
||||||
假设当前的数据在raw_data路径下:raw_data/alpaca_zh.jsonl
|
|
||||||
```js
|
|
||||||
python data_binarize.py --input [PATH to raw_data] --data_type json --output_path [PATH to raw_data_bin] --output_name data
|
|
||||||
```
|
|
||||||
处理完成后,在输出路径(即OUTPUT PATH)下会生成data和meta.bin两个文件,其中data是二进制后的数据文件,meta.bin则记录了这份数据的规模、大小等信息,示例如下:
|
|
||||||
```js
|
|
||||||
{"file_name": "data", "block_begin": 0, "block_end": 45, "nbytes": 738321350, "nlines": 4432310, "mask": false, "block_size": 16777216}
|
|
||||||
```
|
|
||||||
**请注意,当前的框架需要保证block_end数大于所用的GPU总数。**
|
|
||||||
例如,用32卡训练时,需满足block_end>32,如果文件较小,可以在二进制化之前对多个小文件进行拼接,以满足大规模训练的需求。
|
|
||||||
|
|
||||||
在本Quick Start中,我们为jsonl数据到二进制数据的转换过程准备了脚本:
|
|
||||||
``` python
|
|
||||||
for i in {1..10};do
|
|
||||||
cat raw_data/alpaca_zh.jsonl >> raw_data/alpaca_zh_repeat.jsonl
|
|
||||||
done
|
|
||||||
```
|
|
||||||
``` shell
|
|
||||||
mkdir raw_data_repeat
|
|
||||||
mv raw_data/alpaca_zh_repeat.jsonl raw_data_repeat/data.jsonl
|
|
||||||
|
|
||||||
python data_binarize.py --input raw_data_repeat --data_type json --output_path bin_data_repeat --output_name data
|
|
||||||
```
|
|
||||||
#### 3. 准备数据读取脚本
|
|
||||||
鉴于不同的预训练数据所包含的字段可能有所差别,我们还兼容了字段转换的环节,如果按照上述标准流程做的数据预处理,那么转换方式将十分简单,代码如下:
|
|
||||||
```js
|
|
||||||
# transform_script.py
|
|
||||||
import random
|
|
||||||
|
|
||||||
def rand(n: int, r: random.Random):
|
|
||||||
return int(r.random() * n)
|
|
||||||
|
|
||||||
def transform(data, num_sample: int, r: random.Random):
|
|
||||||
return {"input": data["input"], "output": data["output"]}我们还支持多个数据集的混合读入,并设置不同数据集的比例。为此,需要准备一个数据混合的json文件,来指导训练过程中的数据读取策略,示例如下:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"dataset_name": "alpaca_zh",
|
|
||||||
"task_name": "alpaca_zh",
|
|
||||||
"weight": 1.0,
|
|
||||||
"path": "/data/public/CPM-9G/quick_start/bin_data_repeat",
|
|
||||||
"incontext_weight": [
|
|
||||||
1.0
|
|
||||||
],
|
|
||||||
"transforms": "/data/public/CPM-9G/quick_start/transform_data.py"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
该文件中各字段的解释如下:
|
|
||||||
- dataset_name:数据集名称;
|
|
||||||
- task_name:数据集所属任务,task_name+dataset_name 将作为训练过程中识别数据集的标签,task_name 则可用于训练过程中针对任务分别汇总 loss 信息、token 吞吐量等;
|
|
||||||
- weight:浮点数,采样权重;(注意此权重仅代表每个数据集的样本数配比,实际 token 吞吐量的配比还与每个样本的平均 token数量有关)
|
|
||||||
- path:meta.bin、二进制数据的父目录,即前文所述的 raw_data_bin;
|
|
||||||
- transforms:数据转换脚本对应的路径;
|
|
||||||
- incontext_weight: 训练样本叠加方式,[1.0] 表示 100% 的概率采样一个样本,[0.8, 0.2] 表示 80% 的概率采样一个样本, 20% 概率采样两个样本进行拼接,[0.75, 0.1, 0.15] 表示 15% 概率采样三个样本、 10% 的概率采样两个样本进行拼接、75% 采样一个样本;
|
|
||||||
- 数据集的配比(即 weight 参数)需要重点调整,对于模型的训练稳定性和最终在各类数据上的能力表现有重大影响;
|
|
||||||
- 我们在此文件中指定了数据文件的路径、转换脚本路径等信息,后续训练仅需要系统该文件的路径即可。
|
|
||||||
|
|
||||||
## 模型训练
|
|
||||||
模型训练列举了三种训练
|
|
||||||
- [pretrain训练](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#pretrain训练)
|
|
||||||
- [SFT全参数微调训练](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md?tab=readme-ov-file#SFT全参数微调训练)
|
|
||||||
- [LoRA微调训练](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_LORA.md)
|
|
||||||
|
|
||||||
### pretrain训练:
|
|
||||||
模型训练代码的位置:9G-Train/apps/cpm9g/pretrain_cpm9g.py
|
|
||||||
需要将代码中环境变量设置为您的代码路径:
|
|
||||||
``` python
|
|
||||||
#9G-Train/apps/cpm9g/pretrain_cpm9g.py:17
|
|
||||||
sys.path.insert(0, "/data/public/CPM-9G/9G-Train")
|
|
||||||
```
|
|
||||||
|
|
||||||
```shell
|
|
||||||
#! /bin/bash
|
|
||||||
|
|
||||||
# use 8 GPU for example, pretrain may need 32 GPU
|
|
||||||
export MASTER_ADDR=`hostname`
|
|
||||||
export MASTER_PORT=12345
|
|
||||||
|
|
||||||
EXP_PATH=. # 修改为您的实验路径,用于存储训练日志和模型
|
|
||||||
CODE_PATH=/data/public/CPM-9G/9G-Train # 修改为您的代码路径
|
|
||||||
DATA_PATH=/data/public/CPM-9G/quick_start/datasets.json # 修改为您的datasets.json路径
|
|
||||||
CHECKPOINT=/data/public/CPM-9G/models/model.pt # 修改为您的基座模型路径
|
|
||||||
|
|
||||||
mkdir -p ${EXP_PATH}/logs/debug
|
|
||||||
mkdir -p ${EXP_PATH}/logs/tensorboard/cpm9g/
|
|
||||||
CONFIG_NAME="${CODE_PATH}/apps/cpm9g/config/"
|
|
||||||
# --------------- 运行参数 ---------------
|
|
||||||
OPTS=""
|
|
||||||
OPTS+=" --model-config ${CONFIG_NAME}/config.json"
|
|
||||||
OPTS+=" --vocab ${CONFIG_NAME}/vocab.txt"
|
|
||||||
OPTS+=" --batch-size 12"
|
|
||||||
OPTS+=" --train-iters 2000" # 训练步数,达到此步数后,学习率降到最小值
|
|
||||||
OPTS+=" --save-iters 100" # 存储步数,每隔此步数,存储一个模型文件
|
|
||||||
OPTS+=" --save-name cpm9g_checkpoint" # 模型名称前缀
|
|
||||||
OPTS+=" --max-length 4096" # 最多token数量
|
|
||||||
OPTS+=" --lr 1.5e-5" # 峰值学习率
|
|
||||||
OPTS+=" --inspect-iters 100" # 检查步数,每隔此步数,输出一次模型梯度的详细信息
|
|
||||||
OPTS+=" --warmup-iters 50" # 热启动步数
|
|
||||||
OPTS+=" --lr-decay-style noam" # 学习率变化策略
|
|
||||||
OPTS+=" --weight-decay 0.1" # 正则化参数
|
|
||||||
OPTS+=" --clip-grad 1.0" # 正则化参数
|
|
||||||
OPTS+=" --loss-scale 1048576" # 和训练稳定性相关,一般情况下不需修改
|
|
||||||
OPTS+=" --loss-scale-steps 32" # 和训练稳定性相关,一般情况下不需修改
|
|
||||||
OPTS+=" --offload" # 使用cpu offload将优化器参数转移到cpu,一般情况下无需修改
|
|
||||||
OPTS+=" --flash cuda"
|
|
||||||
|
|
||||||
# --------------- 写文件路径 ---------------
|
|
||||||
OPTS+=" --save ${EXP_PATH}/checkpoints/cpm9g/"
|
|
||||||
OPTS+=" --save-model ${EXP_PATH}/models/cpm9g/"
|
|
||||||
|
|
||||||
OPTS+=" --log-dir ${EXP_PATH}/logs/train/"
|
|
||||||
OPTS+=" --tensorboard ${EXP_PATH}/tensorboard/cpm9g/"`date +"%Y%m%d%H%M%S"`
|
|
||||||
|
|
||||||
# --------------- 读文件路径 ---------------
|
|
||||||
OPTS+=" --dataset ${DATA_PATH}"
|
|
||||||
OPTS+=" --load ${CHECKPOINT}"
|
|
||||||
OPTS+=" --start-step 1"
|
|
||||||
|
|
||||||
# --------------- 透传参数 ---------------
|
|
||||||
OPTS+=" $@"
|
|
||||||
|
|
||||||
# --------------- 最终指令 ---------------
|
|
||||||
CMD="torchrun --nnodes=1 --nproc_per_node=8 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} ${CODE_PATH}/apps/cpm9g/pretrain_cpm9g.py ${OPTS}"
|
|
||||||
echo "${CMD}"
|
|
||||||
$CMD
|
|
||||||
```
|
|
||||||
|
|
||||||
### SFT全参数微调训练
|
|
||||||
``` shell
|
|
||||||
export MASTER_ADDR=`hostname`
|
|
||||||
export MASTER_PORT=12345
|
|
||||||
|
|
||||||
CPM_PATH="/data/groups/QY_LLM_Core/arq_project/code/9G-Train"
|
|
||||||
CKPT_NAME="/data/public/anrongqiao/models/"
|
|
||||||
EXP_PATH=./exp/8b/
|
|
||||||
|
|
||||||
mkdir -p $EXP_PATH
|
|
||||||
MODEL_NAME="cpm9g-8b-sft"
|
|
||||||
|
|
||||||
OPTS=""
|
|
||||||
OPTS+=" --model-config ${CKPT_NAME}/config.json"
|
|
||||||
OPTS+=" --vocab ${CKPT_NAME}/vocab.txt"
|
|
||||||
|
|
||||||
OPTS+=" --train-iters 10000" # 训练步数,达到此步数后,学习率降到最小值
|
|
||||||
OPTS+=" --inspect-iters 200" # 存储步数,每隔此步数,存储一个模型文件
|
|
||||||
OPTS+=" --warmup-iters 20" # 热启动步数
|
|
||||||
|
|
||||||
OPTS+=" --lr-decay-style cosine" # 学习率变化策略
|
|
||||||
OPTS+=" --weight-decay 0.1" # 正则化参数
|
|
||||||
OPTS+=" --clip-grad 1.0" # 正则化参数
|
|
||||||
OPTS+=" --loss-scale 1048576" # 和训练稳定性相关,一般情况下不需修改
|
|
||||||
OPTS+=" --max-loss-scale 33554432" #和训练稳定性相关,一般情况下不需修改
|
|
||||||
OPTS+=" --min-loss-scale 1" #和训练稳定性相关,一般情况下不需修改
|
|
||||||
OPTS+=" --loss-scale-steps 32" # 和训练稳定性相关,一般情况下不需修改
|
|
||||||
|
|
||||||
OPTS+=" --offload" # 使用cpu offload将优化器参数转移到cpu,一般情况下无需修改
|
|
||||||
OPTS+=" --batch-size 1"
|
|
||||||
OPTS+=" --max-length 4096" #上下文长度
|
|
||||||
OPTS+=" --lr 1e-5" #学习率
|
|
||||||
OPTS+=" --start-step 0" #初始steps
|
|
||||||
OPTS+=" --epoch 1" # 训练多少个epoch
|
|
||||||
|
|
||||||
OPTS+=" --load ${CKPT_NAME}/model.pt" # 修改成自己的预训练模型
|
|
||||||
OPTS+=" --dataset ../dataset/qy_sft_20230129_bin/" # 和pretrain脚本不同,sft数据量少,直接输入bin文件即可
|
|
||||||
OPTS+=" --save ${EXP_PATH}/checkpoints" # 模型存储
|
|
||||||
OPTS+=" --save-name ${MODEL_NAME}" #待存储模型的前缀
|
|
||||||
OPTS+=" --tensorboard /data/logs/tensorboard/${MODEL_NAME}/${CUR_DATE}/" #
|
|
||||||
OPTS+=" --gradient-accumulation-steps 4" # 梯度累积更新步数
|
|
||||||
OPTS+=" $@"
|
|
||||||
|
|
||||||
#运行指令
|
|
||||||
CMD="torchrun --nnodes=1 --nproc_per_node=8 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} ${CPM_PATH}/apps/cpm9g/sft_cpm9g.py ${OPTS}"
|
|
||||||
echo "${CMD}"
|
|
||||||
$CMD
|
|
||||||
```
|
|
||||||
|
|
||||||
## 模型推理
|
|
||||||
```python
|
|
||||||
import os
|
|
||||||
|
|
||||||
from libcpm import CPM9G
|
|
||||||
|
|
||||||
import argparse, json, os
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("--pt", type=str, help="the path of ckpt")
|
|
||||||
parser.add_argument("--config", type=str, help="the path of config file")
|
|
||||||
parser.add_argument("--vocab", type=str, help="the path of vocab file")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
model_config = json.load(open(args.config, 'r'))
|
|
||||||
model_config["new_vocab"] = True
|
|
||||||
|
|
||||||
model = CPM9G(
|
|
||||||
"",
|
|
||||||
args.vocab,
|
|
||||||
-1,
|
|
||||||
memory_limit = 30 << 30,#memory limit 左边的参数根据gpu的显存设置,如果是A100,可以设置为 72 << 30,这样的话就可以用到更多的显存
|
|
||||||
model_config=model_config,
|
|
||||||
load_model=False,
|
|
||||||
)
|
|
||||||
model.load_model_pt(args.pt)
|
|
||||||
|
|
||||||
datas = [
|
|
||||||
'''<用户>马化腾是谁?<AI>''',
|
|
||||||
'''<用户>你是谁?<AI>''',
|
|
||||||
'''<用户>我要参加一个高性能会议,请帮我写一个致辞。<AI>''',
|
|
||||||
]
|
|
||||||
|
|
||||||
for data in datas:
|
|
||||||
res = model.inference(data, max_length=4096)
|
|
||||||
print(res['result'])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
## FAQs
|
|
||||||
|
|
||||||
常见问题汇总,持续补充ing
|
|
||||||
|
|
||||||
### 训练相关
|
|
||||||
1 推荐大家使用docker,避免大家在conda 环境安装时候遇到的问题
|
|
||||||
2 pretrain训练的脚本和sft训练的脚本基本类似,在apps/cpm_9g目录下
|
|
||||||
3 尽量避免在window机器下修改脚本,window中的编码和格式linux是有差别的,容易在脚本执行中报错
|
|
||||||
4 SFT如何调参训练
|
|
||||||
```
|
|
||||||
回答:如果数据量少于10w条,全参数微调的时候多训练几个epoch,把学习率调低一些,比如说5e-6等;更建议使用lora 微调的方式
|
|
||||||
数据量很多呢,比如说达到百万级别,那可以选择全参数微调,但训练最多2个epoch足够,注意过拟合的问题
|
|
||||||
```
|
|
||||||
5 微调训练中,train_iters如何计算?
|
|
||||||
```
|
|
||||||
回答:因为模型上下文是4096的token数目,通常情况存在训练数据不足4096的长度,所以会对多条数据进行merge,因此送入模型条数要少于实际的数据条数
|
|
||||||
```
|
|
||||||
6 打印出来的Iter信息有缺失
|
|
||||||
```
|
|
||||||
回答:debug下看看是否是出现drop_last的情况
|
|
||||||
```
|
|
||||||
7 现有代码是否需要验证集合?
|
|
||||||
```
|
|
||||||
回答:不需要,参数中出现的val_datasets忽略即可
|
|
||||||
```
|
|
||||||
8 加载模型遇到:invalid header or archive is carrupted,这种一般是模型没有下载完导致的,目前红山上的模型确定是完整的,首先自查自己的模型是否下载成功。
|
|
||||||
9 存储模型的时候遇到failed write file data ,一般先检查下文件路径和权限、磁盘空间吧,存储模型基本不会报错
|
|
||||||
10 是否支持图像模态:
|
|
||||||
```
|
|
||||||
回答:不支持图像模态,仅支持文本模态
|
|
||||||
```
|
|
||||||
### 数据相关
|
|
||||||
1 历史对话的传入:
|
|
||||||
``` json
|
|
||||||
datas = [
|
|
||||||
'''<用户>问题1<AI>答案1<用户>问题2<AI>答案2<用户>问题2<AI>'''
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
1 发布8B-32k上下文的模型
|
|
|
@ -1,124 +0,0 @@
|
||||||
# 分布式多机训练
|
|
||||||
|
|
||||||
|
|
||||||
- 首先保证机器之间能够通信
|
|
||||||
- 每台机器上的训练环境、代码、数据等一致
|
|
||||||
|
|
||||||
## 简单模式
|
|
||||||
这种方式只适用于机器很少的提交方法,比如说两台机器debug调试的时候可以如下操作
|
|
||||||
以sft_cpm9g_8b.sh举例
|
|
||||||
```shell
|
|
||||||
# 这儿指定主节点的IP值
|
|
||||||
export MASTER_ADDR=g3002
|
|
||||||
|
|
||||||
#中间省略各种参数配置
|
|
||||||
|
|
||||||
#--nnodes 指定用几台机器,提交任务后主节点会一直等待通信满足4台机器,直到time out
|
|
||||||
#--nproc_per_node 每张机器多少张卡
|
|
||||||
CMD="torchrun --nnodes=2 --nproc_per_node=8 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} ${CPM_PATH}/apps/cpm9g/sft_cpm9g.py ${OPTS}"
|
|
||||||
```
|
|
||||||
接下来,在这两个机器中都执行bash sft_cpm9g_8b.sh,这样就完成一次最简单的多机训练
|
|
||||||
不过机器多了之后不推荐这种方式
|
|
||||||
|
|
||||||
## slurm 集群多机任务提交
|
|
||||||
|
|
||||||
算力平台使用Slurm调度,常用Slurm命令包括:
|
|
||||||
``` shell
|
|
||||||
Slurm命令 功能
|
|
||||||
sinfo 查看集群分区状态
|
|
||||||
squeue 查看作业队列
|
|
||||||
srun, salloc 交互式运行作业
|
|
||||||
sbatch 提交作业
|
|
||||||
scancel 取消作业
|
|
||||||
scontrol 查看和修改作业参数
|
|
||||||
sacct 查看已完成作业
|
|
||||||
```
|
|
||||||
|
|
||||||
### 单机任务
|
|
||||||
参考脚本
|
|
||||||
前面"#SBATCH"是Slurm配置参数,解释如下:
|
|
||||||
``` shell
|
|
||||||
●--partition: 使用的队列名称
|
|
||||||
●--nodes: 节点数量,用多少台机器
|
|
||||||
●--ntasks-per-node:每个节点的进程数,和每节点的GPU数量保持一致
|
|
||||||
●--gres=gpu:8:每个节点分配的GPU数量
|
|
||||||
●--cpus-per-task:每个任务分配的CPU数量(建议不要修改),该节点的cpu总数为任务数乘以每个任务的cpu数,这个示例脚本中的cpu总数为8x8=64
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 具体示例:
|
|
||||||
|
|
||||||
train.sh:
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
#SBATCH --partition=gpu1
|
|
||||||
#SBATCH --nodelist=g1001
|
|
||||||
#SBATCH --nodes=1
|
|
||||||
#SBATCH --ntasks-per-node=8
|
|
||||||
#SBATCH --gres=gpu:8
|
|
||||||
#SBATCH --cpus-per-task=8
|
|
||||||
|
|
||||||
python main.py
|
|
||||||
```
|
|
||||||
|
|
||||||
提交任务
|
|
||||||
```
|
|
||||||
sbatch train.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 多机任务
|
|
||||||
已测试通过torchrun的方式多机训练,需要设置"MASTER_ADDR"和"MASTER_PORT"两个环境变量,先提交一个主节点的任务,获取"MASTER_ADDR",在提交从节点任务。一个4台机器的多机任务的操作示例如下:
|
|
||||||
|
|
||||||
注意:#SBATCH的nodes参数设置为1,slurm的多节点通信与bmtrain的环境变量有冲突,且srun不稳定,推荐采用slurm提交多个单节点任务,用torchrun的方式实现多节点通信。
|
|
||||||
|
|
||||||
##### 第一步:启动主节点
|
|
||||||
train_master.sh:
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
#SBATCH --partition=gpu1
|
|
||||||
#SBATCH --nodes=1
|
|
||||||
#SBATCH --ntasks-per-node=8
|
|
||||||
#SBATCH --gres=gpu:8
|
|
||||||
#SBATCH --cpus-per-task=8
|
|
||||||
MASTER_ADDR=`hostname`
|
|
||||||
MASTER_PORT=12345
|
|
||||||
echo $MASTER_ADDR
|
|
||||||
torchrun --nnodes=4 --nproc_per_node=8 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} train.py
|
|
||||||
```
|
|
||||||
|
|
||||||
提交主节点:
|
|
||||||
```
|
|
||||||
sbatch train_master.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
在输出的log(slurm-xxx.log)中查看主节点的名称,例如此时查到主节点是"g1001"
|
|
||||||
|
|
||||||
##### 第二步:启动从节点
|
|
||||||
train_slave.sh:
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
#SBATCH --partition=gpu1
|
|
||||||
#SBATCH --nodes=1
|
|
||||||
#SBATCH --ntasks-per-node=8
|
|
||||||
#SBATCH --gres=gpu:8
|
|
||||||
#SBATCH --cpus-per-task=8
|
|
||||||
MASTER_ADDR=g1001
|
|
||||||
MASTER_PORT=12345
|
|
||||||
echo $MASTER_ADDR
|
|
||||||
torchrun --nnodes=4 --nproc_per_node=8 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} train.py
|
|
||||||
```
|
|
||||||
|
|
||||||
提交从节点,示例是一个4台机器的任务,因此再提交3个从节点程序
|
|
||||||
```
|
|
||||||
for i in {1..3};do
|
|
||||||
sbatch train_slave.sh
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
## dockers上的多机提交任务
|
|
||||||
dockers 容器上的多机任务和在主机上是相同的,只需要再其基础上满足两个要求
|
|
||||||
- 在每个机器上拉取同样的docker和激活同样的训练环境,在docker共享的路径、数据、代码都一致
|
|
||||||
- 在docker启动的时候保障 --network=host,和主机共享网络通信,只要机器之间能通信,在dockers中也可以通信和训练
|
|
||||||
|
|
||||||
|
|
||||||
#### TODOs
|
|
||||||
1 完善K8s集群的分布式多机任务训练
|
|
|
@ -1,125 +0,0 @@
|
||||||
#环境配置、算力资源
|
|
||||||
|
|
||||||
|
|
||||||
# Docker使用
|
|
||||||
我们提供可以运行模型训练和推理的docker,便于在新环境下快速使用九格大模型。您也可以使用Conda配置运行环境。Conda配置方式请见下一节。
|
|
||||||
#### [docker 路径](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/cpmlive-flash-0.0.4.tar)
|
|
||||||
## 镜像加载
|
|
||||||
### rootless 启动
|
|
||||||
允许用户在不影响主机系统的情况下运行应用程序和服务,并且可以轻松地共享和分发环境
|
|
||||||
```shell
|
|
||||||
srun -p gpu1 --nodelist=g2001 -N 1 -n 8 -c 8 --gres=gpu:8 --pty bash
|
|
||||||
module load rootless-docker/default
|
|
||||||
start_rootless_docker.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
**注意使用bash(不能用zsh)**
|
|
||||||
运行成功的话,此时执行docker ps可以看到当前没有正在运行的容器,如果有正在运行的容器,说明rootless模式没有启动成功,请联系管理员。
|
|
||||||
|
|
||||||
### 加载镜像
|
|
||||||
```shell
|
|
||||||
docker load -i cpmlive-flash-0.0.4.tar
|
|
||||||
docker tag [IMAGE_ID] cpmlive-flash:0.0.4
|
|
||||||
```
|
|
||||||
|
|
||||||
如果加载镜像遇到:archive/tar invailid tar header的问题,是因为docker下载不全,check下docker下载结果。以红山上上传的docker为准
|
|
||||||
|
|
||||||
### 启动容器
|
|
||||||
```
|
|
||||||
docker run -it -d -v [HOST_PATH1]:[DOCKER_PATH1] -v [HOST_PATH2]:[DOCKER_PATH2] --gpus all --shm-size=4g --sh cpmlive-flash:0.0.4 bash
|
|
||||||
```
|
|
||||||
如果有docker权限、且rootless执行错误的情况下,可以尝试下非rootless启动
|
|
||||||
|
|
||||||
## 非rootless 启动
|
|
||||||
### 启动容器
|
|
||||||
```
|
|
||||||
docker run -it -d -v [HOST_PATH1]:[DOCKER_PATH1] -v [HOST_PATH2]:[DOCKER_PATH2] --gpus all --network host --shm-size=4g cpmlive-flash:0.0.4 bash
|
|
||||||
```
|
|
||||||
|
|
||||||
参数解释如下:
|
|
||||||
- -v [HOST_PATH1]:[DOCKER_PATH1]: 这个选项用于将主机(宿主机)文件系统中的目录或文件挂载到容器中的目录。[HOST_PATH1] 是主机路径,[DOCKER_PATH1] 是容器中对应的路径;
|
|
||||||
- --gpus all: 这个选项用于在容器中启用 GPU 支持,并将所有可用的 GPU 分配给容器。需要在 Docker 守护程序中启用 NVIDIA Container Toolkit 才能使用此选项;
|
|
||||||
- --network host: 这个选项用于让容器共享主机网络命名空间,使容器可以直接访问主机上的网络接口和服务;
|
|
||||||
- --shm-size 容器的share memory,根据主机的情况设置,如果训练推理需要的内存比较多,可以增大share memory值;
|
|
||||||
### 进入容器
|
|
||||||
```shell
|
|
||||||
docker exec -it [CONTAINER_ID] bash
|
|
||||||
```
|
|
||||||
### 退出容器
|
|
||||||
```shell
|
|
||||||
Ctrl+d
|
|
||||||
```
|
|
||||||
### 删除容器
|
|
||||||
```shell
|
|
||||||
docker stop [CONTAINER_ID]
|
|
||||||
```
|
|
||||||
### 查看正在运行容器
|
|
||||||
```shell
|
|
||||||
docker ps
|
|
||||||
```
|
|
||||||
### 环境安装
|
|
||||||
```shell
|
|
||||||
pip install tensorboardX
|
|
||||||
```
|
|
||||||
|
|
||||||
## Conda环境配置
|
|
||||||
### 训练环境配置
|
|
||||||
```shell
|
|
||||||
1. 使用python 3.8.10创建conda环境
|
|
||||||
conda create -n cpm-9g python=3.8.10
|
|
||||||
|
|
||||||
2.安装Pytorch
|
|
||||||
conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.6 -c pytorch -c nvidia
|
|
||||||
|
|
||||||
3. 安装BMTrain
|
|
||||||
pip install bmtrain==0.2.3.post2
|
|
||||||
|
|
||||||
4. 安装flash-attn
|
|
||||||
pip install flash-attn==2.0.8
|
|
||||||
|
|
||||||
5. 安装其他依赖包
|
|
||||||
pip install einops
|
|
||||||
pip install pytrie
|
|
||||||
```
|
|
||||||
|
|
||||||
如果需要自己配置conda的训练,供参考的配置:
|
|
||||||
驱动版本:Driver Version: 470.57.02
|
|
||||||
cuda:11.4-11.6之间都可以
|
|
||||||
|
|
||||||
### 推理环境配置
|
|
||||||
```js
|
|
||||||
1. 安装nvidia-nccl
|
|
||||||
pip install nvidia-nccl-cu11==2.19.3
|
|
||||||
|
|
||||||
2. 配置环境变量
|
|
||||||
nccl_root=`python -c "import nvidia.nccl;import os; print(os.path.dirname(nvidia.nccl.__file__))"`
|
|
||||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$nccl_root/lib
|
|
||||||
echo $LD_LIBRARY_PATH2. 安装LibCPM
|
|
||||||
pip installlibcpm-1.0.0-cp38-cp38-linux_x86_64.whl
|
|
||||||
```
|
|
||||||
|
|
||||||
# 算力资源
|
|
||||||
## 推荐配置:
|
|
||||||
### 千亿大模型
|
|
||||||
- 预训练、全参数微调:8 * 512G以上内存,64 * 80G以上显存
|
|
||||||
- 高效微调(LoRA)与推理: 512G 以上内存,8 * 80G以上显存
|
|
||||||
|
|
||||||
### 百亿大模型
|
|
||||||
- 预训练、全参数微调:2 * 512G以上内存,16 * 80G以上显存
|
|
||||||
- 高效微调(LoRA)与推理: 128G 以上内存,2 * 80G以上显存
|
|
||||||
|
|
||||||
## 极限配置
|
|
||||||
最极限的资源配置,仅供参考,在大模型训练中其实并不推荐,因为其效果一般不佳,训练时长也比较久
|
|
||||||
|
|
||||||
| 模型 | 资源 | 最小算力 |
|
|
||||||
| :-------- | :----- | :----: |
|
|
||||||
| 百亿模型 |内存 |训练:140G, 推理:1G|
|
|
||||||
| 百亿模型 |显存 |训练:49G, 推理:20G|
|
|
||||||
| 千亿模型 |内存 |训练: 200G, 推理:2G|
|
|
||||||
| 千亿模型 |显存 |训练: 8*80G , 推理:4 * 50G|
|
|
||||||
|
|
||||||
另外
|
|
||||||
- 该表格是百亿、千亿模型需要的最小的资源,batch size为1.
|
|
||||||
- 百亿模型是在单卡A100上测试
|
|
||||||
- 千亿的训练是用8卡A100,但是训到过程中out of memory,所以建议至少用2台A100或者至少两台
|
|
||||||
- 千亿的推理是用4卡A100训练
|
|
|
@ -1,80 +0,0 @@
|
||||||
# Lora 训练
|
|
||||||
|
|
||||||
## lora 训练脚本
|
|
||||||
|
|
||||||
``` shell
|
|
||||||
#! /bin/bash
|
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
#SBATCH --partition=gpu3
|
|
||||||
#SBATCH --nodes=1
|
|
||||||
#SBATCH --nodelist=g3005
|
|
||||||
#SBATCH --ntasks-per-node=4
|
|
||||||
#SBATCH --gres=gpu:4
|
|
||||||
#SBATCH --cpus-per-task=4
|
|
||||||
#SBATCH --mem=512GB
|
|
||||||
|
|
||||||
export MASTER_ADDR="localhost"
|
|
||||||
export MASTER_PORT=12347
|
|
||||||
|
|
||||||
CPM_PATH="/home/wangxvjia/CPM-onlyllama"
|
|
||||||
EXP_PATH=/home/wangxvjia/9g_models/cpm_fin_new_1e4
|
|
||||||
MODEL_NAME="9g-finance-sft"
|
|
||||||
|
|
||||||
OPTS=""
|
|
||||||
OPTS+=" --vocab /home/wangxvjia/9g_models/vocab.txt"
|
|
||||||
OPTS+=" --model-config /home/wangxvjia/9g_models/config.json"
|
|
||||||
|
|
||||||
OPTS+=" --train-iters 695"
|
|
||||||
OPTS+=" --inspect-iters 2000"
|
|
||||||
OPTS+=" --warmup-iters 20"
|
|
||||||
|
|
||||||
OPTS+=" --lr-decay-style cosine"
|
|
||||||
OPTS+=" --weight-decay 0.01"
|
|
||||||
OPTS+=" --clip-grad 1.0"
|
|
||||||
OPTS+=" --loss-scale 1048576"
|
|
||||||
OPTS+=" --max-loss-scale 33554432"
|
|
||||||
OPTS+=" --min-loss-scale 1"
|
|
||||||
OPTS+=" --loss-scale-steps 32"
|
|
||||||
|
|
||||||
OPTS+=" --offload"
|
|
||||||
OPTS+=" --batch-size 2"
|
|
||||||
OPTS+=" --max-length 4096"
|
|
||||||
OPTS+=" --lr 3e-4"
|
|
||||||
OPTS+=" --start-step 0"
|
|
||||||
OPTS+=" --epoch 4"
|
|
||||||
OPTS+=" --load /data/groups/QY_LLM_Other/anrongqiao/UltraEval/caterpillar_8b_checkpoint-22000-float16.pt"
|
|
||||||
OPTS+=" --dataset /home/wangxvjia/molora/data_process/fin_9g/train_data_30000"
|
|
||||||
# TODO 这些 /data 在启元机器上需要改成 /home 下的路径
|
|
||||||
OPTS+=" --save ${EXP_PATH}/checkpoints"
|
|
||||||
OPTS+=" --save-name ${MODEL_NAME}"
|
|
||||||
|
|
||||||
OPTS+=" --delta-tuning"
|
|
||||||
OPTS+=" --delta-type lora"
|
|
||||||
OPTS+=" --lora-r 64" # 常用的lora 参数
|
|
||||||
OPTS+=" --lora-dropout 0.05"
|
|
||||||
OPTS+=" --lora-alpha 64" # 常用的lora alpha 参数
|
|
||||||
OPTS+=" --lora-layer project_q project_v project_k w_0 w_1 w_out"
|
|
||||||
OPTS+=" --save-origin-model"
|
|
||||||
|
|
||||||
OPTS+=" $@"
|
|
||||||
|
|
||||||
|
|
||||||
CMD="torchrun --nnodes=1 --nproc_per_node=2 --rdzv_id=1 --rdzv_backend=c10d --rdzv_endpoint=${MASTER_ADDR}:${MASTER_PORT} ${CPM_PATH}/apps/cpm9g/sft_cpm9g_delta.py ${OPTS}"
|
|
||||||
|
|
||||||
echo "${CMD}"
|
|
||||||
$CMD
|
|
||||||
```
|
|
||||||
|
|
||||||
## 合并模型
|
|
||||||
- 将lora delta model参数和original model merge在一起 作为新的模型,但是模型的参数数量并没有增多
|
|
||||||
```python
|
|
||||||
python merge_lora_delta.py --base_path cpm9g-8b-sft.pt --delta_path cpm9g-lora.pt --merge_path cpm9g-8b-sft_with_lora.pt
|
|
||||||
```
|
|
||||||
|
|
||||||
# lora 推理
|
|
||||||
|
|
||||||
合并后的lora模型可以直接采用基础模型推理代码
|
|
||||||
见[quick start](https://www.osredm.com/jiuyuan/CPM-9G-8B/tree/master/quick_start_clean/readmes/README_ALL.md)
|
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
``` -->
|
``` -->
|
||||||
|
|
||||||
## 环境配置
|
## 环境配置
|
||||||
|
### conda 环境安装
|
||||||
```shell
|
```shell
|
||||||
1. 使用python 3.8.10创建conda环境
|
1. 使用python 3.8.10创建conda环境
|
||||||
conda create -n fm-9g python=3.8.10
|
conda create -n fm-9g python=3.8.10
|
||||||
|
@ -112,6 +113,27 @@ pip install tensorboardX
|
||||||
[vllm-0.5.0.dev0+cu122-cp310-cp310-linux_x86_64.whl](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/vllm-0.5.0.dev0%2Bcu122-cp310-cp310-linux_x86_64.whl)
|
[vllm-0.5.0.dev0+cu122-cp310-cp310-linux_x86_64.whl](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/vllm-0.5.0.dev0%2Bcu122-cp310-cp310-linux_x86_64.whl)
|
||||||
同时,我们也提供了vllm源码,位于/quick_start_clean/tools/vllm-0.5.0.dev0.tar
|
同时,我们也提供了vllm源码,位于/quick_start_clean/tools/vllm-0.5.0.dev0.tar
|
||||||
```
|
```
|
||||||
|
### docker环境
|
||||||
|
|
||||||
|
我们提供了打包好的镜像,[镜像下载](https://qy-obs-6d58.obs.cn-north-4.myhuaweicloud.com/9g.0.0.13.tar)
|
||||||
|
镜像使用方法:
|
||||||
|
``` shell
|
||||||
|
1 启动镜像权限,有root权限
|
||||||
|
systemctl start docker
|
||||||
|
|
||||||
|
2 加载镜像
|
||||||
|
dockr load -i 9g.0.0.13.tar
|
||||||
|
docker tag 【IMAGE ID】9g:0.0.13
|
||||||
|
|
||||||
|
3 启动镜像
|
||||||
|
docker run -it -d -v [HOST_PATH1]:[DOCKER_PATH1] -v [HOST_PATH2]:[DOCKER_PATH2] --gpus all --shm-size=50g --network host cpmlive-flash:0.0.4 bash
|
||||||
|
|
||||||
|
4 进入镜像:
|
||||||
|
docker exec -it 【CONTAINER ID】 /bin/bash
|
||||||
|
|
||||||
|
5 退出镜像
|
||||||
|
CTRP + d
|
||||||
|
```
|
||||||
|
|
||||||
## 开源模型
|
## 开源模型
|
||||||
1. 8B的百亿SFT模型,v2版本是在v1基础上精度和对话能力的优化模型,下载链接:
|
1. 8B的百亿SFT模型,v2版本是在v1基础上精度和对话能力的优化模型,下载链接:
|
||||||
|
|
Loading…
Reference in New Issue