# 1. 大模型微调概述
# 1.1 什么是大模型微调
大模型微调是一种迁移学习技术,通过在预训练模型的基础上进行额外训练,使其适应特定任务或领域。这一过程包括选择预训练模型,准备目标任务的数据,调整模型结构,进行微调训练,以及评估和部署。微调的优点在于节省时间和资源,提高性能,但也存在过拟合风险和模型选择与调整的复杂性。总体而言,它是一种强大的技术,特别适用于数据受限或计算资源有限的情况。
在 OpenAI 发布的 ChatGPT 中,就主要应用了大模型微调技术,从而获得了惊艳全世界的效果。
# 1.2 大模型微调的方式
# 1.2.1 全量微调
大模型全量微调通过在预训练的大型模型基础上调整所有层和参数,使其适应特定任务。这一过程使用较小的学习率和特定任务的数据进行,可以充分利用预训练模型的通用特征,但可能需要更多的计算资源。
# 1.2.2 参数高效微调
PEFT技术旨在通过最小化微调参数的数量和计算复杂度,来提高预训练模型在新任务上的性能,从而缓解大型预训练模型的训练成本。这样一来,即使计算资源受限,也可以利用预训练模型的知识来迅速适应新任务,实现高效的迁移学习。因此,PEFT技术可以在提高模型效果的同时,大大缩短模型训练时间和计算成本,让更多人能够参与到深度学习研究中来。
Prefix Tuning:与full fine-tuning更新所有参数的方式不同,该方法是在输入token之前构造一段任务相关的virtual tokens作为Prefix,然后训练的时候只更新Prefix部分的参数,而Transformer中的其他部分参数固定。该方法其实和构造Prompt类似,只是Prompt是人为构造的“显式”的提示,并且无法更新参数,而Prefix则是可以学习的“隐式”的提示。同时,为了防止直接更新Prefix的参数导致训练不稳定的情况,他们在Prefix层前面加了MLP结构(相当于将Prefix分解为更小维度的Input与MLP的组合后输出的结果),训练完成后,只保留Prefix的参数。
Prompt Tuning:该方法可以看作是Prefix Tuning的简化版本,只在输入层加入prompt tokens,并不需要加入MLP进行调整来解决难训练的问题。随着预训练模型参数量的增加,Prompt Tuning的方法会逼近fine-tuning的结果。
P-Tuning:该方法主要是为了解决这样一个问题:大模型的Prompt构造方式严重影响下游任务的效果。P-Tuning将Prompt转换为可以学习的Embedding层,并用MLP+LSTM的方式来对prompt embedding进行一层处理。
P-Tuning v2:让Prompt Tuning能够在不同参数规模的预训练模型、针对不同下游任务的结果上都达到匹敌Fine-tuning的结果。相比Prompt Tuning和P-tuning的方法,P-Tuning v2方法在多层加入了Prompts tokens作为输入,带来两个方面的好处:
1)带来更多可学习的参数(从P-tuning和Prompt Tuning的0.1%增加到0.1%-3%),同时也足够参数高效。
2)加入到更深层结构中的Prompt能给模型预测带来更直接的影响。
Adapter Tuning:该方法设计了Adapter结构(首先是一个down-project层将高维度特征映射到低维特征,然后过一个非线形层之后,再用一个up-project结构将低维特征映射回原来的高维特征;同时也设计了skip-connection结构,确保了在最差的情况下能够退化为identity),并将其嵌入Transformer的结构里面,在训练时,固定住原来预训练模型的参数不变,只对新增的Adapter结构进行微调。同时为了保证训练的高效性(也就是尽可能少的引入更多参数)。
LoRA:在涉及到矩阵相乘的模块,引入A、B这样两个低秩矩阵模块去模拟full fine-tuning的过程,相当于只对语言模型中起关键作用的低秩本质维度进行更新。
# 1.3 常见的参数高效微调技术
# 1.3.1 LoRA技术
LoRA,全称Low-Rank Adaptation of Large Language Models,直译大语言模型的低阶适应,这是微软的研究人员为了解决大语言模型微调而开发的一项技术。
- 项目地址:https://github.com/microsoft/LoRA (opens new window)
- 论文地址:https://arxiv.org/abs/2106.09685 (opens new window)
比如,GPT-3有1750亿参数,为了让它能干特定领域的活儿,需要做微调,但是如果直接对GPT-3做微调,成本太高太麻烦了。LoRA的做法是,冻结预训练好的模型权重参数,然后在每个Transformer(Transforme就是GPT的那个T)块里注入可训练的层,由于不需要对模型的权重参数重新计算梯度,所以,大大减少了需要训练的计算量。研究发现,LoRA的微调质量与全模型微调相当,就好比是大模型的一个小模型。
# 1.3.2 Freeze技术
Freeze 方法,即参数冻结,对原始模型部分参数进行冻结操作,仅训练部分参数,以达到在单卡或不进行 TP 或 PP 操作,就可以对大模型进行训练。在语言模型模型微调中,Freeze 微调方法仅微调 Transformer 后几层的全连接层参数,而冻结其它所有参数。
# 1.3.3 P-Tuning v2技术
P-Tuning v2 通过在每一层加入Prompts tokens,实现了更多的可学习参数和更深层结构中的Prompt对模型预测的直接影响,提高了模型的灵活性和效率。
- 项目地址:https://github.com/THUDM/P-tuning-v2 (opens new window)
- 论文地址:https://arxiv.org/abs/2110.07602 (opens new window)

