# Generative Pre-Training2(GPT2)

## 论文

`Language Models are Unsupervised Multitask Learners`

-   https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf

## 模型结构

![gpt2](gpt2.jpg)

```
GPT2使用Transformer的Decoder结构，并对 Transformer Decoder 进行了一些改动。主要在于将归一化层移到Block的输入位置；在最后一个自注意力块之后加了一层归一化；增大词汇量等。
```

## 算法原理

![image-gpt](image-gpt.png)

## 环境配置

### Docker（方式一）

推荐使用docker方式运行，提供[光源](https://www.sourcefind.cn/)拉取的docker镜像：

```
docker pull image.sourcefind.cn:5000/dcu/admin/base/pytorch:1.10.0-centos7.6-dtk-23.04-py37-latest
docker run -dit --network=host --name=gpt2_pytorch --privileged --device=/dev/kfd --device=/dev/dri --ipc=host --shm-size=16G  --group-add video --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -u root --ulimit stack=-1:-1 --ulimit memlock=-1:-1 image.sourcefind.cn:5000/dcu/admin/base/pytorch:1.10.0-centos7.6-dtk-23.04-py37-latest
docker exec -it gpt2_pytorch /bin/bash
pip install -r requirements.txt  -i https://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com
```

### Anaconda（方法二）：

这里以DTK23.04、python3.7，torch1.10为例，进入[光合开发者社区](https://cancon.hpccube.com:65024/4/main/)进入到pytorch->dtk23.04->下载 torch-1.10.0+gite378c3c.abi0.dtk2304-cp37-cp37m-manylinux2014_x86_64.whl。然后可以仿照下边配置环境：

```
#创建虚拟环境
conda create -n venv_gpt2 python=3.7
#进入venv_gpt2虚拟环境
source activate venv_gpt2
#加载DTK以及其他环境设置
source env.sh		
#安装DTK版本依赖
pip install torch-1.10.0+gite378c3c.abi0.dtk2304-cp37-cp37m-manylinux2014_x86_64.whl
pip install deepspeed-0.9.2+git25d5540.abi0.dtk2304.torch1.10.0-cp37-cp37m-manylinux2014_x86_64.whl
pip install apex-0.1+f49ddd4.abi0.dtk2304.torch1.10-cp37-cp37m-manylinux2014_x86_64.whl
pip install torchvision-0.10.0+git48e6bbb.abi0.dtk2304.torch1.10-cp37-cp37m-manylinux2014_x86_64.whl
#安装其他依赖
pip install -r requirements.txt  -i http://pypi.tuna.tsinghua.edu.cn/simple  --trusted-host pypi.tuna.tsinghua.edu.cn
```



## 数据集

`oscar-1GB`

-   https://huggingface.co/bigscience/misc-test-data/resolve/main/stas/oscar-1GB.jsonl.xz
- 或者通过[SCNet](http://113.200.138.88:18080/aidatasets/project-dependency/oscar-1gb/-/raw/master/oscar-1GB.jsonl.xz)下载
```
#下载数据集
# wget https://huggingface.co/bigscience/misc-test-data/resolve/main/stas/oscar-1GB.jsonl.xz
wget http://113.200.138.88:18080/aidatasets/project-dependency/oscar-1gb/-/raw/master/oscar-1GB.jsonl.xz
#下载vocab文件
wget https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-vocab.json
wget https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-merges.txt
xz -d oscar-1GB.jsonl.xz

#处理数据集参数
--input				输入数据集路径，即oscar-1GB.jsonl.xz解压后的文件路径
--output-prefix		输出数据路径，处理后会自动加上_text_document后缀
--vocab				下载的gpt2-vocab.json词表文件路径
--dataset-impl		dataset类型
--tokenizer-type 	tokenizer类型
--merge-file		下载的gpt2-merges.txt文件路径		
--append-eod		添加结束标志符		
--workers			进程数

#处理数据集
sh creat-data.sh
```

```
#处理后的数据集格式
├── my-gpt2_text_document.bin
├── my-gpt2_text_document.idx
└── oscar-1GB.jsonl
```



## 训练

### GPT2单节点训练

```
#np为起的进程数，和使用GPU数量一致，并且TP*PP < np,4卡的话可以设置2tp 2pp，或者1tp 4pp，4tp 1pp，节点内使用TP性能更好

mpirun -np 4 run-one-node.sh（基于单节点四卡）
```

```
#重要参数
MODEL_NAME 					模型名（自定义）
CHECKPOINT_PATH				模型保存&加载路径
DATA_PATH					数据集路径（转换后的）
TENSORBOARD_PATH			tensorboard路径
CODECARBON_PATH				codecarbon路径

N_GPUS         				使用加速卡数量
TP_SIZE  	 				TP数量
PP_SIZE      				PP数量
MICRO_BATCH_SIZE			MICRO_BATCH_SIZE大小
GLOBAL_BATCH_SIZE           GLOBAL_BATCH_SIZE大小
NLAYERS 					模型层数
NHIDDEN						隐藏层维度
NHEADS						多注意力机制头数
SEQ_LEN						最大长度
SAVE_INTERVAL				保存频率

--train-samples				训练样本数
--eval-interval				验证频率
--eval-iters				验证iter
```

### GPT2模型16B多节点训练

```
#多节点运行
sh mpi-run-16B.sh(主要参数在single-16B.sh,参数类型与单节点相同, 默认以fp32精度训练，如需采用fp16精度可执行sh mpi-16B-fp16.sh)
```

## 推理

### 说明

```
注意：推理时pp数需要为1，而tp数需要与训练时一致或者为1。(tp不为1时为多卡推理，为1则是单卡推理)

tools/convert_checkpoint/deepspeed_to_deepspeed.py 模型tp数转化
tools/convert_checkpoint/deepspeed_to_megatron.py 模型pp数转化，并变为可推理格式（推理必须有这一步)

下边展示多节点4tp 4pp训练的模型专为4tp 1pp的多卡推理，以及单节点4tp 1pp训练的模型转化为1tp 1pp的单卡推理。
16B模型单卡推理显存不足，这里不给示例，如有多tp 多pp转为单卡推理需要可以参考单卡推理conver-model-1tp.sh
```

### 转换成多卡推理

```
#训练后的模型保存格式为deepspeed格式，如果用于推理，需要进行格式转换成megatron格式，deepspeed-> megatron格式时转换前后TP数需要保持相同
#转换脚本
sh conver-model_to_megatron.sh
```

```
#重要参数
需要将工程路径加入PYTHONPATH
例如：export PYTHONPATH=/home/megatron-deepspeed_dtk23.04:$PYTHONPATH

CHECKPOINT_PATH  需要转换的模型路径(具体到保存的global_step)
output_folder	 转换后的模型路径
target_tp		 转换后的TP数，与训练保持一直或设置为1
target_pp		 转换后的PP数，与训练保持一直或设置为1
```

### 转换成单卡推理

```
#原始模型保存的是deepspeed格式，deepspeed-> megatron格式时转换前后TP数需要保持相同，因此需要先deepspeed->deepspeed（改变TP成1），然后再由deepspeed-> megatron转换成可推理的格式

#转换脚本
sh conver-model-1tp.sh
```



### 无条件文本生成

```
#多卡推理
mpirun -np 4 run-inf-gpus.sh
#单卡推理
mpirun -np 1 run-inf.sh
```

```
#生成时模型各项参数需要与训练时保持一致（TP也需要保持一致）
--micro-batch-size  	micro-batch-size大小
--out-seq-length		输出文本程度
--genfile				生成文本保存位置
--num-samples			生成样本个数
```

## result

推理示例如下：（生成单词异常是由于训练不充分导致一些token合并问题）

![result](result.jpg)



## 精度

16B模型训练loss：

|   卡数    |       配置        |   lm loss    |
| :-------: | :---------------: | :----------: |
| 32 x 4DCU | tp4，pp8，单卡16G | 1.965622E+00 |

16B模型验证：

|   卡数    |       配置        | lm loss value | lm loss PPL  |
| :-------: | :---------------: | :-----------: | :----------: |
| 32 x 4DCU | tp4，pp8，单卡16G | 4.299443E+00  | 7.365877E+01 |

16B模型收敛曲线如下：

![image-20230524143710566](image-gpt-loss.png)

![image-20230524143830580](image-gpt-loss2.png)

## 应用场景

### 算法类别

`文本生成`

### 热点应用行业

`互联网`

## 源码仓库及问题反馈

https://developer.hpccube.com/codes/modelzoo/gpt2-pytorch/

## 参考

https://github.com/bigscience-workshop/Megatron-DeepSpeed

