概述
ChatGPT 发布以来,在算法以及工程圈里引发了各种讨论,近期公司业务需要做 GPT 的尝试,因此前期花了一点时间来学习和调研。
名词解释
- LLaMA: Language Model Analysis using Multi-Head Attention, LLaMA可以帮助分析模型在不同任务和数据集上的表现,并提供了一些有用的可视化工具,帮助深入了解模型的内部运行机制
- Stanford Alpaca: 是斯坦福大学自然语言处理组(Stanford NLP Group)开发的一款自然语言处理工具包,它基于神经网络模型,可以用于各种NLP任务,如命名实体识别、句法分析、情感分析等
- Alpaca: Adaptive Language-Powered Assistance for Computational Analysis, Alpaca提供了多种预训练模型,可以用于各种NLP任务
- LLM: Large Language Model
- Transformers库: 是一个用于自然语言处理的Python库,可以用于多种NLP任务,如文本分类、命名实体识别、情感分析、问答等
- HuggingFace: 一个人工智能开源社区,提供了开发和使用自然语言处理(NLP)模型的工具和资源
- Chinese-LLaMA-Alpaca: 中文LLaMA到中文Alpaca
- LoRA: Long Range Arena, 它是一种基于自回归模型的序列生成方法,可以生成比传统模型更长的序列
- decapoda-research/llama-7b-hf: 跟FB的LLaMA类似,但不是一个东西,属于第三方模型库
- Datasets库: 数据处理的库
- Tokenizers库: 分词库
- Accelerate库: 加速库
- Max Length: 训练大型语言模型时经常使用的一个超参数,它指定了输入文本的最大长度
- ChatGLM-6B: 一个开源的、支持中英双语的对话语言模型,基于General Language Model (GLM)架构,具有62亿参数
- FSDP: Fully Sharded Data Parallelism 是一种数据并行训练的方法,它将模型参数划分为多个块,并将每个块分配给不同的计算设备(如GPU)。FSDP采用了一些技术来实现参数的划分和同步,例如参数梯度的平均化和梯度压缩。FSDP的主要优点是它可以在不同的计算设备上以数据并行的方式同时训练模型,从而加快模型的训练速度。
- DeepSpeed: 微软开发的一种开源深度学习训练优化工具,旨在解决大规模模型训练的性能和可扩展性问题,是一个更加综合的分布式训练框架,它支持多种并行训练策略,包括数据并行、模型并行和管道并行等。DeepSpeed还提供了一些工具和技术来优化分布式训练的性能和可扩展性,例如ZeRO(Zero Redundancy Optimization)和Megatron-style模型并行。DeepSpeed的主要优点是它可以很好地适应不同的训练场景和硬件配置,并提供了一些高级功能,例如动态图优化、学习率调整和模型压缩等
- HF格式: 指Hugging Face的模型保存格式
- OPT: from Meta AI
- pre-training (PT): 增量预训练
- multi-task supervised fine-tuning (SFT): 有监督微调
- human feedback learning (RM, PPO).
- RM: 奖励模型建模
- RL: 强化学习
- DPO: 直接偏好优化(Direct Preference Optimization,DPO)
启动GPU容器
GPU 环境的使用总是充满冲突,尤其在资源有限的情况下,但是容器是个好东西,可以一定程度上缓解使用上的冲突,计算资源的调度本身就是一个非常大的课题,目前没有太多精力去支持,所以简单用容器、Jupyter Lab 的方式来支持多用户。
Docker 和 Nvidia-Docker 的安装细节就不展开了,这不是 AIGC 领域的核心东西,简单知道怎么运行就行了。下面这个命令做了什么呢?主要是运行了一个 torch 2.0 + cuda11.7 + cudnn8 的容器环境,并且通过 -v /root/.cache:/root/.cache
这个选项把宿主机的 /root/.cache
挂载到容器的 /root/.cache
,为什么要这么做呢,因为 Hugging Face 的下载默认的目录就是这个,这样是方便大家共享一些数据,而不是每个不同的用户上去都通过网络来下载模型(流量是需要💰的),这个镜像里已经有 Conda 的环境了,所以关于一些依赖不想互相干扰的话(还有网络端口),可以在这个容器内通过 conda
来切换。
1
2
3
4
5
6
7
8
9
10
|
# 测试
docker run --gpus all -it --entrypoint=/bin/bash --network=host pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
# 正式启动之前需要挂载目录
s3fs ai-pytorch /mnt/vos -o passwd_file=/root/.passwd-s3fs -o url=http://gd16-inner-storegw.api.vip.com -o use_path_request_style
# 远程存储
docker run -d --gpus all -v /mnt/vos:/pytorch -it --entrypoint=/bin/bash --network=host newportal10102/ai-noah-llm:torch2.0.0-cuda11.7-cudnn8-devel-latest
# 本地目录
docker run -d --gpus all -it -v /home/dxwang/.cache:/root/.cache --entrypoint=/bin/bash --network=host vipdocker-f9nub.vclound.com/library/ai-noah-llm:torch2.0.0-cuda11.7-cudnn8-devel-latest
# 其他
docker run --name llm-docker --privileged -v /data/llm-docker:/root/.cache -d --gpus all -it --entrypoint=/bin/bash --network=host pytorch/ai-noah-llm:torch2.0.0-cuda11.7-cudnn8-devel-latest
|
Again,如果不想跟其他同学共有一个容器的话,还可以自己创建一个专属的容器,关于如何挂载目录,大家可以自行斟酌,现在是测试环境,尽量不要干扰到其他同学的测试就好,如果是有风险的操作,不太确定的话,可以咨询 oscar01.liu。目前 pytorch/ai-noah-llm:torch2.0.0-cuda11.7-cudnn8-devel-latest
镜像的是这个 Dockerfile。
1
2
3
4
5
6
7
8
9
|
FROM pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
RUN apt-get update && apt-get install git curl git-lfs vim zsh net-tools -y
RUN pip install transformers tokenizers sentencepiece deepspeed psutil==5.9.0 protobuf==3.20 jupyterlab -i http://pypi.xxx.com/simple --trusted-host pypi.xxx.com --user
RUN apt-get install -y --no-install-recommends tensorrt
ENTRYPOINT ["start.sh"]
|
其中 start.sh 脚本可以参考下面的例子来写。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/usr/bin/env bash
set -x
cat > /root/.jupyter/jupyter_lab_config.py <<"EOF"
c.ServerApp.allow_origin = '*'
c.ServerApp.disable_check_xsrf = True
c.ServerApp.websocket_compression_options = {}
# 线上环境需要这个
# c.ServerApp.websocket_origin = "http://minio-vos.vip.vip.com"
c.ServerApp.notebook_dir = "/root/.cache"
EOF
cp ~/.local/bin/jupyter /usr/local/bin/
nohup jupyter lab --allow-root --ip 0.0.0.0 --notebook-dir=/root/.cache --NotebookApp.token='yourpassword' --port 80 2>&1 &
|
Jupyter Lab
为什么要用 Jupyter Lab 呢?主要是为了提供一个 Web 页面,方便不习惯登录服务器或者进入容器操作的同学来操作。关于部署,这也不是 AIGC 十分关注的领域,我们可以跳过,反正大部分的官方教程都有说,但是我部署的方式是在上面的容器内直接运行的,只需要两条命令。
1
2
3
|
# 在上述的容器中执行
pip3 install jupyterlab -i http://pypi.xxx.com/simple --trusted-host pypi.xxx.com --user
nohup ~/.local/bin/jupyter lab --allow-root --ip 0.0.0.0 --NotebookApp.token='你设置的密码' --port 80 2>&1 &
|
这样你就可以在上述的容器里启动一个 Jupyter Lab 的后台服务了,通过指定的 port
和 token
可以直接在公网访问。注意 pip 包最好用 root 来安装。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
pip3 install jupyterlab
mkdir -p /root/.jupyter
cat > /root/.jupyter/jupyter_lab_config.py <<"EOF"
c.ServerApp.allow_origin = '*'
c.ServerApp.disable_check_xsrf = True
c.ServerApp.websocket_compression_options = {}
# 线上环境需要这个
c.ServerApp.websocket_origin = "http://minio-xxx.com"
c.ServerApp.notebook_dir = "/root/.cache"
EOF
# 后台执行
nohup jupyter lab --allow-root --ip 0.0.0.0 --NotebookApp.token='xxx' --port 80 2>&1 &
# 公有云密码安全度高一点
nohup jupyter lab --allow-root --ip 0.0.0.0 --NotebookApp.token='xxx' --port 80 2>&1 &
# 个人notebook
nohup jupyter lab --allow-root --ip 0.0.0.0 --NotebookApp.token='xxx' --port 32222 2>&1 &
# 如果非root用户可能需要调整一下
cp ~/.local/bin/jupyter /usr/local/bin/
nohup jupyter lab --allow-root --ip 0.0.0.0 --notebook-dir=/root/.cache --NotebookApp.token='xxx' --port 80 2>&1 &
nohup jupyter lab --allow-root --ip 0.0.0.0 --notebook-dir=/root/.cache --NotebookApp.token='xxx' --port 8888 2>&1 &
|
测试
按照 standford_alpaca 的代码进行测试。基本上测试都会根据官方给的示例脚本,再根据环境来进行一些微调,比如修改一下模型、语料路径之类的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
git clone https://github.com/tatsu-lab/stanford_alpaca.git
torchrun --nproc_per_node=6 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--output_dir /data/github/stanford_alpaca/output_dir \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--lr_scheduler_type "cosine" \
--logging_steps 1 \
--fsdp "full_shard auto_wrap" \
--fsdp_transformer_layer_cls_to_wrap 'OPTDecoderLayer'
# 默认的deepspeed配置stage3+offload
torchrun --nproc_per_node=2 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--output_dir /data/github/stanford_alpaca/output_dir \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--deepspeed "./configs/default_offload_opt_param.json" \
--tf32 True
|
DeepSpeed
DeepSpeed 是后面官方添加的,之前是没有关于使用 DeepSpeed 运行分布式训练的相关代码例子的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
torchrun --nproc_per_node=2 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--bf16 True \
--output_dir /data/github/stanford_alpaca/output_dir \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--deepspeed "./configs/default_offload_opt_param.json" \
--tf32 True
torchrun --nproc_per_node=6 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--bf16 True \
--output_dir /tmp/ \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--deepspeed "./configs/default_offload_opt_param.json" \
--tf32 True
|
stage2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
torchrun --nproc_per_node=1 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--bf16 True \
--output_dir /tmp/ \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--deepspeed "./configs/stage2_offload_opt_param.json" \
--tf32 True
# 换个端口
torchrun --nproc_per_node=1 --master_port=8889 train.py \
--model_name_or_path "facebook/opt-125m" \
--data_path ./alpaca_data.json \
--bf16 True \
--output_dir /tmp/ \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--deepspeed "./configs/stage2_offload_opt_param.json" \
--tf32 True
|
官方默认
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
# 单机4卡
torchrun --nproc_per_node=4 --master_port=8888 train.py \
--model_name_or_path "facebook/opt-6.7b" \
--data_path ./alpaca_data.json \
--cache_dir /root/.cache/huggingface/hub/ \
--bf16 True \
--output_dir /tmp/standfor/ \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 4 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--lr_scheduler_type "cosine" \
--logging_steps 1 \
--fsdp "full_shard auto_wrap" \
--fsdp_transformer_layer_cls_to_wrap 'OPTDecoderLayer' \
--tf32 True
# 修改一下,可以放在A800集群的jupyter内运行
torchrun --nproc_per_node=1 --master_port=9999 train.py \
--model_name_or_path "/home/public/models/opt-125m" \
--data_path ./alpaca_data.json \
--bf16 True \
--output_dir /home/llms \
--num_train_epochs 1 \
--per_device_train_batch_size 8 \
--per_device_eval_batch_size 8 \
--gradient_accumulation_steps 8 \
--evaluation_strategy "no" \
--save_strategy "steps" \
--save_steps 2000 \
--save_total_limit 1 \
--learning_rate 2e-5 \
--weight_decay 0. \
--warmup_ratio 0.03 \
--lr_scheduler_type "cosine" \
--logging_steps 1 \
--fsdp "full_shard auto_wrap" \
--fsdp_transformer_layer_cls_to_wrap 'OPTDecoderLayer' \
--tf32 True \
--report_to wandb
|
参考资料
- 下载HuggingFace上模型的正确姿势
- 类ChatGPT的部署与微调(上):从LLaMA、Alpaca/Vicuna/BELLE、中文版
- MedicalGPT: 基于LLaMA-13B的中英医疗问答模型(LoRA)、实现包括二次预训练、有监督微调、奖励建模
- 社区供稿 | 基于 LoRA 的 RLHF: 记一次不太成功但有趣的百川大模型调教经历
警告
本文最后更新于 2023年3月12日,文中内容可能已过时,请谨慎参考。