大模型微调实战:QLoRA 单 GPU 微调 Llama 3 专属模型,显存 16GB 就能跑

张开发
2026/4/12 23:29:10 15 分钟阅读

分享文章

大模型微调实战:QLoRA 单 GPU 微调 Llama 3 专属模型,显存 16GB 就能跑
本文为原创技术分享仅用于技术学习交流。适用场景个人开发者、学生、算法爱好者想微调专属大模型但显卡显存不够只有 16GBQLoRA 技术正好解决这个痛点本文亲测可跑。一、痛点场景大模型微调你是否也卡在这里现在 Llama 3 开源了大家都想微调一个自己的专属模型比如微调一个专属写作助手把自己的领域知识灌进去做一个垂直领域的问答机器人但是全参数微调一下就要几十 GB 显存普通人哪有这么好的显卡A100 一天租金都要好几十个人玩家玩不起。QLoRA 论文出来说 4-bit 量化 LoRA 可以达到全微调接近的效果还能省很多显存。网上都说好但真正从环境配置到训练完成的 step by step 教程不多很多人跟着教程走还是会卡。这篇文章就带大家用 16GB 显存微调 Llama 3 8B从环境配置到训练脚本踩过的坑都给你写清楚。二、最终效果展示我用 16GB 显存的 RTX 3080 成功跑完了微调项目参数基础模型Llama 3 8B Instruct量化4-bit NF4训练数据1k 条中文对话样本Batch size4显存占用~14GB训练时间~3 小时训练完之后模型能够学到你给的对话风格和领域知识效果接近全参数微调但是显存只用了 16GB普通消费级显卡就能跑。三、实战代码完整可运行环境依赖安装pip install torch transformers accelerate peft bitsandbytes huggingface_hubpip install githttps://github.com/huggingface/trl.git#!/usr/bin/env python3 # -*- coding: utf-8 -*- QLoRA 微调 Llama 3 示例 显存要求: 16GB 足够 import torch from datasets import load_dataset from transformers import ( AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments, pipeline, ) from peft import LoraConfig, PeftModel, get_peft_model from trl import SFTTrainer # 配置 MODEL_NAME meta-llama/Meta-Llama-3-8B-Instruct DATASET_PATH your_dataset.jsonl # 你的数据集每条一个 text 字段 OUTPUT_DIR ./llama3-8b-qlora # QLoRA 配置 LORA_R 8 LORA_ALPHA 16 LORA_DROPOUT 0.05 LORA_TARGET_MODULES [q_proj, v_proj] # 4-bit 量化配置 BNB_4BIT True BNB_4BIT_USE_DOUBLE_QUANTIZATION True BNB_4BIT_QUANT_TYPE nf4 # 训练参数 BATCH_SIZE 4 GRADIENT_ACCUMULATION_STEPS 4 LEARNING_RATE 2e-4 NUM_EPOCHS 3 MAX_SEQ_LENGTH 512 def main(): # 4-bit 量化配置 bnb_config BitsAndBytesConfig( load_in_4bitBNB_4BIT, bnb_4bit_use_double_quantBNB_4BIT_USE_DOUBLE_QUANTIZATION, bnb_4bit_quant_typeBNB_4BIT_QUANT_TYPE, ) # 加载模型和分词器 model AutoModelForCausalLM.from_pretrained( MODEL_NAME, quantization_configbnb_config, device_mapauto, trust_remote_codeTrue, ) tokenizer AutoTokenizer.from_pretrained(MODEL_NAME) tokenizer.pad_token tokenizer.eos_token tokenizer.padding_side right # 避免警告 # LoRA 配置 lora_config LoraConfig( rLORA_R, lora_alphaLORA_ALPHA, target_modulesLORA_TARGET_MODULES, lora_dropoutLORA_DROPOUT, biasnone, task_typeCAUSAL_LM, ) model get_peft_model(model, lora_config) model.print_trainable_parameters() # 输出应该是: trainable params: ~40M / 8B → 0.5% 左右 # 加载数据集 # 数据集格式: jsonl 每一行: {text: 完整的对话文本} dataset load_dataset(json, data_filesDATASET_PATH, splittrain) # 训练配置 training_args TrainingArguments( output_dirOUTPUT_DIR, per_device_train_batch_sizeBATCH_SIZE, gradient_accumulation_stepsGRADIENT_ACCUMULATION_STEPS, learning_rateLEARNING_RATE, num_train_epochsNUM_EPOCHS, weight_decay0.01, logging_steps10, save_strategyepoch, fp16True, push_to_hubFalse, report_tonone, ) # SFT 训练 trainer SFTrainer( modelmodel, train_datasetdataset, peft_configlora_config, dataset_text_fieldtext, max_seq_lengthMAX_SEQ_LENGTH, tokenizertokenizer, argstraining_args, ) # 开始训练 trainer.train() # 保存 LoRA 权重 trainer.model.save_pretrained(OUTPUT_DIR) print(f训练完成权重保存到: {OUTPUT_DIR}) def merge_and_save(base_model_path, lora_path, output_path): 合并基础模型和 LoRA 权重保存完整模型 from transformers import BitsAndBytesConfig base_model AutoModelForCausalLM.from_pretrained( base_model_path, quantization_configbnb_config, device_mapauto, trust_remote_codeTrue, ) model PeftModel.from_pretrained(base_model, lora_path) model model.merge_and_unload() tokenizer AutoTokenizer.from_pretrained(base_model_path) model.save_pretrained(output_path) tokenizer.save_pretrained(output_path) print(f合并完成完整模型保存到: {output_path}) if __name__ __main__: main()数据集格式要求你的训练数据保存为 dataset.jsonl每行一个样本按照 Llama 3 的对话模板整理{text: |system|你是一个专业的Python开发助手。|end||user|如何实现快速排序|end||assistant这里是我的回答...|end|}四、步骤讲解从零到一跑起来第一步获取 Llama 3 权重需要在 Hugging Face 申请 Llama 3 授权通过之后from huggingface_hub import loginlogin(你的-hf-token)第二步准备数据集把你的训练数据按照上面的 jsonl 格式整理好路径填到代码里。第三步开始训练直接运行python qlora_finetune_llama3.py然后就等训练完成一般一千条样本三个小时左右。第四步推理测试训练完加载 LoRA 权重就可以聊天了from transformers import AutoModelForCausalLM, AutoTokenizer, pipelinemodel AutoModelForCausalLM.from_pretrained(meta-llama/Meta-Llama-3-8B-Instruct)# 加载 LoRA 权重...pipe pipeline(text-generation, modelmodel, tokenizertokenizer, device_mapauto)prompt |system|你是我的专属助手。|end||user|你好|end||assistant|outputs pipe(prompt, max_new_tokens512)print(outputs[0][generated_text])五、避坑指南我踩过的这些坑坑 1显存溢出 OOM问题 运行直接报 CUDA out of memory。解决减小 MAX_SEQ_LENGTH比如从 1024 改成 512减小 BATCH_SIZE从 4 改成 2 甚至 1开启梯度检查点training_args 里加 gradient_checkpointingTrue按照本文配置16GB 显存 512 长度 batch4 是没问题的坑 2bitsandbytes 版本不对问题 报错 Could not load bitsandbytes。解决 一定要装最新版本pip uninstall bitsandbytes -ypip install bitsandbytes --upgrade如果还是不行检查你的 CUDA 版本是否匹配。坑 3Llama 3 分词器错误问题 报错 pad_token is None。解决 代码里一定要加这两行tokenizer.pad_token tokenizer.eos_tokentokenizer.padding_side rightLlama 3 原生分词器没有 pad_token手动设置一下就好了。坑 4训练完合并权重报错问题 合并 LoRA 和基础模型的时候显存溢出。解决 合并的时候也需要显存如果不够可以分步来先保存 LoRA部署推理的时候动态加载不一定非要合并。坑 5学习率太高/太低问题 训练不收敛或者模型学坏了。解决 QLoRA 推荐学习率就是 2e-4不要瞎调这个参数亲测好用。如果你的数据集比较小可以降到 1e-4增大 epoch 数量。QLoRA 真的是个人玩家福音16GB 显存就能微调 Llama 3 8B效果还不差。如果你想做一个自己专属的大模型没有高端显卡只有 16GB 消费级显卡不想花大价钱租云服务器这个方案非常适合你。代码完整可直接运行按照步骤来就能跑通。免责声明 本文项目仅供技术学习交流使用请遵守 Meta Llama 3 社区许可协议。

更多文章