ChatGLM-6B微调实践与问题汇总(fine-tune+p-tuning+知识遗忘解决尝试)
1.介绍
ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。在模型量化技术的加持下,INT4 量化级别下显存占用不到6G,满足一些消费级显卡部署的需要。
https://github.com/THUDM/ChatGLM-6B.git
本文只涉及对官方仓库中模型参数全量fine-tune和p-tuning方案的复现,以及对p-tuning训练后,模型对旧知识遗忘现象的优化。
训练后,丧失了原有的对话功能的优化可直接调到第5节
2.软硬件环境
硬件平台
cpu:Inter Xeon Gold 6130 x2
GPU:Tesla V100 16G x8
预训练模型
chatglm-6B
数据集
adgen
软件环境
deepspeed==0.9.2
protobuf
transformers==4.28.1(不建议用requirements中的4.27.1版本,不要问我怎么知道的)
cpm_kernels
torch>=1.10
gradio
mdtex2html
sentencepiece
accelerate
rouge_chinese
nltk
jieba
datasets
3.模型与数据集下载
模型
https://huggingface.co/THUDM/chatglm-6b
数据集
下载处理好的 ADGEN 数据集 https://cloud.tsinghua.edu.cn/f/b3f119a008264b1cabd1/?dl=1,将解压后备用。
4.训练
训练操作过程参考https://github.com/THUDM/ChatGLM-6B/blob/main/ptuning/README.md
4.1 fine-tune
脚本:
ds_train_finetune.sh
LR=1e-4
MASTER_PORT=$(shuf -n 1 -i 10000-65535)
deepspeed --num_gpus=4 --master_port $MASTER_PORT main.py \
--deepspeed deepspeed.json \
--do_train \
--train_file AdvertiseGen/train.json \
--test_file AdvertiseGen/dev.json \
--prompt_column content \
--response_column summary \
--overwrite_cache \
--model_name_or_path THUDM/chatglm-6b \
--output_dir ./output/adgen-chatglm-6b-ft-$LR \
--overwrite_output_dir \
--max_source_length 64 \
--max_target_length 64 \
--per_device_train_batch_size 4 \
--per_device_eval_batch_size 1 \
--gradient_accumulation_steps 1 \
--predict_with_generate \
--max_steps 5000 \
--logging_steps 10 \
--save_steps 1000 \
--learning_rate $LR \
--fp16
官方给出的deepspeed配置文件为zero stage2,由于本服务器单卡显存较低,需要使用ZeRO stage3 + offload cpu。
新建deepspeed配置文件:deepspeed_zero3_config.json
{
"gradient_accumulation_steps":"auto",
"train_micro_batch_size_per_gpu": "auto",
"zero_allow_untested_optimizer": true,
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"initial_scale_power": 16,
"loss_scale_window": 1000,
"hysteresis": 2,
"min_loss_scale": 1
},
"bf16": {
"enabled": "auto"
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
},
"allgather_partitions": true,
"allgather_bucket_size": 5e8,
"reduce_scatter": true,
"contiguous_gradients" : true,
"overlap_comm": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
}
}
实际训练时需对如下两个参数进行调整
--num-gpus 8
--deepspeed deepspeed_zero3_config.json
训练过程资源利用情况
cpu | men | GPU | 显存 |
---|---|---|---|
8*550% | 8*4.4% | 50%-100% | 8*(14.8-16G) |
GPU利用率波动较大
训练时长
31h11min
针对ADGEN数据集的评价指标
脚本 ptuning/evaluate_finetune.sh
Bleu-4: 8.6162
rouge-1: 30.7453
rouge-2: 7.6246
rouge-1: 24.832
4.2 p-tuning
训练脚本 train.sh
PRE_SEQ_LEN=128
LR=2e-2
CUDA_VISIBLE_DEVICES=0 python3 main.py \
--do_train \
--train_file AdvertiseGen/train.json \
--validation_file AdvertiseGen/dev.json \
--prompt_column content \
--response_column summary \
--overwrite_cache \
--model_name_or_path THUDM/chatglm-6b \
--output_dir output/adgen-chatglm-6b-pt-$PRE_SEQ_LEN-$LR \
--overwrite_output_dir \
--max_source_length 64 \
--max_target_length 64 \
--per_device_train_batch_size 1 \
--per_device_eval_batch_size 1 \
--gradient_accumulation_steps 16 \
--predict_with_generate \
--max_steps 3000 \
--logging_steps 10 \
--save_steps 1000 \
--learning_rate $LR \
--pre_seq_len $PRE_SEQ_LEN \
--quantization_bit 4
训练过程资源占用
model Quantized to 8 bit
cpu | 内存 | GPU | 显存 |
---|---|---|---|
1core100% | 0.5% | 80%-100% | 8500MB |
训练总时间:
3h48min
针对ADGEN数据集的评价指标
脚本 :ptuning/evaluate.sh
指标:
Bleu-4: 7.951
rouge-1: 31.520
rouge-2: 7.219
rouge-1: 24.932
5.效果优化,针对”训练后丧失了原有的对话功能“
根据4中的步骤完成训练后,模型在广告生成效果上表现较好(输入:类型#上衣版型#宽松版型#显瘦图案#线条衣样式#衬衫衣袖型#泡泡袖衣款式#抽绳),切两种训练方式得到的模型效果类似。但是在常规的问答或其他任务中,丧失了原有的对话功能,出现了对旧知识遗忘的现象。
https://github.com/THUDM/ChatGLM-6B/issues/1148
所以后续尝试对两种训练方式的训练超参数进行调整:
fine-tune
学习率调整为1e-6 (原始为1e-4),其他参数不变
模型在训练step=2000时,训练收敛,提前结束训练
模型在广告生成和原始对话功能的表现都正常
实际效果如下:
command :( input something or press Ctrl + c to exit ...)
马掉进海里会变成海马么
马掉进海里不会变成海马。马是一种哺乳动物,属于鸮形目,而海马是海龙的别称,属于腔肠动物门。它们是不同的生物,所以马掉进海里不会变成海马。
time consume :2135.13ms, and speed :31.398970588235297 ms / word
command :( input something or press Ctrl + c to exit ...)
类型#上衣*材质#丹宁*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞
这件简约而不简单的丹宁外套,采用白色作为基调,将丹宁外套的硬朗气质与白色调的柔和气息相结合,演绎出时尚与干练兼具的都市摩登感。领口、袖口、下摆以及门襟处的破洞设计,在带来个性时尚的同时,也赋予了外套
time consume :2942.03ms, and speed :29.71747474747475 ms / word
command :( input something or press Ctrl + c to exit ...)
老鼠病了可用吃老鼠药么
不建议使用老鼠药来治疗老鼠病。老鼠药通常是用于杀死老鼠或其他害虫,而不是治疗它们的疾病。使用老鼠药可能会导致其他动物的伤害或死亡,并可能违反当地的动物保护法律。
如果老鼠生病了,建议寻求兽医的帮助。兽医可以通过检查和诊断来找出老鼠病的根本原因,并采取适当的治疗措施来治愈它。
time consume :3605.08ms, and speed :26.123768115942028 ms / word
command :( input something or press Ctrl + c to exit ...)
下岗和下海有啥区别
下岗指的是在原公司、单位或者行业失业后选择再就业的情况;下海指的是离开原来的工作,自己创业当老板的情况。两者的主要区别在于就业方向和创业方式的不同。
time consume :1790.36ms, and speed :24.194054054054053 ms / word
p-tuning
学习率调整为1e-4(原始为2e-2),其他参数不变
训练完成后
模型在广告生成和原始对话功能的表现都正常。
针对ADGEN数据集的评价指标:
Bleu-4: 5.6319
rouge-1: 27.1907
rouge-2: 5.0235
rouge-1: 22.4369
实际效果如下:
command :( input something or press Ctrl + c to exit ...)
马掉进海里会变成海马么
马掉进海里不会变成海马,因为马是陆地上的生物,不会变成海洋中的生物。
time consume :1171.6ms, and speed :34.45882352941176 ms / word
command :( input something or press Ctrl + c to exit ...)
类型#上衣*材质#丹宁*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞
这件丹宁外套,采用了简约的直筒款式,搭配白色的刺绣图案,看起来兴起兴起。衣袖处破洞的设计,给这件丹宁外套增加了一点幽默感。
time consume :2121.93ms, and speed :34.78573770491803 ms / word
command :( input something or press Ctrl + c to exit ...)
老鼠病了可用吃老鼠药么
不建议使用老鼠药来治疗老鼠的疾病。老鼠药通常用于捕捉老鼠,而不是治疗它们。使用老鼠药可能会对老鼠造成伤害,并且可能会导致它们死亡。此外,使用老鼠药来治疗其他动物可能会导致道德和伦理问题。因此,建议不要试图使用老鼠药来治疗老鼠的疾病。
command :( input something or press Ctrl + c to exit ...)
下岗和下海有啥区别
下岗和下海下海是两个不同的概念。下岗指的是失业后重新就业的过程,下海则指的是离开工作岗位,从事其他行业或职业的过程。
从字面上看,下岗指的是离开原工作岗位,下海指的是从事其他行业或职业。但是,下海与下岗的本质区别在于,下海是对原有的工作岗位的放弃,而下岗则是因为原工作岗位的失业
6.资源占用
推理对比
训练方式 | 量化 | 运行显存 | 内存 | VIRT | 加载时间 | 推理速度 |
---|---|---|---|---|---|---|
p-Tuning | fp16 | 13197MB | 0.4% | 26G | 13s | 25-30ms/word |
全量fine-Tuning | fp16 | 12255MB | 0.3% | 24.6G | 11s | 25-30ms/word |
7.问题与解决
6.1 全量fine-tune时,模型初始化报错“NotImplementedError: Cannot copy out of meta tensor; no data!”
修改main.py:124
model = AutoModel.from_pretrained(model_args.model_name_or_path, config=config, trust_remote_code=True)
改为
model = AutoModel.from_pretrained(model_args.model_name_or_path, config=config, trust_remote_code=True, empty_init=False)
“NotImplementedError: Cannot copy out of meta tensor; no data!
这个错误通常是由于Deepspeed在使用自定义权重初始化时出现问题,而这些初始化可能需要从先前的训练中加载权重。如果在使用Deepspeed进行分布式训练时出现此错误,则需要在初始化模型时指定`empty_init=False`,以便在加载权重之前,权重矩阵不会被初始化为空。
AutoModel.from_pretrained是Hugging Face Transformers库中的一个方法,用于从预训练模型中加载权重。在Deepspeed分布式训练中,模型的初始化和权重加载可能需要特殊处理,因此需要使用`empty_init=False`参数来指定在加载权重之前不要将权重矩阵初始化为空。
在其他模型中,可能不需要这个参数是因为它们的初始化和权重加载不需要特殊处理,或者因为它们的代码已经进行了相应的修改以适应Deepspeed的分布式训练流程。”
--https://github.com/THUDM/ChatGLM-6B/issues/530