单卡微调7B模型——从环境配置到本地部署


前面几篇文章你一直在用别人的模型。GPT-4 什么都知道,但它不知道你们实验室的 SOP。Claude 能写漂亮的文案,但不懂你们学院的论文格式。

你需要的是让模型学会你给的东西。这就是微调(Fine-tuning)。

微调最妙的一点是:2024年以后,它不再是"大公司才做得了的事"。LoRA 和 QLoRA 的出现让一张 RTX 3060 就能微调 7B 模型。这个门槛的降低是过去两年 LLM 领域最重要的变化之一。

这篇不讲原理推导——我们走完一条完整的微调流水线:从装 LLaMA-Factory 开始,到微调、评测、量化、部署,最后在你的笔记本上跑起来。


微调的本质:三句话讲清楚

动手之前,先花几分钟搞懂微调到底在干什么。

第一,模型的本质是一个函数。 输入文本,输出下一个词的概率。这个函数长什么样,完全由几十亿个"参数"决定——参数就是模型的大脑,语法、常识、推理能力全在这些数字里。

第二,好参数是一步步试出来的。 学自行车不需要物理公式——你只需要每次摔倒后微调身体姿势。大模型训练也一样:随机初始化参数 → 喂数据 → 算误差 → 往减少误差的方向调参数 → 重复几百万次。这个"试探→纠错→再试探"的循环就叫梯度下降,没有捷径。

第三,微调是站在巨人肩膀上。 从头训练等于从零造车——发动机、底盘、电路全部自己做,需要海量数据和算力。微调等于买辆现成的车,只改装导航和内饰,让它适配你的通勤路线。基座模型已经在海量文本上学好了语法和常识,你只需要用少量数据教它你的任务——这就是一张 RTX 3060 能微调 7B 模型的原因:大部分参数不动,只更新一小撮(LoRA)。

理解了这三层,后面六步流水线就不再是机械操作——你会知道为什么 loss 下降不等于学会了、为什么数据质量比数量重要、以及为什么微调后模型变了风格但没变知识。


硬件前提

先确认你的设备能跑:

  • 最低配置:RTX 3060 (12GB) 或同等显存——可以 QLoRA 微调 7B 模型(QLoRA 把模型量化为 4-bit,显存需求降到 8GB 左右)
  • 推荐配置:RTX 4060 Ti (16GB) 或 RTX 4090——可以 LoRA 微调 7B 甚至 14B 模型
  • 纯 CPU 用户:可以跟着学流程,但不要尝试训练,跑完数据准备和部署部分

没有好显卡?可以用 Google Colab 的免费 T4(15GB 显存),足够跑通 QLoRA。

Windows 用户注意:Qwen2.5-7B-Instruct 模型权重约 14GB,加载时需要将整个模型文件映射到虚拟内存。如果 C 盘空间不足(< 40GB)或系统页面文件不够大,你会遇到 OSError: 页文件太小,无法完成操作 (os error 1455)。解决方案是将页面文件迁移到空间充足的 D 盘:

  1. 右键"此电脑" → 属性 → 高级系统设置 → 高级 → 性能设置 → 高级 → 更改
  2. 取消"自动管理所有驱动器的分页文件大小"
  3. 选中 C 盘,设为"无分页文件" → 点"设置"
  4. 选中 D 盘 → “自定义大小” → 初始 16384 MB,最大 32768 MB(或更大,取决于 D 盘空闲空间)
  5. 点"设置" → 重启电脑生效

整条流水线

从零到部署,分六步走:

在这里插入图片描述


第一步:装 LLaMA-Factory

LLaMA-Factory 是这篇的绝对主角。它的价值在于把微调从"需要看一堆论文和改一堆代码"变成了"Web 界面点几下"。

git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e ".[torch,metrics]"
llamafactory-cli webui

浏览器打开 http://localhost:7860,你会看到一个 Web 界面。这个界面背后的能力:

  • 支持几十种主流模型(Qwen、Llama、DeepSeek 等)
  • 支持 LoRA / QLoRA / 全参微调
  • 支持指令微调 SFT 和偏好对齐 DPO
  • 单卡 + 4-bit量化 = 能跑 7B 模型

第二步:选模型和数据集

第一次实验,选最稳妥的配置:

  • 模型Qwen2.5-7B-Instruct(通义千问,中文支持最好的开源模型之一)
  • 方法LoRA(显存友好,效果够用)
  • 数据集ruozhiba_gpt4(弱智吧问答,约 2k 条)

