大模型微调实战:ChatGLM-6B 微调经验与开源项目汇总
分享了 ChatGLM-6B 大模型微调的实战经验,对比了 Freeze、P-Tuning 和 LoRA 三种参数高效微调方法在信息抽取任务上的表现。实验结果显示 P-Tuning V2 效果最佳,LoRA 在显存效率上具有优势,且微调过程未出现明显的灾难性遗忘。文章还汇总了可用的中文开源大模型、指令数据集及相关项目,为开发者提供技术参考和资源指引。

分享了 ChatGLM-6B 大模型微调的实战经验,对比了 Freeze、P-Tuning 和 LoRA 三种参数高效微调方法在信息抽取任务上的表现。实验结果显示 P-Tuning V2 效果最佳,LoRA 在显存效率上具有优势,且微调过程未出现明显的灾难性遗忘。文章还汇总了可用的中文开源大模型、指令数据集及相关项目,为开发者提供技术参考和资源指引。

本文总结了作者在 ChatGLM-6B 模型微调的经验,并汇总了目前开源项目及数据。在大型语言模型(LLM)迅速发展的背景下,如何高效地对模型进行领域适配成为关键问题。笔者通过实践对比了多种微调方法,发现采用单指令进行模型微调时,模型并未出现灾难性遗忘现象。本文旨在分享技术细节、实验结果及资源汇总,供开发者参考。
大型语言模型正在改变开发模式,从最初的焦虑到全面拥抱,开源社区提供了丰富的微调工具。笔者进行了多轮 ChatGLM-6B 模型的微调实践,重点对比了不同参数高效微调(PEFT)方案的效果。本次实践的核心结论是:在特定任务下,合理选择微调策略可以在保持模型原有能力的同时,显著提升下游任务表现。
模型参数量越大,对显存和算力的要求越高。目前主流的大模型微调方法主要分为三类:Freeze 方法、P-Tuning 方法和 LoRA 方法。为了验证这些方法的有效性,笔者在信息抽取任务上对 ChatGLM-6B 进行了微调。为了防止数据泄露,采用了领域比赛数据集——汽车工业故障模式关系抽取(https://www.datafountain.cn/competitions/584),随机抽取 50 条作为测试集。
详细代码见上述 GitHub 链接,该仓库已被 ChatGLM 官方收录。
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,其他任务的评价标准可根据实际需求进行修改。
技术补充: Freeze 方法虽然显存友好,但可训练参数较少,可能导致模型难以充分学习新任务的特征分布。适用于数据量较小且任务与预训练任务相似度较高的场景。
P-Tuning 方法是一种针对大模型的 Soft-Prompt 方法。它不更新模型权重,而是引入可训练的连续向量(Prompt Embedding)来引导模型生成。
参考 ChatGLM 官方代码 (https://github.com/THUDM/ChatGLM-6B/blob/main/ptuning/README.md)。
微调代码见 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 方法;为 False 时,为 P-Tuning 方法。可设置参数包含 train_path、model_dir、num_train_epochs、train_batch_size、gradient_accumulation_steps、output_dir、prompt_text、pre_seq_len 等。
启动命令示例:
CUDA_VISIBLE_DEVICES=0 deepspeed finetuning_pt.py --num_train_epochs 5 --train_batch_size 2 --pre_seq_len 16
技术补充: P-Tuning 通过引入额外的 Prompt 向量,使得模型在不更新主权重的情况下适应新任务。P-Tuning V2 通过在每一层添加投影层,增强了提示信息的表达能力,通常能获得更好的收敛效果。
LoRA (Low-Rank Adaptation) 方法是在大型语言模型上对指定参数增加额外的低秩矩阵。在模型训练过程中,仅训练额外增加的参数。当'秩值'远小于原始参数维度时,新增的低秩矩阵参数量很小,达到仅训练很小的参数就能获取较好的结果。
LoRA 论文:https://arxiv.org/abs/2106.09685 官方代码:https://github.com/microsoft/LoRA HuggingFace 封装的 peft 库:https://github.com/huggingface/peft
微调代码见 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)
可设置参数包含 lora_r、lora_alpha 等超参数。启动命令示例:
CUDA_VISIBLE_DEVICES=0 deepspeed finetuning_lora.py --num_train_epochs 5 --train_batch_size 2 --lora_r 8
注意: 对于结果需要保持一致的任务(即关掉 dropout,解码关掉 do_sample),需要保存模型的 adapter_config.json 文件中,将 inference_mode 参数修改成 false,并将模型执行 model.eval() 操作。主要原因是 ChatGLM 模型代码中未采用 Conv1D 函数,需注意推理模式的切换。
实验环境配置:最大长度为 768,Batch 大小为 2,训练轮数为 5,fp16 训练,采用 DeepSpeed 的 Zero-1 训练。
由于之前训练 PT 在 48G-A40 显卡上会出现 OOM(显存溢出),因此之前进行 PT 实验时对模型开启了 gradient_checkpointing_enable,使得模型显存占用变小,但训练时长增加。时间换空间是解决显卡资源问题的常用手段,简单玩玩还可以,如果想要模型达到最优效果或快速看到效果,建议使用更高性能的算力资源。
下面实验结果均是在租用的 80G-A100 上进行的实验,与 Github 里用的 A40 的实验结果会有些差异,主要在训练时长(纯训练速度,剔除模型保存的时间)。实际上,要训练一个大模型,多个 A100 是必不可少的,可以减少很多模型并行的操作,效果上也更好把控一些。
| 微调方法 | PT-Only-Embedding | PT | Freeze | Lora |
|---|---|---|---|---|
| 显卡占用 | 37G | 56G | 24G | 39G |
| 总参数 | 6.259B | 7.211B | 6.255B | 6.259B |
| 可训练参数占比 | 0.0586% | 13.26% | 16.10% | 0.0586% |
| 训练耗时 | 20min | 52min | 46min | 25min |
| 测试结果 F1 | 0.0 | 0.6283 | 0.5675 | 0.5359 |
上面测试仅代表个人测试结果。很多同学在微调后出现了灾难性遗忘现象,但我这边并没有出现。对'翻译任务'、'代码任务'、'问答任务'进行测试,采用 freeze 模型,可以用 test_forgetting.py 进行测试。
虽然市面上出来很多大模型,但 Open 且中文可直接使用的并不多。以下对中文开源大模型、数据集和项目进行汇总,方便开发者快速上手。
直接可微调,无需指令增量训练:
原始模型多语言 or 英文,需要中文指令数据集增量训练:
下面中文指令集,大多数从 Alpaca 翻译而来,请看下面项目中 data 目录。目前通过 ChatGPT 或者 GPT4 作为廉价标注工为自己的数据进行数据标注是一个不错的思路。
总结下面较火的开源项目:
目前各大厂的大模型陆陆续续放出,堪称百家争鸣!个人玩家也是全面拥抱,想尽一切办法来训练微调大模型。只愿大家以后可以实现'大模型'自由。愿再无'model-as-a-service'。
在实际应用中,建议根据硬件资源选择合适的微调策略。如果显存充足,可以尝试全量微调或 P-Tuning V2 以获得最佳效果;如果资源受限,LoRA 或 Freeze 是性价比更高的选择。此外,数据质量对微调效果至关重要,构建高质量的指令数据集往往比调整超参数更能提升模型性能。未来随着 PEFT 技术的演进,预计会有更多轻量级且高效的微调方案涌现,降低大模型落地的门槛。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online