# 2. 大模型微调相关项目
# 2.1 大模型微调开源项目
作者后来将各种大模型的高效微调,统一到了一个项目里:https://github.com/hiyouga/LLaMA-Factory (opens new window)
截止2023年10月29日,已经支持微调的模型型号有:
Model | Model size | Default module | Template |
---|---|---|---|
LLaMA (opens new window) | 7B/13B/33B/65B | q_proj,v_proj | - |
LLaMA-2 (opens new window) | 7B/13B/70B | q_proj,v_proj | llama2 |
BLOOM (opens new window) | 560M/1.1B/1.7B/3B/7.1B/176B | query_key_value | - |
BLOOMZ (opens new window) | 560M/1.1B/1.7B/3B/7.1B/176B | query_key_value | - |
Falcon (opens new window) | 7B/40B | query_key_value | - |
Baichuan (opens new window) | 7B/13B | W_pack | baichuan |
Baichuan2 (opens new window) | 7B/13B | W_pack | baichuan2 |
InternLM (opens new window) | 7B/20B | q_proj,v_proj | intern |
Qwen (opens new window) | 7B/14B | c_attn | chatml |
ChatGLM3 (opens new window) | 6B | query_key_value | chatglm3 |
Phi-1.5 (opens new window) | 1.3B | Wqkv | - |
# 2.1.1 ChatGLM大模型微调
- 项目简介: 基于 PEFT 的高效 ChatGLM 微调,兼容 ChatGLM 与 ChatGLM-2 模型,支持 Full Tuning、LoRA、P-Tuning V2、Freeze等微调方式。
- 项目地址:https://github.com/hiyouga/ChatGLM-Efficient-Tuning (opens new window)
# 2.1.2 LLaMA大模型微调
- 项目简介:基于 PEFT 的高效 LLaMA 微调,兼容 LLaMA 与 LLaMA-2 模型。
- 项目地址:https://github.com/hiyouga/LLaMA-Efficient-Tuning (opens new window)
# 2.2 大模型微调开源数据集
典型的数据集格式:{"instruction": "", "input": "", "output": ""}
,目前通用的中文微调数据集:
数据集 | 内容 |
---|---|
COIG (opens new window) | Chinese Open Instruction Generalist project |
Stanford Alpaca (Chinese) (opens new window) | Alpaca 数据集中文翻译(ChatGPT 辅助翻译) |
BELLE (opens new window) | BELLE 项目的中文数据集(ChatGPT 生成) |
GuanacoDataset (opens new window) | Guannaco 模型的对话数据集 |
WebQA(zh) (opens new window) | 中文网络问答 |
pCLUE (opens new window) | 基于提示的大规模预训练数据集,用于多任务学习和零样本学习 |
注:很多开源数据集里,问题放在 instruction 上,而 input 是空的,这是正常情况,数据字段也没有对应错。这是因为 instruction 与 input 是拼一起用的。比如:“翻译以下这段话:xxx”,翻译以下这段话是 instruction,xxx 是 input。
# 3. ChatGLM2的高效微调
实验环境:租用的揽睿星舟的GPU服务器,NVIDIA RTX 3090 / 24GB,Python 3.10.6, CUDA 11.7
关于GPU服务器租用、Jupyter及HuggingFace的使用,这里就不赘述了,详见我的另一篇博客:常用深度学习平台的使用指南 (opens new window)
# 3.1 拉取仓库并安装依赖
拉取ChatGLM-Efficient-Tuning项目并安装依赖。
$ git clone https://github.com/hiyouga/ChatGLM-Efficient-Tuning.git
$ cd ChatGLM-Efficient-Tuning
$ pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/
$ pip3 config set install.trusted-host mirrors.aliyun.com
$ pip3 install -r requirements.txt
2
3
4
5
# 3.2 单GPU微调训练模型
该项目支持使用多个 GPU 进行分布式微调,但我这里的服务器环境只有一个GPU,就不尝试了。
创建个checkpoint目录用于保存微调后的模型。
$ mkdir /home/user/checkpoint
制作测试数据集(复制一份alpaca_gpt4_data_zh.json数据集,就保留几条数据),然后在 /home/user/ChatGLM-Efficient-Tuning/data/dataset_info.json
文件里再加一条配置。
"alpaca_gpt4_zh_test": {
"file_name": "alpaca_gpt4_data_zh_test.json",
"file_sha1": "3eaa3bda364ccdd59925d7448a698256c31ef846"
},
2
3
4
这里使用官方示例的数据集和参数运行(为了加快训练速度,使用刚刚制作的测试数据集,规模进行了阉割):
$ cd /home/user/ChatGLM-Efficient-Tuning
$ CUDA_VISIBLE_DEVICES=0 python3 src/train_bash.py \
--stage sft \
--model_name_or_path THUDM/chatglm2-6b \
--do_train \
--dataset alpaca_gpt4_zh_test \
--finetuning_type lora \
--output_dir /home/user/checkpoint \
--per_device_train_batch_size 4 \
--gradient_accumulation_steps 4 \
--lr_scheduler_type cosine \
--logging_steps 10 \
--save_steps 1000 \
--learning_rate 5e-5 \
--num_train_epochs 3.0 \
--plot_loss \
--fp16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
注意事项:GPU服务器厂商提供的预训练模型在/home/user/imported_models/chatglm2-6b/huggingface/THUDM/chatglm2-6b
目录下,但是这个模型亲测没法用。报错“ValueError: Please update the model files of ChatGLM2-6B.”。模型文件应该从 https://huggingface.co/THUDM/chatglm2-6b/tree/main (opens new window) 下载,我这里直接填写了 THUDM/chatglm2-6b,程序执行时会自动下载模型。
常用参数说明:这里只解释官方命令里用到的,其余的自己看源码里的说明吧。
--stage sft:在训练过程中要执行的阶段。(默认值: sft,可选值:sft、rm、ppo)
--model_name_or_path:模型文件名称(例如THUDM/chatglm2-6b,从huggingface下载)或者本地路径
--do_train:是否进行训练。(默认值:False)
--dataset:要使用的提供的数据集名称,用逗号分隔多个数据集。(默认值:alpaca_zh)
--finetuning_type:要使用的微调方法。(默认值: lora,可选值:freeze,p_tuning,lora,full)
--output_dir:用于输出训练后模型checkpoint的目录。(默认值:None)
--per_device_train_batch_size:每个GPU/TPU核心/CPU用于训练的批量大小。(默认值:8)
--gradient_accumulation_steps:在执行向后/更新传递之前累积的更新步数。(默认值:1)
--lr_scheduler_type:要使用的调度程序类型。(默认值:linear,可选值:linear,cosine,cosine_with_restarts,polynomial,constant,constant_with_warmup,inverse_sqrt,reduce_lr_on_plateau)
--logging_steps:每X次更新步骤记录一次。应为整数或范围为[0,1)的浮点数。如果小于1,将被解释为总训练步骤的比例。(默认值:500)
--save_steps:每X次更新步骤保存一个检查点。应为整数或范围为[0,1)的浮点数。如果小于1,将被解释为总训练步骤的比例。(默认值:500)
--learning_rate:AdamW的初始学习率。(默认值:5e-05)
--num_train_epochs:执行的总训练时代数。(默认值:3.0)
--plot_loss:是否在微调后绘制训练损失。(默认值:False)
--fp16:是否使用fp16(混合)精度而不是32位。(默认值:False)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
训练过程:微调训练过程所需时间较长,具体取决于所选的基础大模型、微调方式、参数设置以及数据集规模。如果只是为了体验流程的话,可以专门弄个两三条的测试数据集,几秒就能跑完。
训练完的模型,被保存在 /home/user/checkpoint
目录,文件列表如下:
README.md 88 B
adapter_config.json 435 B
adapter_model.bin 7.45 MB
all_results.json 162 B
finetuning_args.json 254 B
train_results.json 162 B
trainer_log.jsonl 224 B
trainer_state.json 578 B
training_args.bin 3.23 KB
2
3
4
5
6
7
8
9
# 3.3 对微调后的模型进行指标评估
指标评估(BLEU分数和汉语ROUGE分数),创建个eval_result目录用于保存微调模型的指标评估结果。
$ mkdir /home/user/eval_result
$ cd /home/user/ChatGLM-Efficient-Tuning
$ CUDA_VISIBLE_DEVICES=0 python3 src/train_bash.py \
--stage sft \
--model_name_or_path THUDM/chatglm2-6b \
--do_eval \
--dataset alpaca_gpt4_zh_test \
--finetuning_type lora \
--checkpoint_dir /home/user/checkpoint \
--output_dir /home/user/eval_result \
--per_device_eval_batch_size 8 \
--max_samples 50 \
--predict_with_generate
2
3
4
5
6
7
8
9
10
11
12
13
评估过程:因为我这里使用的是只有3条数据的测试数据集,所以评估过程也很快。
评估结果:保存的评估结果JSON文件也是这个内容。
***** eval metrics *****
eval_accuracy = 0.0
eval_bleu-4 = 9.1284
eval_rouge-1 = 36.5252
eval_rouge-2 = 10.9344
eval_rouge-l = 22.3205
eval_runtime = 0:00:06.50
eval_samples_per_second = 0.461
eval_steps_per_second = 0.154
2
3
4
5
6
7
8
9
# 3.4 使用微调后的模型进行预测
创建个predict_result目录用于保存微调模型的预测结果。
$ mkdir /home/user/predict_result
$ cd /home/user/ChatGLM-Efficient-Tuning
$ CUDA_VISIBLE_DEVICES=0 python3 src/train_bash.py \
--stage sft \
--model_name_or_path THUDM/chatglm2-6b \
--do_predict \
--dataset alpaca_gpt4_zh_test \
--finetuning_type lora \
--checkpoint_dir /home/user/checkpoint \
--output_dir /home/user/predict_result \
--per_device_eval_batch_size 8 \
--max_samples 100 \
--predict_with_generate
2
3
4
5
6
7
8
9
10
11
12
13
预测过程:因为我这里使用的是只有3条数据的测试数据集,所以预测过程也很快。
预测结果,被保存在 /home/user/predict_result
目录,文件列表如下:
all_results.json 311 B
generated_predictions.jsonl 3.93 KB
predict_results.json 311 B
2
3
其中 generated_predictions.jsonl 的内容如下:
{
"label": "以下是保持健康的三个提示:\n\n1. 保持身体活动。每天做适当的身体运动,如散步、跑步或游泳,能促进心血管健康,增强肌肉力量,并有助于减少体重。\n\n2. 均衡饮食。每天食用新鲜的蔬菜、水果、全谷物和脂肪含量低的蛋白质食物,避免高糖、高脂肪和加工食品,以保持健康的饮食习惯。\n\n3. 睡眠充足。睡眠对人体健康至关重要,成年人每天应保证 7-8 小时的睡眠。良好的睡眠有助于减轻压力,促进身体恢复,并提高注意力和记忆力。",
"predict": "保持健康对于我们的身体和心理健康都非常重要。以下是三个保持健康的提示:\n\n1. 积极心态:积极心态可以帮助我们减轻压力,增强自信心,提高心理韧性,从而有助于保持心理健康。\n\n2. 均衡饮食:均衡饮食是保持健康的关键,我们应该吃各种颜色的蔬菜和水果,适量摄入优质蛋白质、健康脂肪和碳水化合物,避免过度食用或饮用高热量、高脂肪和高糖分的食物。\n\n3. 充足睡眠:睡眠是恢复身体和大脑功能的重要环节,我们应该尽量保证每晚7-8小时的睡眠时间,并创造一个安静、舒适的睡眠环境,避免过度使用电子设备、过度饮食和过度运动等不良睡眠习惯。"
}{
"label": "三原色通常指的是红色、绿色和蓝色(RGB)。它们是通过加色混合原理创建色彩的三种基础颜色。在以发光为基础的显示设备中(如电视、计算机显示器、智能手机和平板电脑显示屏), 三原色可混合产生大量色彩。其中红色和绿色可以混合生成黄色,红色和蓝色可以混合生成品红色,蓝色和绿色可以混合生成青色。当红色、绿色和蓝色按相等比例混合时,可以产生白色或灰色。\n\n此外,在印刷和绘画中,三原色指的是以颜料为基础的红、黄和蓝颜色(RYB)。这三种颜色用以通过减色混合原理来创建色彩。不过,三原色的具体定义并不唯一,不同的颜色系统可能会采用不同的三原色。",
"predict": "三原色是红色、绿色和蓝色,分别对应波长范围为约620-750纳米的红光、约495-570纳米的绿光和约450-495纳米的蓝光。在彩色显示、打印和电视技术中,我们通常使用红、绿、蓝三原色作为基本颜色,通过它们的不同组合可以产生各种颜色,这种方式也被称为“加色混合”。"
}{
"label": "原子是物质的基本单位,它由三种基本粒子组成:质子、中子和电子。质子和中子形成原子核,位于原子中心,核外的电子围绕着原子核运动。\n\n原子结构具有层次性。原子核中,质子带正电,中子不带电(中性)。原子核非常小且致密,占据了原子总质量的绝大部分。电子带负电,通常围绕核运动,形成若干层次,称为壳层或电子层。电子数量与质子数量相等,使原子呈电中性。\n\n电子在每个壳层中都呈规律分布,并且不同壳层所能容纳的电子数也不同。在最里面的壳层一般只能容纳2个电子,其次一层最多可容纳8个电子,再往外的壳层可容纳的电子数逐层递增。\n\n原子核主要受到两种相互作用力的影响:强力和电磁力。强力的作用范围非常小,主要限制在原子核内,具有极强的吸引作用,使核子(质子和中子)紧密结合在一起。电磁力的作用范围较大,主要通过核外的电子与原子核相互作用,发挥作用。\n\n这就是原子的基本结构。原子内部结构复杂多样,不同元素的原子核中质子、中子数量不同,核外电子排布分布也不同,形成了丰富多彩的化学世界。",
"predict": "原子由位于原子核中的质子与核外电子组成。质子带正电荷,电子带负电荷,质子与电子数目相等。因此,原子的结构可以用质子、中子、电子和核来描述。"
}
2
3
4
5
6
7
8
9
10
# 3.5 导出微调后的模型
创建个predict_result目录用于保存微调后的模型。
$ mkdir /home/user/export_models
$ cd /home/user/ChatGLM-Efficient-Tuning
$ python3 src/export_model.py \
--model_name_or_path THUDM/chatglm2-6b \
--finetuning_type lora \
--checkpoint_dir /home/user/checkpoint \
--output_dir /home/user/export_models
2
3
4
5
6
7
导出过程:大概耗时1min,将微调后的模型导出来了。
导出模型,被保存在 /home/user/export_models
目录,文件列表如下:
config.json 1.38 KB
configuration_chatglm.py 2.25 KB
generation_config.json 111 B
modeling_chatglm.py 49.55 KB
pytorch_model-00001-of-00015.bin 932.95 MB
pytorch_model-00002-of-00015.bin 810.33 MB
pytorch_model-00003-of-00015.bin 777.67 MB
pytorch_model-00004-of-00015.bin 777.67 MB
pytorch_model-00005-of-00015.bin 777.67 MB
pytorch_model-00006-of-00015.bin 777.67 MB
pytorch_model-00007-of-00015.bin 777.67 MB
pytorch_model-00008-of-00015.bin 777.67 MB
pytorch_model-00009-of-00015.bin 777.67 MB
pytorch_model-00010-of-00015.bin 777.67 MB
pytorch_model-00011-of-00015.bin 777.67 MB
pytorch_model-00012-of-00015.bin 777.67 MB
pytorch_model-00013-of-00015.bin 777.67 MB
pytorch_model-00014-of-00015.bin 777.67 MB
pytorch_model-00015-of-00015.bin 827.70 MB
pytorch_model.bin.index.json 20.00 KB
quantization.py 14.35 KB
special_tokens_map.json 3 B
tokenization_chatglm.py 9.84 KB
tokenizer.model 994.54 KB
tokenizer_config.json 325 B
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 4. 参考资料
[1] 使用 Amazon SageMaker 微调和部署 ChatGLM 模型 from Amazon (opens new window)
[2] 人工智能大语言模型微调技术:SFT 监督微调、LoRA 微调方法、P-tuning v2 微调方法、Freeze 监督微调方法 from 稀土掘金 (opens new window)
[3] 大模型训练数据集介绍 from 知乎 (opens new window)
[4] 大模型LLM-微调经验分享&总结 from 知乎 (opens new window)
[5] 大模型参数高效微调技术原理综述(一)-背景、参数高效微调简介 from 吃果冻不吐果冻皮 (opens new window)
[6] 大模型参数高效微调技术原理综述(二)-BitFit、Prefix Tuning、Prompt Tuning from 吃果冻不吐果冻皮 (opens new window)
[7] 大模型参数高效微调技术原理综述(三)-P-Tuning、P-Tuning v2 from 吃果冻不吐果冻皮 (opens new window)
[8] 大模型参数高效微调技术原理综述(四)-Adapter Tuning及其变体 from 吃果冻不吐果冻皮 (opens new window)
[9] 大模型参数高效微调技术原理综述(五)-LoRA、AdaLoRA、QLoRA from 吃果冻不吐果冻皮 (opens new window)
[10] 大模型参数高效微调技术原理综述(六)-MAM Adapter、UniPELT from 吃果冻不吐果冻皮 (opens new window)
[11] 大模型实践总结 from 吃果冻不吐果冻皮 (opens new window)
[12] 分享大模型相关技术原理以及实战经验 from 吃果冻不吐果冻皮 (opens new window)
[13] 大模型微调方法综述 from 古月居 (opens new window)
[14] 落地领域大模型应知必会 (1) :主要微调方法总览 from 稀土掘金 (opens new window)
[15] 多模态大型语言模型的最新论文和数据集 from Github (opens new window)
[16] 大语言模型(LLM)微调技术笔记 from Github (opens new window)
[17] LLM大模型 指令微调、peft高效参数微调 from CSDN (opens new window)
[18] 人工智能大语言模型微调技术:SFT 、LoRA 、Freeze 监督微调方法 from Bilibili (opens new window)
[19] LLM时代,数据为王,19个开源数据集下载网站汇总 from 吃果冻不吐果冻皮 (opens new window)