中科院等机构的研究发现,用弱智吧数据微调的模型在多项中文推理任务中表现突出。这类问题包含大量反直觉思维和模糊概念边界,能有效增强模型的逻辑推理能力。更重要的是——微调前后的回答风格差异非常明显,你一眼就能看出"模型变了"。

数据长什么样

Alpaca 格式就是三块:instruction(指令)、input(输入)、output(输出)。弱智吧数据集长这样——问题很刁钻,但回答一本正经:

{
  "instruction": "众所周知,两点之间线段最短,那么人下楼为什么要走楼梯而不做自由落体运动呢?",
  "output": "虽然几何上两点之间的直线最短,但在现实生活中,自由落体运动会产生巨大的冲击力,对人体造成严重伤害。走楼梯虽然路径更长,但安全得多。"
}

用自己的数据

假设你有一份实验室 SOP 问答表 lab_sop.xlsx

问题 答案
门禁密码是多少? 门禁密码是 2024#Lab,每周一更新
论文格式要求是什么? 请参照最新版毕业论文模板,字号小四,行距 1.5 倍
内网服务器怎么连接? SSH 连接 192.168.1.100,端口 2222

两步把它变成 LLaMA-Factory 能用的数据集:

第一步:转成 JSON 并注册

import pandas as pd
import json

df = pd.read_excel("lab_sop.xlsx")
with open("lab_sop.json", "w", encoding="utf-8") as f:
    for _, row in df.iterrows():
        item = {
            "instruction": row["问题"],
            "output": row["答案"]
        }
        f.write(json.dumps(item, ensure_ascii=False) + "\n")

把生成的 lab_sop.json 放到 LLaMA-Factory 的 data/ 目录下,然后在 data/dataset_info.json 末尾注册:

"lab_sop": {
  "file_name": "lab_sop.json"
}

如果数据有 input 字段,注册时需写明三字段映射:"columns": {"instruction": "...", "input": "...", "output": "..."}。另外如果提示缺 openpyxl,先 pip install openpyxl,或者把 Excel 另存为 CSV 用 csv 模块读取。

第二步:在 WebUI 中刷新

点右上角 🔄 刷新按钮,数据集下拉框就会出现 lab_sop,选中它开始训练。

建议:第一次微调先用弱智吧标准数据集跑通流程,确认环境没问题之后,再换成自己的数据。否则你会在"是代码出了 bug 还是数据格式不对"之间反复排查,浪费大量时间。


第三步:训练

第一次训练黄金参数

在 WebUI 选好模型和数据集后,按这张表配参数:

参数 推荐值 说明
学习率 (Learning rate) 5e-5 LoRA 常见范围 1e-5~1e-4,从 5e-5 起步。如果 loss 下降太慢再试着提到 1e-4
训练轮数 (Epochs) 3 ruozhiba 数据量小(2k 条),3 个 epoch 足够
最大梯度范数 1.0 防止梯度爆炸,默认值即可
最大样本数 100000 取全部数据,不用改
计算类型 bf16 半精度训练,省显存(显卡需支持)
截断长度 2048 大多数指令数据不超过这个长度
批处理大小 (Batch size) 2 16GB+ 显存可设 2,12GB 设 1
梯度累积 8 等效 batch size = 2 × 8 = 16
学习率调节器 (LR scheduler) cosine 先大步学后小步微调,稳
验证集比例 0 小数据集不用分验证集

LoRA rank 和 alpha 在 LoRA 参数设置 折叠菜单里:rank 设为 8,alpha 设为 16。这是新手村黄金值,兼顾学习能力和稳定性。

训练前:记录基线

先不要点 Train——先加载原始模型测一遍,记录微调前的回答。这是后续判断微调效果的唯一依据。

操作步骤
WebUI → 点 Chat 标签页 → 选择 Qwen2.5-7B-Instruct → 点"加载模型"
  → 右侧参数面板:temperature 设 0.01,最大长度设 512,系统提示词留空
  → 输入下面 5 道测试题 → 逐题记录回答到表格(训练前列)

加载模型要多久? Qwen2.5-7B-Instruct 约 14GB。已缓存的话 1-3 分钟,首次下载 10-40 分钟。下载源选 modelscope(国内推荐)。加载时留意右下角显存进度条。

📂 加载本地模型:如果你有自己的模型文件,在模型路径下拉框选择或直接输入路径(如 E:/models/Qwen2.5-7B-Instruct),然后点加载即可。

对比参数设置

训练前后参数必须完全一致,否则输出差异可能来自参数不同,而不是微调的效果:

