LLMs之ChatGLM2:ChatGLM-Finetuning(基于DeepSpeed)的简介、使用方法(四种微调方法(Freeze方法/Lora方法/P-Tuning方法/全量参数)+单卡/多卡训练设置+显存资源占用对比)、案例应用(基于4张A800-80G+采用ChatGLM-6B模型+全量参数+基于DeepSpeed框架(ZeRO3的模型拆分技术)流水线实现)之详细攻略
目录
LLMs之GLM-130B/ChatGLM:《GLM-130B: AN OPEN BILINGUAL PRE-TRAINED MODEL》翻译与解读
LLMs之ChatGLM2:ChatGLM2-6B的简介、安装、使用方法之详细攻略
LLMs之ChatGLM:ChatGLM Efficient Tuning(一款高效微调ChatGLM-6B/ChatGLM2-6B的工具【LoRA/P-Tunin】)的简介、安装、使用方法之详细攻略
LLMs之ChatGLM2:基于ChatGLM Efficient Tuning(微调工具包)实现对ChatGLM2进行LoRA微调并进行推理测试图文教程之详细攻略
LLMs:LangChain-Chatchat(一款可实现本地知识库问答应用)的简介、安装、使用方法之详细攻略
2、微调方法:基于4卡 A800-80G采用微调训练,最长2小时左右
T1、Freeze方法:修改train_type=freeze及其freeze_module_name参数
(2)、ChatGLM四卡训练:设置CUDA_VISIBLE_DEVICES参数
(4)、ChatGLM2四卡训练:设置CUDA_VISIBLE_DEVICES参数
(5)、耗费显存资源占用对比—Freeze方法:对比ChaGLM和ChaGLM2
T2、PT方法(即P-Tuning及P-Tuning V2):修改train_type为ptuning、prefix_projection=True
(5)、耗费显存资源占用对比—PT方法:对比ChaGLM和ChaGLM2
(5)、耗费显存资源占用对比—LoRA方法:对比ChaGLM和ChaGLM2
T4、全参方法(基于DeepSpeed-Zero3方法【对模型参数进行多卡分割】+Offload方法【将优化器参数卸载到CPU上】):修改train_type=all
(3)、耗费显存资源占用对比—全参方法:对比ChaGLM和ChaGLM2
1、流水线并行训练案例:基于4张A800-80G+采用ChatGLM-6B模型+全量参数+基于DeepSpeed框架(ZeRO3的模型拆分技术)流水线实现
显卡实时占比:每张卡依次占比55/80G、80/80G、80/80G、70/80G
相关文章
相关论文
LLMs之GLM-130B/ChatGLM:《GLM-130B: AN OPEN BILINGUAL PRE-TRAINED MODEL》翻译与解读
LLMs之GLM-130B/ChatGLM:《GLM-130B: AN OPEN BILINGUAL PRE-TRAINED MODEL》翻译与解读_一个处女座的程序猿的博客-CSDN博客
LLMs之ChatGLM2:ChatGLM2-6B的简介、安装、使用方法之详细攻略
LLMs之ChatGLM2:ChatGLM2-6B的简介、安装、使用方法之详细攻略_一个处女座的程序猿的博客-CSDN博客
实战案例
LLMs:从头到尾手把手教大家利用ChatGLM-6B模型实现训练、部署、推理(CLI/Gradio交互界面)、微调(两个提效技巧【混合精度+ZeRO零冗余提效】+三种微调方法【fine-tuning/P-tuning v2改变参数分布/LoRA低秩近似降低要更新参数量】)图文教程之详细攻略
https://yunyaniu.blog.csdn.net/article/details/120249551
LLMs之ChatGLM:基于Langchain框架利用text2vec-large-chinese+ChatGLM大模型(Docker 部署)接入本地知识库(生成本地知识库/分割/向量化+基于问题【Embdding+向量化+匹配TopK作为上下文】=生成Prompt喂给大模型→LLMs响应)实现问答响应项目(CLI/WebUI/VUE)图文教程之详细攻略
https://yunyaniu.blog.csdn.net/article/details/130998758
LLMs之ChatGLM:ChatGLM Efficient Tuning(一款高效微调ChatGLM-6B/ChatGLM2-6B的工具【LoRA/P-Tunin】)的简介、安装、使用方法之详细攻略
LLMs之ChatGLM2:ChatGLM2-6B本地部署之单机推理(API/CLI/GUI)、低成本部署(GPU量化部署/CPU及其量化部署/Mac部署/多卡部署)、有限资源下高效微调(全参/P-tuning v2)、模型评估和推理之图文教程之详细攻略
LLMs之ChatGLM2:基于ChatGLM Efficient Tuning(微调工具包)实现对ChatGLM2进行LoRA微调并进行推理测试图文教程之详细攻略
LLMs:LLaMA Efficient Tuning(一款可高效微调【全参数/LoRA/QLoRA】主流大模型【ChatGLM2/LLaMA2/Baichuan等】的高效工具【预训练+指令监督微调+奖励模型训练+PPO 训练+DPO 训练】)的简介、安装、使用方法之详细攻略
LLMs:LangChain-Chatchat(一款可实现本地知识库问答应用)的简介、安装、使用方法之详细攻略
LLMs:LangChain-Chatchat(一款可实现本地知识库问答应用)的简介、安装、使用方法之详细攻略_一个处女座的程序猿的博客-CSDN博客
LLMs之ChatGLM2:ChatGLM-Finetuning的简介、使用方法(四种微调方法(Freeze方法/Lora方法/P-Tuning方法/全量参数)+单卡/多卡训练设置+显存资源占用对比)、案例应用之详细攻略
https://yunyaniu.blog.csdn.net/article/details/132613495
LLMs之ChatGLM2:ChatGLM-Finetuning之源码解读(train.py文件)—解析命令行(模型路径+数据集相关【最大序列长度/最大输入长度】+训练参数相关【批次大小/学习率/权重衰减系数/训练轮数/梯度累计步数/学习率预热比例】+结果输出相关【输出路径/训练方式【四种方式微调,如Freeze/Lora/P-Tuning/全量参数】/进程标志/loss频率/保存模型频率】+否启用梯度检查点+DeepSpeed配置+LoRA/Freeze/P-tuning配置)及初始化设置(是否启用分布式GPU+加载DeepSpeed配置参数+日志写入器)→加载数据(加载tokenizer/训练集)→模型训练(载入优化器和学习率调度器并设置参数+判断启用梯度检查点+将模型和优化器包装到deepspeed中【DeepSpeed封装数据并行】+执行模型训练【训练epoch循环+迭代训练数据+计算loss+反向传播+梯度裁剪技术】)+模型保存(定期显示训练损失并保存模型,判断zero3训练时其模型参数需要合并保存)
ChatGLM-Finetuning的简介
本项目主要针对ChatGLM和ChatGLM2模型进行不同方式的微调(Freeze方法、Lora方法、P-Tuning方法、全量参数等),训练代码均采用DeepSpeed进行训练,并对比大模型在不同微调方法上的效果,主要针对信息抽取任务、生成任务、分类任务等。
本项目支持单卡训练&多卡训练,由于采用单指令集方式微调,模型微调之后并没有出现严重的灾难性遗忘。由于官方代码和模型一直在更新,目前代码和模型使用的是最新版本(20230806)。
PS:没有用Trainer(虽然Trainer代码简单,但不易修改,大模型时代算法工程师本就成为了数据工程师,因此更需了解训练流程)
ChatGLM-Finetuning的安装及其使用方法
1、配置环境
1.1、下载项目代码
1.2、配置环境,各个包版本的要求
cpm_kernels==1.0.11
deepspeed==0.9.0
numpy==1.24.2
peft==0.3.0
sentencepiece==0.1.96
tensorboard==2.11.0
tensorflow==2.13.0
torch==1.13.1+cu116
tqdm==4.64.1
transformers==4.27.1
2、微调方法:基于4卡 A800-80G采用微调训练,最长2小时左右
模型微调时,如果遇到显存不够的情况,可以开启gradient_checkpointing、zero3、offload等参数来节省显存。下面model_name_or_path参数为模型路径,请根据可根据自己实际模型保存地址进行修改。
T1、Freeze方法:修改train_type=freeze及其freeze_module_name参数
Freeze方法,即参数冻结,对原始模型部分参数进行冻结操作,仅训练部分参数,以达到在单卡或多卡,不进行TP(张量并行)或PP(管道并行)操作就可以对大模型进行训练。
微调代码,见train.py,核心部分如下:
freeze_module_name = args.freeze_module_name.split(",")
for name, param in model.named_parameters():
if not any(nd in name for nd in freeze_module_name):
param.requires_grad = False
针对模型不同层进行修改,可以自行修改freeze_module_name参数配置,例如"layers.27.,layers.26.,layers.25.,layers.24."。 训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、freeze_module_name、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。
(1)、ChatGLM单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B/ \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type freeze \
--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm
(2)、ChatGLM四卡训练:设置CUDA_VISIBLE_DEVICES参数
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B/ \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type freeze \
--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm
(3)、ChatGLM2单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B/ \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type freeze \
--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm2
(4)、ChatGLM2四卡训练:设置CUDA_VISIBLE_DEVICES参数
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B/ \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type freeze \
--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm2
(5)、耗费显存资源占用对比—Freeze方法:对比ChaGLM和ChaGLM2
PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:
Model | DeepSpeed-Stage | Offload | Gradient Checkpointing | Batch Size | Max Length | GPU-A40 Number | 所耗显存 |
---|---|---|---|---|---|---|---|
ChaGLM | zero2 | No | Yes | 1 | 1560 | 1 | 36G |
ChaGLM | zero2 | No | No | 1 | 1560 | 1 | 38G |
ChaGLM | zero2 | No | Yes | 1 | 1560 | 4 | 24G |
ChaGLM | zero2 | No | No | 1 | 1560 | 4 | 29G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 1 | 35G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 1 | 36G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 4 | 22G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 4 | 27G |
T2、PT方法(即P-Tuning及P-Tuning V2):修改train_type为ptuning、prefix_projection=True
PT方法,即P-Tuning方法,参考ChatGLM官方代码 ,是一种针对于大模型的soft-prompt方法。
微调代码,见train.py,核心部分如下:
config = MODE[args.mode]["config"].from_pretrained(args.model_name_or_path)
config.pre_seq_len = args.pre_seq_len
config.prefix_projection = args.prefix_projection
model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path, config=config)
for name, param in model.named_parameters():
if not any(nd in name for nd in ["prefix_encoder"]):
param.requires_grad = False
当prefix_projection为True时,为P-Tuning-V2方法,在大模型的Embedding和每一层前都加上新的参数;为False时,为P-Tuning方法,仅在大模型的Embedding上新的参数。
训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、pre_seq_len、prefix_projection、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。
(1)、ChatGLM单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B \
--per_device_train_batch_size 1 \
--max_len 768 \
--max_src_len 512 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type ptuning \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--pre_seq_len 16 \
--prefix_projection True \
--output_dir ./output-glm
(2)、ChatGLM四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type ptuning \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--pre_seq_len 16 \
--prefix_projection True \
--output_dir ./output-glm
(3)、ChatGLM2单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type ptuning \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--pre_seq_len 16 \
--prefix_projection True \
--output_dir ./output-glm2
(4)、ChatGLM2四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type ptuning \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--pre_seq_len 16 \
--prefix_projection True \
--output_dir ./output-glm2
(5)、耗费显存资源占用对比—PT方法:对比ChaGLM和ChaGLM2
PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:
Model | DeepSpeed-Stage | Offload | Gradient Checkpointing | Batch Size | Max Length | GPU-A40 Number | 所耗显存 |
---|---|---|---|---|---|---|---|
ChaGLM | zero2 | No | Yes | 1 | 768 | 1 | 43G |
ChaGLM | zero2 | No | No | 1 | 300 | 1 | 44G |
ChaGLM | zero2 | No | Yes | 1 | 1560 | 4 | 37G |
ChaGLM | zero2 | No | No | 1 | 1360 | 4 | 44G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 1 | 20G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 1 | 40G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 4 | 19G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 4 | 39G |
T3、Lora方法:修改train_type=lora及其lora_dim=16、lora_alpha=64、lora_dropout=0.1、lora_module_name="query_key_value"
Lora方法,即在大型语言模型上对指定参数(权重矩阵)并行增加额外的低秩矩阵,并在模型训练过程中,仅训练额外增加的并行低秩矩阵的参数。 当“秩值”远小于原始参数维度时,新增的低秩矩阵参数量也就很小。在下游任务tuning时,仅须训练很小的参数,但能获取较好的表现结果。
微调代码,见train.py,核心部分如下:
model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path)
lora_module_name = args.lora_module_name.split(",")
config = LoraConfig(r=args.lora_dim,
lora_alpha=args.lora_alpha,
target_modules=lora_module_name,
lora_dropout=args.lora_dropout,
bias="none",
task_type="CAUSAL_LM",
inference_mode=False,
)
model = get_peft_model(model, config)
model.config.torch_dtype = torch.float32
训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、lora_dim、lora_alpha、lora_dropout、lora_module_name、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。
(1)、ChatGLM单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type lora \
--lora_dim 16 \
--lora_alpha 64 \
--lora_dropout 0.1 \
--lora_module_name "query_key_value" \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm
(2)、ChatGLM四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type lora \
--lora_dim 16 \
--lora_alpha 64 \
--lora_dropout 0.1 \
--lora_module_name "query_key_value" \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm
(3)、ChatGLM2单卡训练
CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type lora \
--lora_dim 16 \
--lora_alpha 64 \
--lora_dropout 0.1 \
--lora_module_name "query_key_value,dense_h_to_4h,dense_4h_to_h,dense" \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm2
(4)、ChatGLM2四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type lora \
--lora_dim 16 \
--lora_alpha 64 \
--lora_dropout 0.1 \
--lora_module_name "query_key_value,dense_h_to_4h,dense_4h_to_h,dense" \
--seed 1234 \
--ds_file ds_zero2_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm2
(5)、耗费显存资源占用对比—LoRA方法:对比ChaGLM和ChaGLM2
PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:
Model | DeepSpeed-Stage | Offload | Gradient Checkpointing | Batch Size | Max Length | GPU-A40 Number | 所耗显存 |
---|---|---|---|---|---|---|---|
ChaGLM | zero2 | No | Yes | 1 | 1560 | 1 | 20G |
ChaGLM | zero2 | No | No | 1 | 1560 | 1 | 45G |
ChaGLM | zero2 | No | Yes | 1 | 1560 | 4 | 20G |
ChaGLM | zero2 | No | No | 1 | 1560 | 4 | 45G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 1 | 20G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 1 | 43G |
ChaGLM2 | zero2 | No | Yes | 1 | 1560 | 4 | 19G |
ChaGLM2 | zero2 | No | No | 1 | 1560 | 4 | 42G |
注意:Lora方法在模型保存时仅保存了Lora训练参数,因此在模型预测时需要将模型参数进行合并,具体参考merge_lora.py。
T4、全参方法(基于DeepSpeed-Zero3方法【对模型参数进行多卡分割】+Offload方法【将优化器参数卸载到CPU上】):修改train_type=all
全参方法,对大模型进行全量参数训练,主要借助DeepSpeed-Zero3方法,对模型参数进行多卡分割,并借助Offload方法,将优化器参数卸载到CPU上以解决显卡不足问题。
微调代码,见train.py,核心部分如下:
model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path)
训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。
(1)、ChatGLM四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm \
--train_type all \
--seed 1234 \
--ds_file ds_zero3_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm
(2)、ChatGLM2四卡训练
通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \
--train_path data/spo_0.json \
--model_name_or_path ChatGLM2-6B \
--per_device_train_batch_size 1 \
--max_len 1560 \
--max_src_len 1024 \
--learning_rate 1e-4 \
--weight_decay 0.1 \
--num_train_epochs 2 \
--gradient_accumulation_steps 4 \
--warmup_ratio 0.1 \
--mode glm2 \
--train_type all \
--seed 1234 \
--ds_file ds_zero3_no_offload.json \
--gradient_checkpointing \
--show_loss_step 10 \
--output_dir ./output-glm2
(3)、耗费显存资源占用对比—全参方法:对比ChaGLM和ChaGLM2
PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:
Model | DeepSpeed-Stage | Offload | Gradient Checkpointing | Batch Size | Max Length | GPU-A40 Number | 所耗显存 |
---|---|---|---|---|---|---|---|
ChaGLM | zero3 | Yes | Yes | 1 | 1560 | 4 | 33G |
ChaGLM2 | zero3 | No | Yes | 1 | 1560 | 4 | 44G |
ChaGLM2 | zero3 | Yes | Yes | 1 | 1560 | 4 | 26G |
后面补充DeepSpeed的Zero-Stage的相关内容说明。
多种微调技巧结果对比:PT-only-Embedding(37G【显卡占用】,53m【训练耗时】+3m【测试耗时】)、PT(30G,135m+3m)、Freeze(24G,112m+3m)、Lora(39G,65m+4m)四种微调结果
ChatGLM-Finetuning的案例应用
1、流水线并行训练案例:基于4张A800-80G+采用ChatGLM-6B模型+全量参数+基于DeepSpeed框架(ZeRO3的模型拆分技术)流水线实现
本项目代码采用了4张A800-80G进行训练(实际上2张卡也行),结果显示F1得分在0.55~0.65之间;虽然Lora、P-tuing等技术,使得13b模型也可以在单张A100上训练,但是如果模型参数量过大,单张显卡不足以加载训练模型时,流水线并行是必不可少的。
(1)、训练阶段:采用三元组数据进行模型训练及测试
训练脚本 |
CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 5524 train_pipeline.py \ --train_path data/spo_0.json \ --model_name_or_path ./ChatGLM-6B/ \ --per_device_train_batch_size 14 \ --max_len 1024 \ --max_src_len 512 \ --num_train_epochs 5 \ --gradient_accumulation_steps 1 \ --seed 1234 \ --show_loss_step 20 \ --num_stages 4 \ --save_model_step 100 \ --output_dir ./output-glm-pp |
(2)、推理阶段:模型转换脚本
由于pipeline训练时,模型存在的变量名称与原始模型有所区别,因此在推理阶段,如果采用原始模型结构时,需要将convert_model_to_hf.py文件中,保存模型进行变量名称转换。
模型转化代码 |
模型转化代码如下所示 model_static_dict = {} for path in Path(pipeline_model_dir).iterdir(): print("已经处理文件:{}".format(path)) if not path.name.startswith('layer'): continue small_static_dict = torch.load(path, map_location="cpu") layer_i = int(path.name.split('-')[0].replace('layer_', '')) if layer_i == 0: model_static_dict["transformer.word_embeddings.weight"] = small_static_dict["word_embeddings.weight"] elif layer_i == 30: model_static_dict["lm_head.weight"] = small_static_dict["word_embeddings.weight"] elif layer_i == 29: for k, v in small_static_dict.items(): model_static_dict["transformer." + k] = v else: for k, v in small_static_dict.items(): model_static_dict["transformer." + k.replace("layer.", "layers.{}.".format(layer_i - 1))] = v torch.save(model_static_dict, join(save_model_dir, "pytorch_model.bin")) |
推理脚本 |
python3 convert_model_to_hf.py \ --ori_model_dir ./ChatGLM-6B/ \ --pipeline_model_dir output-glm-pp/global_step300/ \ --save_model_dir output-glm-pp/gs300/ |
(3)、结果对比
显卡实时占比:每张卡依次占比55/80G、80/80G、80/80G、70/80G
F1得分在0.59左右
步数 | 300 | 400 | 500 |
---|---|---|---|
F1值 | 0.5882 | 0.5793 | 0.5874 |