本文为原创技术分享,仅用于技术学习交流。

适用场景:个人开发者、学生、算法爱好者想微调专属大模型,但显卡显存不够(只有 16GB),QLoRA 技术正好解决这个痛点,本文亲测可跑。

一、痛点场景:大模型微调,你是否也卡在这里?

现在 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 size

4

显存占用

~14GB

训练时间

~3 小时

训练完之后,模型能够学到你给的对话风格和领域知识,效果接近全参数微调,但是显存只用了 16GB,普通消费级显卡就能跑。

三、实战代码:完整可运行

环境依赖安装

pip install torch transformers accelerate peft bitsandbytes huggingface_hub

pip install git+https://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_4bit=BNB_4BIT,
        bnb_4bit_use_double_quant=BNB_4BIT_USE_DOUBLE_QUANTIZATION,
        bnb_4bit_quant_type=BNB_4BIT_QUANT_TYPE,
    )

    # ============ 加载模型和分词器 ============
    model = AutoModelForCausalLM.from_pretrained(
        MODEL_NAME,
        quantization_config=bnb_config,
        device_map="auto",
        trust_remote_code=True,
    )

    tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
    tokenizer.pad_token = tokenizer.eos_token
    tokenizer.padding_side = "right"  # 避免警告

    # ============ LoRA 配置 ============
    lora_config = LoraConfig(
        r=LORA_R,
        lora_alpha=LORA_ALPHA,
        target_modules=LORA_TARGET_MODULES,
        lora_dropout=LORA_DROPOUT,
        bias="none",
        task_type="CAUSAL_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_files=DATASET_PATH, split="train")

    # ============ 训练配置 ============
    training_args = TrainingArguments(
        output_dir=OUTPUT_DIR,
        per_device_train_batch_size=BATCH_SIZE,
        gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,
        learning_rate=LEARNING_RATE,
        num_train_epochs=NUM_EPOCHS,
        weight_decay=0.01,
        logging_steps=10,
        save_strategy="epoch",
        fp16=True,
        push_to_hub=False,
        report_to="none",
    )

    # ============ SFT 训练 ============
    trainer = SFTrainer(
        model=model,
        train_dataset=dataset,
        peft_config=lora_config,
        dataset_text_field="text",
        max_seq_length=MAX_SEQ_LENGTH,
        tokenizer=tokenizer,
        args=training_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_config=bnb_config,
        device_map="auto",
        trust_remote_code=True,
    )
    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 login

login("你的-hf-token")

第二步:准备数据集

把你的训练数据按照上面的 jsonl 格式整理好,路径填到代码里。

第三步:开始训练

直接运行:
 

python qlora_finetune_llama3.py




然后就等训练完成,一般一千条样本三个小时左右。

第四步:推理测试

训练完加载 LoRA 权重就可以聊天了:
 

from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline

model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")

# 加载 LoRA 权重...

pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, device_map="auto")

prompt = """<|system|>你是我的专属助手。<|end|><|user|>你好!<|end|><|assistant|>"""

outputs = pipe(prompt, max_new_tokens=512)

print(outputs[0]["generated_text"])

五、避坑指南:我踩过的这些坑

坑 1:显存溢出 OOM

问题: 运行直接报 CUDA out of memory。

解决:

  • 减小 MAX_SEQ_LENGTH,比如从 1024 改成 512

  • 减小 BATCH_SIZE,从 4 改成 2 甚至 1

  • 开启梯度检查点:training_args 里加 gradient_checkpointing=True

  • 按照本文配置,16GB 显存 512 长度 batch=4 是没问题的

坑 2:bitsandbytes 版本不对

问题: 报错 Could not load bitsandbytes。

解决: 一定要装最新版本:
 

pip uninstall bitsandbytes -y

pip install bitsandbytes --upgrade




如果还是不行,检查你的 CUDA 版本是否匹配。

坑 3:Llama 3 分词器错误

问题: 报错 pad_token is None。

解决: 代码里一定要加这两行:
 

tokenizer.pad_token = tokenizer.eos_token

tokenizer.padding_side = "right"




Llama 3 原生分词器没有 pad_token,手动设置一下就好了。

坑 4:训练完合并权重报错

问题: 合并 LoRA 和基础模型的时候显存溢出。

解决: 合并的时候也需要显存,如果不够,可以分步来:先保存 LoRA,部署推理的时候动态加载,不一定非要合并。

坑 5:学习率太高/太低

问题: 训练不收敛,或者模型学坏了。

解决: QLoRA 推荐学习率就是 2e-4,不要瞎调,这个参数亲测好用。如果你的数据集比较小,可以降到 1e-4,增大 epoch 数量。

QLoRA 真的是个人玩家福音,16GB 显存就能微调 Llama 3 8B,效果还不差。如果你:

  • 想做一个自己专属的大模型

  • 没有高端显卡,只有 16GB 消费级显卡

  • 不想花大价钱租云服务器

这个方案非常适合你。代码完整可直接运行,按照步骤来就能跑通。

免责声明: 本文项目仅供技术学习交流使用,请遵守 Meta Llama 3 社区许可协议。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