参数 默认值 对比测试建议
Temperature 0.95 设为 0.01(回答确定不变)
Top-p 0.7 保持不动
最大生成长度 1024 512
系统提示词 留空(否则分不清效果来源)
测试题

设计原则:针对基座模型不太擅长、但微调后会有改善的场景。前 3 题是重点——ruozhiba 训练后,对这类问题的回答风格会从简短敷衍变成"一本正经地长篇分析"。

# 1. 逻辑推理——弱智吧经典
Q: "既然鱼不能离开水,那为什么带鱼被叫做带鱼?"

# 2. 逻辑推理——弱智吧经典
Q: "众所周知,两点之间线段最短,那么人下楼为什么要走楼梯而不做自由落体运动呢?"

# 3. 逻辑推理——弱智吧经典
Q: "如果蚊子不吸人血,只吸脂肪,那它会成为减肥神器吗?"

# 4. 指令精准度
Q: "用一句话解释什么是机器学习,不要超过20个字"

# 5. 灾难性遗忘检验
Q: "1+1等于几?"

开始训练

参数配好、基线记好后,回到 WebUI 点"开始训练"。一小时左右(取决于显卡),你会看到一个 loss 曲线在下降。

训练加速:如果你每次训练要等很久,可以试试 Unsloth。它通过优化的内核实现无损训练加速 2x,同时降低显存占用。LLaMA-Factory 已集成,安装后自动生效,无需改代码。

看 Loss 曲线

Loss 曲线应该像缓坡一样平滑下降:

现象 原因 解决
曲线剧烈震荡 学习率太高 降到 2e-5 试试
曲线平坦不下降 学习率太低或数据有问题 升到 1e-4,检查数据质量
Loss 降到接近 0 严重过拟合(记住答案了) 减少 epochs,增加数据量
Val loss 在上升 开始过拟合 在 loss 最低点早停

⚠️ 最重要的提醒:loss 在下降 模型变好了。loss 只说明模型在训练集上的预测误差在减少,不代表它学到了你想要的能力。真正的检验在后面的评测部分。 loss 异常一定说明有问题,值得停训排查。


第四步:评测

训练后对比测试

训练完成后,回到 Chat 标签页加载微调后的模型,用完全相同的参数问同一套题:

点 Chat → 加载基座模型 + 训练好的 adapter
  → 参数设成和训练前完全一样(temperature 0.01,最大长度 512,系统提示词空)
  → 逐一输入 5 道测试题 → 记录回答(训练后列)
  → 和训练前的记录对比
操作检查清单
训练前 Chat 测试:
  ☐ 点 Chat → 选模型 → 加载(1-3 分钟)
  ☐ temperature 0.01,最大长度 512,系统提示词留空
  ☐ 逐一输入测试题 → 记录回答

训练后 Chat 测试:
  ☐ 加载训练后的模型,参数设成和训练前完全一样
  ☐ 问同一套题 → 记录回答
  ☐ 对比两列差异
一次真实的微调实验

以下来自 Qwen2.5-7B-Instruct + ruozhiba_gpt4 数据集的实验记录(temperature=0.01):

问题 训练前 训练后
带鱼为什么叫带鱼 “带鱼"这个名字并不是因为它需要水才能生存,而是因为它身体修长、扁平,像一条带子,因此得名"带鱼”。这个名字来源于它的外形特征,而不是它的生存环境。 “带鱼"这个名称并不是根据鱼的习性命名的。事实上,带鱼是一种生活在海洋中的鱼类,它们可以在深海和浅海中游动。虽然鱼需要水才能生存,但"带鱼"这个名称可能来源于其外形特征。带鱼的体型较长,形状像一条带子,因此得名"带鱼”。另外,带鱼的英文名称"hairtail"也是因为其长形的尾巴,像头发一样。所以,带鱼这个名字更多是基于其外貌特征,而不是其生活环境或习性。
下楼为什么不走自由落体 虽然两点之间线段最短,但自由落体运动在实际生活中是不安全的,可能会造成严重的伤害。因此,人们选择走楼梯以确保安全。安全总是优先于理论上的最短路径。 两点之间线段最短是几何学中的一个基本定理,适用于物理空间中的直线距离。然而,人在下楼时需要考虑安全和实际操作性。自由落体运动虽然在理论上是最短路径,但在现实中,它可能导致严重的身体伤害,甚至生命危险。因此,楼梯作为一种安全、方便的下楼方式被广泛使用。楼梯不仅提供了一个稳定的支撑结构,还允许人以可控的速度和方式下楼,避免了自由落体带来的风险。所以,人下楼选择走楼梯而不是做自由落体运动,是为了确保安全和便利。
蚊子吸脂肪会怎样 蚊子吸脂肪虽然听起来有趣,但实际上并不现实。蚊子的口器和消化系统是专门设计来吸血的,而不是吸脂肪。即使假设蚊子能够吸脂肪,它们的数量和效率也无法达到显著减肥的效果。此外,依赖蚊子吸脂肪来减肥也不是一个健康或科学的方法。保持健康的生活方式,包括合理饮食和适量运动,才是有效的减肥手段。 蚊子吸血的主要目的是为了获取蛋白质和其他营养物质,尤其是雌蚊需要血液中的蛋白质来孵化卵子。如果蚊子只吸脂肪,它们可能无法获得足够的营养来满足其繁殖和生存需求。因此,它们可能会因为营养不良而无法存活。此外,脂肪虽然含有高能量,但蚊子的消化系统可能无法有效处理脂肪,这会导致它们的代谢出现问题。因此,即使蚊子吸脂肪,它们也不会成为减肥神器,反而可能会威胁到它们的生存。
一句话解释机器学习 ≤20字 机器学习是让计算机通过数据学习规律并做出预测。 机器学习是让计算机通过数据自动学习和改进的一种算法技术。
1+1等于几 1+1等于2。 1+1等于2。

