前言:在开源模型如火如荼发展的今天,我们该怎么高效微调大模型呢?今天分享一个“黑科技”工具——Unsloth。
它通过自定义内核优化,能实现 2 倍的训练速度并减少 60% 的显存占用。本文将手把手教你如何使用 QLoRA 在 FineTome-100k 数据集上完成一次高质量的指令微调。
一、 环境准备:安装 Unsloth
Unsloth 对环境有特殊要求,建议在 Linux 或 WSL2 环境下运行。
Bash
# 安装 Unsloth 核心库及相关依赖
!pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
!pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes
二、 模型加载:4-bit 量化引入
为了节省显存,我们选择预量化的版本。Llama 3.1 原版 16-bit 需 16GB,而 4-bit 版仅需 5.4GB。
Python
import torch
from unsloth import FastLanguageModel
max_seq_length = 2048 # 限制上下文窗口以节省显存
dtype = None # 自动检测(Ampere架构及以上支持BF16)
load_in_4bit = True # 开启4-bit量化
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/llama-3.1-8b-bnb-4bit",
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
)
三、 配置 LoRA:只训练 0.5% 的参数
我们通过 LoRA(低秩自适应)进行微调。在本配置下,我们只训练 80 亿参数中的 4200 万个,极大降低了计算成本。
Python
model = FastLanguageModel.get_peft_model(
model,
r = 16, # 等级(Rank),推荐 8, 16, 32, 64
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
lora_alpha = 16, # 缩放因子
lora_dropout = 0, # 设置为0以获得Unsloth优化加速
bias = "none",
use_gradient_checkpointing = "unsloth", # 关键:大幅节省显存
random_state = 3407,
)
四、 数据准备:ShareGPT 格式与 ChatML 模板
我们使用的是 FineTome-100k 数据集。它经过精细过滤,非常适合多轮对话。我们将使用 ChatML 格式进行标准化。
Python
from unsloth.chat_templates import get_chat_template
# 1. 设置聊天模板映射
tokenizer = get_chat_template(
tokenizer,
mapping={"role": "from", "content": "value", "user": "human", "assistant": "gpt"},
chat_template="chatml",
)
# 2. 处理数据集
def apply_template(examples):
messages = examples["conversations"]
text = [tokenizer.apply_chat_template(message, tokenize=False, add_generation_prompt=False) for message in messages]
return {"text": text}
from datasets import load_dataset
dataset = load_dataset("mlabonne/FineTome-100k", split="train")
# 小提示:算力有限可以先跑前10000条:split="train[:10000]"
dataset = dataset.map(apply_template, batched=True)
五、 训练配置:SFT 实战
使用 SFTTrainer 进行监督微调。注意这里使用了 adamw_8bit 优化器。
| 显卡类型 | 100k 数据预估耗时 |
|---|---|
| A800 (80GB) | ~2 小时 45 分钟 |
| L4 (24GB) | ~19 小时 40 分钟 |
| T4 (16GB) | ~47 小时 |
Python
from trl import SFTTrainer
from transformers import TrainingArguments
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = max_seq_length,
packing = True, # 将小样本打包以提升训练效率
args = TrainingArguments(
learning_rate = 3e-4,
lr_scheduler_type = "linear",
per_device_train_batch_size = 8,
gradient_accumulation_steps = 2,
num_train_epochs = 1,
optim = "adamw_8bit",
weight_decay = 0.01,
warmup_steps = 10,
output_dir = "output",
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 1,
),
)
trainer.train()
六、 推理与保存:导出 GGUF 格式
微调完成后,我们最关心的就是如何使用。Unsloth 支持直接导出 GGUF 格式,方便在 Ollama 或 LM Studio 中直接运行。
1. 快速推理测试
Python
model = FastLanguageModel.for_inference(model)
messages = [{"from": "human", "value": "Is 9.11 larger than 9.9?"}]
inputs = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt").to("cuda")
from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer)
_ = model.generate(input_ids=inputs, streamer=text_streamer, max_new_tokens=128)
2. 保存与导出
Python
# 保存本地适配器
model.save_pretrained("../Fine_tuneModel/")
tokenizer.save_pretrained("../Fine_tuneModel/")
# 导出为 GGUF 格式 (Q8_0量化)
model.save_pretrained_gguf("../Fine_tuneModel/gguf-model.q8_0.gguf", tokenizer, "q8_0")
结语
通过 Unsloth,我们不仅实现了极速微调,还直接打通了从训练到部署的最后一步。微调后的 Llama 3.1 在指令遵循和逻辑判断上会有质的飞跃。
接下来你可以尝试:
- 在 Open LLM Leaderboard 上评估你的模型。
- 使用自己的私有数据集进行垂直领域增强。
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏,并在评论区分享你的微调心得!