Skip to content

基于ChatGLM-6B模型,进行下游具体任务微调,涉及Freeze、Lora、P-tuning等

Notifications You must be signed in to change notification settings

xiaobazhang/ChatGLM-Finetuning

This branch is 14 commits behind liucongg/ChatGLM-Finetuning:master.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

97bdeb9 · Apr 10, 2023

History

15 Commits
Apr 6, 2023
Apr 6, 2023
Apr 7, 2023
Apr 10, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 6, 2023
Apr 10, 2023
Apr 7, 2023
Apr 6, 2023

Repository files navigation

ChatGLM微调

本项目主要针对ChatGLM模型进行不同方式的微调,并对比大模型在不同微调方法上的效果,主要针对信息抽取任务、生成任务、分类任务等。

为了模型适配其他方法,对官方ChatGLM模型文件进行了部分修改,将820-821行参数冻结代码删掉,再外部进行参数冻结。

上述实验结果均基于单卡训练,并发现模型微调之后,并没有出现灾难性遗忘现象

由于官方模型和代码一直再更新,请使用项目中的代码,对应版本模型见百度网盘,提取码:jh0l

微调方法

Freeze方法

Freeze方法,即参数冻结,对原始模型部分参数进行冻结操作,仅训练部分参数,以达到在单卡或不进行TP或PP操作,就可以对大模型进行训练。

微调代码,见finetuning_freeze.py,核心部分如下:

for name, param in model.named_parameters():
    if not any(nd in name for nd in ["layers.27", "layers.26", "layers.25", "layers.24", "layers.23"]):
        param.requires_grad = False

针对模型不同层进行修改,可以自行修改。 训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_dir、num_train_epochs、train_batch_size、gradient_accumulation_steps、output_dir、prompt_text等, 可根据自己的任务配置。

CUDA_VISIBLE_DEVICES=0 deepspeed finetuning_freeze.py --num_train_epochs 5 --train_batch_size 2

三元组抽取的推理代码,见predict_freeze.py,其他任务可以根据自己的评价标准进行推理预测。

PT方法

PT方法,即P-Tuning方法,参考ChatGLM官方代码 ,是一种针对于大模型的soft-prompt方法。

  • P-Tuning仅对大模型的Embedding加入新的参数。paper
  • P-Tuning-V2,将大模型的Embedding和每一层前都加上新的参数。paper 微调代码,见finetuning_pt.py,核心部分如下:
config = ChatGLMConfig.from_pretrained(args.model_dir)
config.pre_seq_len = args.pre_seq_len
config.prefix_projection = args.prefix_projection

model = ChatGLMForConditionalGeneration.from_pretrained(args.model_dir, 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_dir、num_train_epochs、train_batch_size、gradient_accumulation_steps、output_dir、prompt_text、pre_seq_len、prompt_text等, 可根据自己的任务配置。

CUDA_VISIBLE_DEVICES=0 deepspeed finetuning_pt.py --num_train_epochs 5 --train_batch_size 2 --pre_seq_len 16

三元组抽取的推理代码,见predict_pt.py,其他任务可以根据自己的评价标准进行推理预测。

Lora方法

Lora方法,即在大型语言模型上对指定参数(权重矩阵)并行增加额外的低秩矩阵,并在模型训练过程中,仅训练额外增加的并行低秩矩阵的参数。 当“秩值”远小于原始参数维度时,新增的低秩矩阵参数量也就很小。在下游任务tuning时,仅须训练很小的参数,但能获取较好的表现结果。

微调代码,见finetuning_lora.py,核心部分如下:

model = ChatGLMForConditionalGeneration.from_pretrained(args.model_dir)
config = LoraConfig(r=args.lora_r,
                    lora_alpha=32,
                    target_modules=["query_key_value"],
                    lora_dropout=0.1,
                    bias="none",
                    task_type="CAUSAL_LM",
                    inference_mode=False,
                    )

model = get_peft_model(model, config)

训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_dir、num_train_epochs、train_batch_size、gradient_accumulation_steps、output_dir、prompt_text、lora_r等, 可根据自己的任务配置。

CUDA_VISIBLE_DEVICES=0 deepspeed finetuning_lora.py --num_train_epochs 5 --train_batch_size 2 --lora_r 8

三元组抽取的推理代码,见predict_lora.py,其他任务可以根据自己的评价标准进行推理预测。

注意:对于结果需要保持一致的任务,需要保存模型的adapter_config.json文件中,inference_mode参数修改成false,并将模型执行model.eval()操作。 主要原因是chatglm模型代码中,没有采用Conv1D函数。

运行环境

查看requirements.txt文件

实验结果

三元组抽取

  • 为了防止大模型的数据泄露,采用一个领域比赛数据集-汽车工业故障模式关系抽取,随机抽取50条作为测试集
  • 模型训练时,最大长度为768,Batch大小为2,训练轮数为5,fp16训练,采用DeepSpeed的Zero-1训练;
  • PT为官方的P-Tuning V2训练方法,PT-Only-Embedding表示仅对Embedding进行soft-prompt,Freeze仅训练模型后五层参数,Lora采用低秩矩阵方法训练,秩为8;
  • 由于之间训练PT在48G-A40显卡上会出现OOM,因此下面PT实验对模型开启了gradient_checkpointing_enable(),使得模型显存占用变小,但训练时长增加。
  • 训练示例:
prompt_text:你现在是一个信息抽取模型,请你帮我抽取出关系内容为\"性能故障\", \"部件故障\", \"组成\"和 \"检测工具\"的相关三元组,三元组内部用\"_\"连接,三元组之间用\\n分割。文本:
输入:故障现象:发动机水温高,风扇始终是低速转动,高速档不工作,开空调尤其如此。
输出:发动机_部件故障_水温高\n风扇_部件故障_低速转动
微调方法 PT-Only-Embedding PT Freeze Lora
显卡占用 37G 30G 24G 39G
总参数 6.259B 7.211B 6.255B 6.259B
可训练参数占比 0.0586% 13.26% 16.10% 0.0586%
训练耗时 53min 135min 112min 65min
测试结果F1 0.0 0.6283 0.5675 0.5359
测试耗时 191s 198s 180s 278s

结构分析:

  • 效果为PT>Freeze>Lora>PT-Only-Embedding
  • PT-Only-Embedding效果很不理想,发现在训练时,最后的loss仅能收敛到2.几,而其他机制可以收敛到0.几。分析原因为,输出内容形式与原有语言模型任务相差很大,仅增加额外Embedding参数,不足以改变复杂的下游任务。
  • PT方法占用显存更大,因为也增加了很多而外参数。
  • 测试耗时,由于其他方法均增加了额外参数,因此推理耗时会比Freeze方法要高。
  • 上面测试仅代表个人测试结果,并且由于生成模型生成长度对推理耗时影响很大,因此可以其他数据会有不一样的结果。
  • 模型在指定任务上微调之后,并没有丧失原有能力,例如生成“帮我写个快排算法”,依然可以生成-快排代码。
  • 由于大模型微调都采用大量instruction进行模型训练,仅采用单一的指令进行微调时,对原来其他的指令影响不大,因此并没导致原来模型的能力丧失。

很多同学在微调后出现了灾难性遗忘现象,但本项目的训练代码并没有出现,对“翻译任务”、“代码任务”、“问答任务”进行测试,采用freeze模型,可以用test_forgetting.py进行测试,具体测试效果如下:

翻译任务

代码任务

问答任务

文本生成

待补充

文本分类

待补充

About

基于ChatGLM-6B模型,进行下游具体任务微调,涉及Freeze、Lora、P-tuning等

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%