变化总结:

  • 训练前回答简短直接,点到即止
  • 训练后回答更长、更有条理,出现了"先分析 A 角度,再分析 B 角度"的结构化输出
  • 对于荒谬问题,训练后更愿意接受前提并认真论证
  • 第 4 题字数控制略有下降(训练后超了 20 字),说明指令跟随没有明显提升
  • 第 5 题完全一致,说明没有灾难性遗忘

这就是微调的真实效果——模型学会了训练数据集的回答风格,而不是学到了新知识。

三层次考试

基本对比之外,再用三个层次检验微调的真实效果:

  1. 会做题了? —— 拿几条训练数据里的问题问模型。它应该能给出和训练集中类似的回答。如果这都做不到,说明根本没学会。
  2. 会泛化了? —— 问一些类似但没见过的场景。比如训练数据里有"SQL 注入检测",你可以问"检查这段代码有没有 XSS 漏洞"。这步过了,才算真的学到了能力。
  3. 变傻了没? —— 问一个完全无关的问题(“西红柿炒蛋怎么做?”)。微调后的模型不能连基本常识都丢了。如果这一步翻车,说明灾难性遗忘——回调学习率或减少 epochs。
怎么看结果
现象 结论
训练后回答更长、更有条理 ✅ 微调成功——学到了训练数据风格
训练后和训练前完全一样 ❌ 训练没收敛——检查 loss 曲线
训练后 1+1 答错了 ❌ 灾难性遗忘——学习率太高或 epoch 太多
训练后直接背出训练数据原文 ❌ 过拟合——减少 epochs

这个测试集(5 条数据)从头到尾不参与训练,纯粹用来检验效果。它是"定性评估",和下面的 OpenCompass 定量评估互为补充。


OpenCompass 标准化评测

对比测试靠人看,OpenCompass 靠分数说话。OpenCompass 在多个标准测试集上给出量化分数,让你精确知道微调改变了模型的哪些能力。

pip install opencompass
python run.py --models hf Qwen2.5-7B-Instruct --datasets ceval mmlu

建议评测两个时间点:

  1. 原始模型(训练前)——记下基线分数
  2. 微调后的模型(训练后)——对比差距

重点关注两个指标:

  • C-Eval(中文综合能力):微调后通常提升 5-15%,因为训练数据是中文
  • MMLU(英文通用知识):通常会略微下降 1-3%,这是正常现象

如果 MMLU 下降超过 5%,说明学习率太高或训练步数太多——灾难性遗忘的信号。

OpenCompass 的命令行方式适合集成到实验脚本中。每次训练完自动跑一遍,结果追加到同一个 CSV 文件,方便追踪多轮实验的效果变化。


第五步:量化

训练完的模型由两部分组成:基座模型(FP16)+ LoRA adapter(几 MB 的小文件)。量化前必须先把 adapter 合并到基座模型,否则导出的 GGUF 不包含你微调的内容:

# 在 LLaMA-Factory 中导出合并后的模型
llamafactory-cli export \
  --model_name_or_path Qwen/Qwen2.5-7B-Instruct \
  --adapter_name_or_path ./saves/Qwen2.5-7B-Instruct/lora/your-checkpoint \
  --template qwen \
  --finetuning_type lora \
  --export_dir ./exported-model

合并后的 ./exported-model 是完整 FP16 模型(约 14GB)。用 llama.cpp 把它量化到 4-bit,降到 4-5GB:

git clone https://github.com/ggerganov/llama.cpp.git
python convert.py ./exported-model --outfile model.gguf
./quantize model.gguf model-Q4_K_M.gguf q4_K_M

Q4_K_M 是效果和体积的最佳平衡点。量化后的模型在 CPU 上就能跑——./llama-cli -m model-Q4_K_M.gguf -p "你好"


第六步:部署

把量化后的模型交给 Ollama 管理。Qwen2.5 使用 ChatML 格式,Modelfile 必须正确设置模板和停止词:

FROM ./model-Q4_K_M.gguf
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
"""
PARAMETER stop "<|im_end|>"
# 导入 Ollama
ollama create my-model -f Modelfile
ollama run my-model

模板不对会导致对话格式错乱。如果你在 Ollama 中看到模型回答带特殊 token 或格式混乱,先检查 Modelfile 里的 TEMPLATE 是否正确。

然后装 Open WebUI(Docker 一键部署),得到一个像 ChatGPT 一样的网页界面,但背后跑的是你自己的微调模型:

docker run -d -p 3000:8080 ghcr.io/open-webui/open-webui:main

浏览器打开 localhost:3000,选择你的模型开始对话。从这一刻起,你不再是一个"调 API 的人",你是一个"真正微调过模型的人"。


实验追踪

WebUI 点选很方便,但它不会帮你记住"这组参数是什么"。做第 1 次实验没问题——参数都在界面上,一目了然。但到第 3、4 次时,你会在下拉菜单和滑块之间反复确认"上次是不是这么配的"。

两个工具能解决这个问题:

  • WandB(Weights & Biases)自动记录每次训练的 loss 曲线和参数。LLaMA-Factory WebUI 自带开关——在训练页面勾选 Enable W&B,填 API key 即可,不需要写任何代码。
  • YAML 配置文件——你在文件里写参数,而不是在界面上点选。

用 YAML 代替 WebUI:

# train.yaml
model_name_or_path: Qwen/Qwen2.5-7B-Instruct
dataset: alpaca_zh
finetuning_type: lora
lora_rank: 8
learning_rate: 5e-5
num_train_epochs: 3
cutoff_len: 2048
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
llamafactory-cli train train.yaml

每次实验复制一份 YAML,改参数就是改文件。几天后回头看,你还能知道"v3 和 v4 的区别只是学习率从 5e-5 改到了 3e-5"。YAML 文件本身就是你的实验记录本。


本文涉及的项目——LLaMA-Factory、PEFT、OpenCompass、llama.cpp、Ollama、Open WebUI——覆盖了从训练到部署的全流程,是整个系列里含金量最高的一组工具链。


本系列 Notebook 及配套文章:github.com/ASPIRINH/hands-on-llm


常见问题

Q: RTX 3060 12GB 能不能跑 QLoRA?
A: 能。在 LLaMA-Factory WebUI 里选 QLoRA(4-bit 量化),模型选 Qwen2.5-7B-Instruct,batch size 设 1,gradient accumulation 设 4。显存占用约 8GB,你有余量。

Q: 训练到一半显存溢出(OOM)?
A: 降低 batch size(从 1 降到 1——已经是 1 了就降 gradient accumulation 步数),或者换更小的基座模型(Qwen2.5-1.5B)。如果还不行,检查有没有其他程序占用显存(nvidia-smi 查看)。

Q: 微调后模型回答质量反而变差了?
A: 最常见的两种原因:1) 训练步数太多导致灾难性遗忘——2k 条规模的数据集 1-2 个 epoch 通常就够了;2) 学习率太高——如果你用的学习率高于本文推荐的 5e-5,降下来试试。

Q: llama.cppconvert.pyno module named 'gguf'
A: 需要装依赖。在 llama.cpp 目录下运行 pip install -r requirements.txt,或者单独 pip install gguf

Q: Ollama 导入模型后对话效果和微调前一样?
A: 检查 Modelfile 里的 TEMPLATE 格式是否正确。Qwen 系列需要特定的 chat template。去 LLaMA-Factory 的 export 目录找生成的 tokenizer_config.json,里面的 chat_template 就是答案。

Q: Colab 免费 T4 能否跑 LLaMA-Factory?
A: 可以。Colab T4 有 15GB 显存,足够 QLoRA 微调 7B 模型。注意 Colab 空闲 90 分钟会断开,建议分段训练或用 LLaMA-Factory 的 --resume_from_checkpoint 续训。

Logo

免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