整理不易,请不要吝啬你的赞和收藏。
这篇文章将通过一次微调内部代码数据集,带你了解 QLoRA 微调的整个流程,包括如何选择模型,下载模型,如何搭建微调环境,训练时该注意哪些参数,要如何配置能达到较好的效果等等。
接下来,我们先了解目前大模型微调(Fine-tuning)有哪些主流方案,根据训练目标、硬件条件、模型规模和任务类型不同,通常可以分为三大类:全参数微调、参数高效微调(PEFT)、指令/对齐微调。
原理
对预训练模型中的所有参数(如Transformer的所有层、注意力权重、词嵌入等)进行梯度更新,而不仅仅是新增或部分参数。 也就是说,在训练过程中,会对整个模型(数十亿甚至上千亿参数)都进行反向传播和梯度优化。
优点
精度最高,可以完全拟合新任务可适用于领域迁移(如法律、医疗、工业等特定语料)没有额外推理时开销(不依赖 adapter 层或 LoRA 权重)缺点
显存占用极高训练耗时长容易遗忘预训练知识保存下来的模型文件体积巨大适用场景
模型完全重构特定领域(例如“医疗问诊模型”、“法律咨询模型”)。
原理
PEFT 是一类只微调模型中极少部分参数的方法,它在保持原始模型绝大多数参数冻结(不更新)的同时,通过增加或调整少量参数,让模型适应新的任务或领域。
其核心思想是:冻结模型大部分参数,只训练一小部分“可插拔层 。对比全参数微调,其效果接近甚至相同,但显存开销大幅减少。是目前的主流方案。、
优点
显存占用低(通常节省 90%)训练速度快(10x+)可并行训练多个任务(多适配器)方便部署(按需加载)缺点
模型性能上限略低于全参数微调容易在极端领域"欠拟合"需要开发者具备一定的调优能力推理阶段开销略增,PEFT 不是纯粹修改原模型权重,而是额外添加模块 。在推理时, 需要在模型中加载 LoRA 的 delta 权重(A、B矩阵),并进行矩阵加法运算。常见微调方法
| 方法 | 核心思想 | 显存需求 | 适用场景 |
|---|---|---|---|
| LoRA | 在每个线性层添加低秩矩阵 | 极低(<20%) | 各类任务通用 |
| QLoRA | 在量化模型基础上应用 LoRA | 极低(适合单卡) | 消耗更少显存 |
| Prefix Tuning | 在输入前添加可学习的前缀向量 | 低 | 生成类任务 |
| Adapter Tuning | 在 Transformer 层间插入可训练小模块 | 中 | 分类任务 |
| BitFit | 只训练 bias 参数 | 很低 | 小范围微调 |
| IA³ | 训练少量缩放参数 | 很低 | 通用、快速适配 |
指令微调(Instruction Fine-tuning) 和 对齐微调(Alignment Fine-tuning) 是目前使大模型变得「听话」「有用」「符合人类价值观」的关键技术环节。
定义
指令微调的目的是让模型学会理解指令、生成符合意图的回答 ,模型对齐第一阶段。
对齐微调的目的是 让模型学会符合人类偏好、安全、礼貌 ,模型对齐第二阶段。
为什么需要指令/对齐微调?
预训练语言模型(Pre-trained LM)虽然掌握了大量知识,但它只是**“补全下一个词”**的机器,它不知道“用户的问题”是什么意思,也不知道该“有条理地回答”。
例如:
用户:请帮我写一封道歉信
原始LM:道歉信是一种书信体...
它会解释“什么是道歉信”,而不是直接写信。这说明它没学过“指令 → 输出”这种模式。所以我们要通过指令微调教它:“当我说‘帮我写一封道歉信’,不是让你定义,而是让你生成。”。
优点
让模型理解人类意图、遵循指令显著提升可用性和人机交互体验缺点
需要高质量指令数据(构造成本高)容易学习数据偏见或错误模式上面大致介绍了目前主流的微调方案,下面我们进入本篇文章的主题。
LoRA,全称 Low-Rank Adaptation of Large Language Models,即大语言模型的低秩适应,是一种用于微调大型语言模型的技术。论文:《LoRA: Low-Rank Adaptation of Large Language Models》
核心思想
LoRA的核心思想是通过低秩分解来建模模型参数的更新。它在微调时冻结预训练模型的权重,仅在指定层(如 Transformer 的 attention 投影层)中注入两个可训练的低秩矩阵,从而大幅减少可训练参数量。
工作原理

原理:

QLoRA(Quantized Low-Rank Adapter)全称是量化低秩适配器微调,其结合了量化和低秩适配(LoRA)技术,以在低资源环境下实现模型的高效微调,同时保持性能。 论文: 《QLoRA: Efficient Finetuning of Quantized LLMs》 。
下图是不同的微调方法和它们的内存需求。QLoRA 通过将 transformer 模型量化为 4 位精度,并使用分页优化器来处理内存峰值,从而改进了 LoRA。

HuggingFace 和 ModelScope(魔塔社区) 是目前主流的机器学习开发和共享平台,我们可以在上面进行模型下载。基于网络问题,我这里使用 ModelScope 下载模型。
(PS:我的电脑信息,win11 系统,英伟达 5070Ti 移动端显卡,显存 12GB)
首先我们先配置环境变量 MODELSCOPE_CACHE 和 HF_HOME。配置后模型会默认下载到该路径下,便于管理。
# 值为自己的目录,我这里全部配置成一个路径,方便管理模型
MODELSCOPE_CACHE = D:workspacepackagesmodelscope_cache
HF_HOME = D:workspacepackagesmodelscope_cache

以下为不同微调方式、精度、模型参数所需的显存大小预估,信息摘自 LLaMA-Factory 。
你可以根据自己电脑的显存配置选择适合的模型。
| 方法 | 精度 | 7B | 14B | 30B | 70B |
x B |
|---|---|---|---|---|---|---|
Full (
bf16 or
fp16) | 32 | 120GB | 240GB | 600GB | 1200GB |
18xGB |
Full (
pure_bf16) | 16 | 60GB | 120GB | 300GB | 600GB |
8xGB |
| Freeze/LoRA/GaLore/APOLLO/BAdam | 16 | 16GB | 32GB | 64GB | 160GB |
2xGB |
| QLoRA | 8 | 10GB | 20GB | 40GB | 80GB |
xGB |
| QLoRA | 4 | 6GB | 12GB | 24GB | 48GB |
x/2GB |
| QLoRA | 2 | 4GB | 8GB | 16GB | 24GB |
x/4GB |
初步筛选
基于如下框架的模型可用于微调:LoRA 、Transformers 、PyTorch 、TensorFlow 等。

二次确认
点击模型详情,如果出现如下 ‘训练’ / ‘Train’ 标识,说明该模型是支持微调,当然有些模型不带 ‘训练’ 也可以微调,具体参考模型提供商介绍文档。
ModelScope:

HuggingFace:

下载
以 Qwen/Qwen2.5-Coder-7B-Instruct 模型为例,我这里使用命令行下载。

# 1. 安装 ModelScope
pip install modelscope
# 2. 下载完整模型库
modelscope download --model Qwen/Qwen3-4B-Instruct-2507
本文主要介绍如何制作 Alpaca格式 和 ShareGPT格式 的数据集。
该格式数据集通常用于单轮指令微调(instruction tuning)。
格式:
[
{
"instruction": "指令",
"input": "输入(可选)",
"output": "输出"
}
]
样例:
[
{
"instruction": "解释什么是量子纠缠。",
"input": "",
"output": "量子纠缠是指两个或多个粒子之间存在的量子态关联..."
}
]
# 或者带有输入的情况
[
{
"instruction": "将下面的句子翻译为英语。",
"input": "我喜欢机器学习。",
"output": "I like machine learning."
}
]
适用场景:单轮任务、领域特定微调(如问答、文本生成)。
该格式数据集通常用于 多轮对话微调(chat tuning)。
标准格式:每行包含conversations字段,记录多轮对话,每轮有role(human/assistant)和content。
[
{
"conversations": [
{"from": "human", "value": "你好!你是谁?"},
{"from": "assistant", "value": "我是一个AI语言模型,很高兴见到你!"},
{"from": "human", "value": "你能帮我写个Python算法吗?"},
{"from": "assistant", "value": "当然可以!请告诉我算法的具体需求。"}
]
}
]
变体:OPenAI格式
[
{
"messages": [
{"role": "user", "content": "问题"},
{"role": "assistant", "content": "回答"}
]
}
]
适用场景:多轮对话、聊天机器人训练、RLHF预训练。
我微调的是内部的前端框架代码,数据集采用的 Alpaca 格式,以下是部分示例:
原始内容:
/**
* 编辑某行记录
* @method editRow
* @param {String} rowid 行id
* @param {Object} [option] 参数对象,内置'oper=edit'用来区分操作行为
*/
editRow: function (rowid, o) {
this.getGrid().grid('editRow',rowid, o);
},
整理后的数据集:
{
"instruction": "请实现GridView的editRow方法",
"input": "编辑某行记录",
"output": "```js
/**
* 编辑某行记录
* @method editRow
* @param {String} rowid 行id
* @param {Object} [option] 参数对象,内置'oper=edit'用来区分操作行为
*/
editRow: function (rowid, o) {
this.getGrid().grid('editRow',rowid, o);
},
```"
},
{
"instruction": "解释GridView中editRow方法的作用",
"input": "",
"output": "- 编辑某行记录。"
},
{
"instruction": "editRow方法的参数有哪些?",
"input": "",
"output": "| 参数 | 类型 | 描述 |
|------|------|------|
| rowid | String | 行id |
| option | Object | 参数对象,内置'oper=edit'用来区分操作行为 |"
}
建议
确保每个样本的代码是完整的,可运行的。同一个任务用不同的描述方式。建议使用 虚拟环境 管理 python 依赖,我这里使用 uv (也可以使用 conda)。
# 1. 安装 uv
pip install uv
# 2. 使用 uv 创建一个项目(先进入自己的项目工作空间)
uv init train-demo
# 3. 进入项目
cd . rain-demo
# 4. 创建基于 python 3.11 的虚拟环境
uv venv --python=3.11
# 5. 使用PyCharm等IDE打开项目
项目目录结构如下:
good_train/
└── src/
├── datas/
│ └── code_alpaca.json # 训练数据
└── examples/
└── code/
├── train_code.py # 训练脚本
├── test_inference.py # 推理脚本
├── merge_lora.py # 合并脚本
└── output/ # 输出目录
其中 code_alpaca.json 为数据集,train_code.py 为微调代码,merge_lora.py 为合并LoRA权重代码,test_inference.py 为测试推理代码,目录 output 为微调后输出目录。
【踩坑笔记】50系显卡适配的 PyTorch 安装_cuda13.0对应pytorch-CSDN博客
# 1. 先卸载(可选)
uv pip uninstall torch torchvision
# 2. 安装 Pytorch
uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cu129
# 3. 验证,返回 True 说明安装成功
uv run python -c "import torch; print(torch.cuda.is_available())"
# 1. 安装 HuggingFace 生态和微调工具包
uv pip install transformers datasets accelerate peft bitsandbytes safetensors
# 2. 安装 modelscope, 需要其 snapshot_download 加载 modelscope 下载的模型
uv pip install modelscope
介绍:
| 包名 | 关键词 | 主要作用 |
|---|---|---|
| transformers | 预训练模型 | 加载、训练、推理 BERT/GPT/LLaMA/Qwen 等各种 Transformer 模型。提供
pipeline、
Trainer 等高层接口。 |
| datasets | 数据集处理 | 高效下载、加载和切分数据集,支持 TB 级数据的内存映射。 |
| accelerate | 分布式/混合精度 | 简化多 GPU/TPU 训练、自动混合精度(fp16/bf16)。 |
| peft | 参数高效微调 | 支持 LoRA、Prefix Tuning、P-Tuning 等,只训练少量参数,显著降低显存需求。 |
| bitsandbytes | 4bit/8bit 量化 | 提供高效 8bit/4bit 量化加载与训练,配合
transformers 直接
load_in_4bit=True。 |
| safetensors | 安全权重格式 | 更快更安全的模型权重文件格式(
.safetensors),替代
.bin/
.pt。 |
典型组合:
大模型推理:
transformers + bitsandbytes + safetensorsLoRA/PEFT 微调:
transformers + datasets + accelerate + peft (+ bitsandbytes)
torch: 2.8.0+cu129
transformers: 4.57.0
datasets: 4.1.1
peft: 0.17.1
modelscope: 1.31.0
下面将通过一步步讲解带你了解完整的 QLoRA 微调流程实现,完整代码将在文末提供。
定义数据集来源、数据输出目录以及模型文件。
注意: 这里我使用
modelscope 的仓库下载模型(如果你之前没有预下载模型,将会自动从该仓库下载模型),之后使用
transformers 来训练模型。
current_dir = os.path.dirname(os.path.abspath(__file__))
data_path = os.path.join(current_dir, "../../datas/code_alpaca.json")
output_dir = os.path.abspath(os.path.join(current_dir, "./output/qwen2.5-7b-qlora"))
os.makedirs(output_dir, exist_ok=True)
model_name = snapshot_download("Qwen/Qwen2.5-Coder-7B-Instruct")
# 配置 bitsandbytes 量化工具
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
)
BitsAndBytesConfig类是
transformers 库中用于配置 bitsandbytes 量化工具 的配置类。其作用是通过量化(将模型参数从 32 位 / 16 位压缩到 4 位或 8 位)来显著减少模型的内存占用,同时尽可能保留模型性能,使得大模型能在资源有限的设备(如消费级 GPU)上运行或训练。
以下是其常用参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| load_in_4bit |
bool |
False | 是否启用 4-bit 量化(
True 表示启用)。与
load_in_8bit 互斥。 |
| load_in_8bit |
bool |
False | 是否启用 8-bit 量化(
True 表示启用)。与
load_in_4bit 互斥。 |
| bnb_4bit_quant_type |
str |
"nf4" | 4-bit 量化类型,可选:
"fp4"(浮点4位)或
"nf4"(正态优化4位,推荐)。仅在
load_in_4bit=True 时生效。 |
| bnb_4bit_use_double_quant |
bool |
True | 是否启用 双重量化(double quantization),进一步压缩模型权重,降低显存占用。仅对 4bit 量化有效。 |
| bnb_4bit_compute_dtype |
torch.dtype |
torch.float16 | 计算时的精度类型,推荐
torch.float16 或
torch.bfloat16。仅对 4bit 量化有效。 |
| llm_int8_threshold |
float |
6.0 | 离群值阈值。激活值超过该阈值的部分会使用 FP16 计算,以减少精度损失。仅对 8bit 量化有效。 |
| llm_int8_has_fp16_weight |
bool |
False | 是否在 int8 模型中同时保留 FP16 权重,用于减少精度损失(通常不需要开启)。 |
| llm_int8_enable_fp32_cpu_offload |
bool |
False | 是否将部分 FP32 计算卸载到 CPU,以节省显存。仅对 8bit 模型有效。 |
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True,
)
AutoModelForCausalLM.from_pretrained() 是
transformers 库中用于从本地或远程加载预训练好的大语言模型,并返回一个可直接用于推理或微调的模型实例 。AutoModelForCausalLM 会自动选择适合“Causal Language Modeling(因果语言建模)”任务的模型类,比如 QwenForCausalLM、LlamaForCausalLM 等。
以下是其常用参数:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| pretrained_model_name_or_path |
str | 无(必填) | 模型名称或本地路径。可为: - HuggingFace/ModelScope 上的模型ID(如
"Qwen/Qwen2.5-Coder-7B-Instruct") - 本地模型路径(如
"./local_model") |
| quantization_config |
BitsAndBytesConfig |
None | 量化配置(如
BitsAndBytesConfig 或
GPTQConfig),用于加载低精度量化模型(4bit/8bit)。 |
| device_map |
str /
dict |
"auto" | 设备分配策略:
"auto":自动分配到可用设备(优先 GPU,剩余到 CPU)
"cpu":全加载到 CPU
"cuda":全加载到 GPU
"字典":手动指定层到设备映射(如
{"lm_head": 0, "transformer.layers.0": 1} 多卡) |
| trust_remote_code |
bool |
False | 是否信任远程代码(当模型包含自定义
modeling_*.py 时需设为 True) |
| torch_dtype |
torch.dtype |
None | 模型加载的数据类型(如
torch.float16、
torch.bfloat16、
torch.float32),影响精度与内存占用。 |
| low_cpu_mem_usage |
bool |
True | 启用低 CPU 内存模式(加载时减少内存峰值,适合大模型)。 |
| use_safetensors |
bool |
True | 是否优先使用
.safetensors 权重文件(更安全、更快)。 |
| cache_dir |
str |
None | 指定模型缓存路径(若未设置,默认使用
~/.cache/huggingface/transformers)。 |
| local_files_only |
bool |
False | 是否只从本地加载(不联网)。 |
| offload_folder |
str |
None | 当显存不足时,部分层可临时卸载到磁盘路径(需配合
device_map="auto")。 |
用于配置分词器的补齐(padding)行为,确保在批量处理文本时格式兼容。
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
lora_config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=[ "q_proj", "k_proj", "v_proj", "o_proj", "up_proj", "down_proj", "gate_proj" ],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# 将LoRA应用到模型
model = get_peft_model(model, lora_config)
核心参数解析:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| r |
int |
8 | LoRA 的秩(rank),控制低秩矩阵的维度。值越小,参数越少、计算越快,但可能限制表达能力。常见取值:4、8、16、32。 |
| lora_alpha |
int |
32 | LoRA 的缩放因子,与 r 共同决定低秩矩阵输出的权重(更新量 = 低秩矩阵输出 × (alpha/r))。通常设为 r 的 2-4 倍(如 r=8 时 alpha=16)。 |
| target_modules |
List[str] |
["q_proj", "v_proj"] | 指定应用 LoRA 的模型模块(因模型而异)。 1)LLaMA/OPT 类:
q_proj, v_proj(基础)或
q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj(全注意力 + MLP,增强能力);2)BERT 类:
query, value;建议参考同模型 SOTA 配置,避免漏改层名(如不同版本模型层名可能有差异)。 |
| lora_dropout |
float |
0.05 | LoRA 层的 dropout 比例,防止过拟合。常设 0.05。 |
| bias |
str |
"none" | 是否微调偏置项:
none(不微调,默认,省显存)、
all(微调所有偏置)、
lora_only(仅微调 LoRA 相关偏置)。小样本任务可尝试
lora_only 提升性能,大模型建议
none 控制参数规模。 |
| task_type |
str |
"CAUSAL_LM" | 任务类型,决定 LoRA 适配的模型输出头类型。常见值: 1)
"CAUSAL_LM":因果语言模型(文本生成) 2)
"SEQ_CLASSIFICATION":序列分类 3)
"TOKEN_CLASSIFICATION":token 分类 4)
"SEQ_2_SEQ_LM":序列到序列模型 |
可选参数解析:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modules_to_save |
List[str] |
None | 除 LoRA 层外,还要保存的模块名称。例如
["lm_head"]。 |
| layers_to_transform |
List[int] |
None | 仅在指定的层注入 LoRA(按层号索引)。 |
| layers_pattern |
str |
None | 模型层命名规则,例如
"decoder_layer",通常配合
layers_to_transform 使用。 |
| fan_in_fan_out |
bool |
False | 控制 LoRA 权重矩阵乘法顺序,某些模型(如 GPT-NeoX)需设为
True。 |
| enable_lora |
List[bool] |
None | 对应每个
target_module,是否启用 LoRA。 |
| use_rslora |
bool |
False | 是否使用 Rank-Stabilized LoRA(改进版 LoRA,训练更稳定)。 |
| init_lora_weights |
str |
"gaussian" | LoRA 权重初始化方式。可选
"gaussian"、
"kaiming"、
"zeros" 等。 |
| inference_mode |
bool |
False | 是否为推理模式(禁用梯度更新)。 |
| use_dora |
bool |
False | 是否启用 DoRA,一种新的低秩替代方案(Dynamic Rank Adaptation)。 |
| rank_pattern |
Dict[str, int] |
None | 为不同模块指定不同的 LoRA 秩
r(可覆盖全局设置)。 |
拓展:
Transformer 类模型下各模块(target_modules)介绍:
| 模块名 | 所属层 | 功能 | LoRA 加入作用 |
|---|---|---|---|
| q_proj | Multi-Head Attention (MHA) 多头自注意力 | 将输入映射到 Query 向量 | 调整注意力查询的特征表示,改变注意力聚焦模式 |
| k_proj | MHA | 将输入映射到 Key 向量 | 调整注意力的匹配机制,影响“看哪里” |
| v_proj | MHA | 将输入映射到 Value 向量 | 改变注意力加权后的信息输出 |
| o_proj | MHA 输出 | 将多头注意力输出映射回隐藏维度 | 调整注意力信息整合后的输出 |
| up_proj | Feed-Forward Network (MLP) 前馈网络 | FFN 的上投影矩阵 | 改变中间隐藏层信息流 |
| down_proj | FFN | FFN 的下投影矩阵 | 控制 FFN 输出的表示能力 |
| gate_proj | FFN / Gated Linear Unit (GLU) | FFN 中 gate 控制矩阵 | 调整信息流的门控机制,对输出风格有影响 |
# 加载 Alpaca 数据集
dataset = load_dataset("json", data_files=data_path)
full_dataset = dataset["train"]
# 划分训练数据集和验证数据集
split_dataset = full_dataset.train_test_split(test_size=0.05, seed=42)
train_data = split_dataset["train"]
eval_data = split_dataset["test"]
# 格式化数据集
def format_batch(batch):
prompts = []
for inst, inp, outp in zip(batch["instruction"], batch["input"], batch["output"]):
if not inst or not outp: # 跳过空样本
continue
if inp:
text = (
f"### 指令:
{inst.strip()}
"
f"### 输入:
{inp.strip()}
"
f"### 回复:
{outp.strip()}"
)
else:
text = (
f"### 指令:
{inst.strip()}
"
f"### 回复:
{outp.strip()}"
)
prompts.append(text)
tokenized = tokenizer(
prompts,
truncation=True,
max_length=1024,
padding="max_length",
return_tensors=None,
)
return tokenized
# 用 tokenizer 进行编码
tokenized_train = train_data.map(format_batch, batched=True, remove_columns=train_data.column_names)
tokenized_eval = eval_data.map(format_batch, batched=True, remove_columns=eval_data.column_names)
training_args = TrainingArguments(
output_dir=output_dir, # 模型输出目录
per_device_train_batch_size=1, # 每个设备(GPU/CPU)的训练批次大小;显存小可设为 1~2
per_device_eval_batch_size=1,
gradient_accumulation_steps=8, # 梯度累积步数,等效于 batch_size × steps
warmup_steps=100, # 学习率预热步数有助于训练稳定
# max_steps=10, # 最大训练步数或者使用 num_train_epochs
num_train_epochs=3,
learning_rate=2e-5, # 学习率;
weight_decay=0.01,
fp16=True, # 是否启用半精度训练(float16)
eval_strategy=IntervalStrategy.STEPS, # 验证策略:按步数间隔进行验证
eval_steps=90,
save_strategy=SaveStrategy.STEPS,
save_steps=90,
save_total_limit=3,
load_best_model_at_end=True,
metric_for_best_model="eval_loss",
greater_is_better=False,
logging_steps=30, # 日志打印间隔步数;每 1 步记录一次 loss、lr 等信息
report_to="none",
prediction_loss_only=True,
)
TrainingArguments 是
transformers 库中用于配置模型训练过程的核心类,它封装了几乎所有训练相关的参数(如训练轮数、学习率、批处理大小、日志设置等),无需手动编写训练循环,可直接与
Trainer 类配合使用,大幅简化训练流程。
核心训练参数,直接影响微调效果:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| learning_rate |
float |
5e-5 | 学习率影响模型收敛速度与稳定性。LoRA/QLoRA 推荐
2e-5 ~ 2e-4(视模型规模调整:7B 模型可偏上限,13B+ 模型建议偏下限);小数据可适当偏大(如
1e-4),但需配合早停避免过拟合;微调全量参数时建议
1e-5 ~ 5e-5。 |
| warmup_ratio / warmup_steps |
float / int |
0.0 / 0 | 学习率预热阶段,避免初期震荡。建议
0.03~0.1(即总步数的
3%~10% 作为预热阶段),小样本 / 短训练可设固定步数(如
100~500);大模型(如 30B+)建议提高到
0.1~0.2。 |
| num_train_epochs |
int |
3 | 训练轮数。小数据集(<1k)建议
3~10,视过拟合情况调节(若验证集性能下降则提前终止);大数据集(>10k)可设
1~3,优先通过增大 batch 提升训练效率。。 |
| per_device_train_batch_size |
int |
8 | 每个设备(GPU)上的训练 batch 大小。显存受限时可配合
gradient_accumulation_steps 控制等效 batch(建议等效 batch 在
16~64 之间,过小波动大,过大收敛慢)。 |
| gradient_accumulation_steps |
int |
1 | 用于在显存受限时增大等效 batch(等效 batch = 单卡 batch × 卡数 × 积累步数)。常见
4~16(12GB 显存训练 7B 模型时推荐
8~16),但需注意积累步数过大会延缓参数更新频率。 |
| weight_decay |
float |
0.0 | L2 正则,防止过拟合。LoRA/小数据可设 0.01,过大会抑制学习。 |
| lr_scheduler_type |
str |
"linear" | 学习率调度策略。
cosine 适合大多数场景(后期学习率缓慢下降,利于精细收敛);
linear 适合快速收敛;
constant 仅建议小样本且配合早停;小样本/LoRA 推荐
"cosine"。 |
| optim |
str |
adamw_torch_fused /
"adamw_torch" | 优化器类型。 PyTorch 版本 ≥ 2.8 时,默认值为
adamw_torch_fused(融合版 AdamW,速度更快)。 PyTorch 版本 < 2.8 时,默认值为
adamw_torch(普通版 AdamW,兼容性更广)。 |
| max_grad_norm |
float |
1.0 | 梯度裁剪,防止梯度爆炸。默认
1.0 对多数任务足够;训练不稳定(loss 骤升)时可降至
0.5,稳定任务可提高到
2.0。 |
| fp16 / bf16 |
bool |
False | 半精度训练可大幅降低显存占用(约节省 50%),支持 bf16 GPU 可设
bf16=True。 |
| gradient_checkpointing |
bool |
False | 牺牲
~20% 速度换取
~40% 显存节省,12GB 显存训练 7B+ 模型强烈建议开启;全量微调或大 batch 场景必开。 |
| eval_strategy |
str |
"no" | 建议
epoch(每轮评估)或
steps(按步评估)。小样本设
epoch(数据量小,轮次评估更有意义),大数据设
steps(如每 1000 步),便于及时监控过拟合。 |
| eval_steps |
int |
None | 每多少步进行评估,小数据集可 50~200 步,大数据集可 1000~5000 步。 |
| load_best_model_at_end |
bool |
False | 自动加载验证集性能最优模型,需配合
evaluation_strategy 使用。 |
| max_steps |
int |
-1 | 按步控制训练长度,优先于
num_train_epochs。小样本可 500~2000 步。 大数据可设 10000+;用于控制总更新次数,避免 epoch 计算受 batch 大小影响。 |
| seed |
int |
42 | 保证实验可复现,多 seed 做平均减少随机性。 |
| train_on_inputs |
bool |
True | LoRA 指令微调是否计算 prompt loss,False 仅计算回答部分 loss。 |
其他重要参数:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| output_dir |
str | – | 模型输出目录,训练结果(模型、日志、检查点)保存目录。 |
| overwrite_output_dir |
bool |
False | 若目录存在是否覆盖,慎用,避免误删重要模型。 |
| per_device_eval_batch_size |
int |
8 | 每个设备上(GPU)的评估 batch 大小,大于训练 batch 可加速 eval,但不能超显存。 |
| logging_steps |
int |
500 | 日志打印间隔,小样本可高频 10~50 步。 |
| save_strategy |
str |
"steps" | 保存策略:
"no",
"steps",
"epoch"。 |
| save_steps |
int |
500 | 保存间隔,建议与 eval_steps 对齐,便于回溯最优模型。 |
| save_total_limit |
int |
None | 保留 checkpoint 数量,防止占满磁盘,建议 2~5。 |
| save_safetensors |
bool |
True | 推荐 safetensors 格式,安全高效。 |
| resume_from_checkpoint |
str |
None | 断点续训路径,保证数据与配置一致。 |
| run_name |
str |
None | 实验名称,适配 wandb/tensorboard,可包含关键参数信息。 |
| group_by_length |
bool |
False | 按序列长度分组 batch,减少 padding,提高效率,推荐 True。 |
| report_to |
str / list |
["tensorboard"] | 训练日志监控,可选
tensorboard /
wandb /
none。 |
| device |
str | 自动检测 | 训练设备,单卡可
"cuda:0",多卡由 local_rank 控制。 |
| local_rank |
int |
-1 | 分布式进程索引,多卡训练必用,自动分配。 |
| ddp_find_unused_parameters |
bool |
None | LoRA 部分参数冻结时可设 True,否则 False 提高效率。 |
| torch_compile |
bool |
False | PyTorch 2.0+ 编译加速,LoRA/自定义层需测试兼容性。 |
| tf32 |
bool |
None | Ampere 及以上 GPU TensorFloat32 加速矩阵运算,可设 True。 |
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_train,
eval_dataset=tokenized_eval,
data_collator=data_collator,
callbacks=[
# 监控训练过程中的内存(显存)使用情况,便于排查 OOM(内存溢出)问题
MemoryMonitorCallback(),
# 早停策略
EarlyStoppingCallback(
early_stopping_patience=3,
early_stopping_threshold=0.001
)
],
)
trainer.train()
Trainer 是
transformers 库中的一个高级训练接口,封装了模型训练、验证、
num_train_epochs 评估的完整流程,支持单机单卡、单机多卡、多机多卡等多种训练模式,极大简化了 transformer 模型的训练代码编写。
参数解析:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| model |
nn.Module | 必填 | PyTorch 模型,可使用
AutoModelForXXX。 |
| args |
TrainingArguments | 必填 | 训练参数配置。 |
| train_dataset |
Dataset | None | 训练数据集(支持 HF Dataset 或 torch Dataset)。 |
| eval_dataset |
Dataset | None | 验证/评估数据集。 |
| tokenizer |
PreTrainedTokenizer | None | 用于数据编码和保存 tokenizer。 |
| data_collator |
Callable | None | 用于生成 batch 的函数,支持 padding、mask 等。 |
| compute_metrics |
Callable | None | 接收 predictions 和 labels 返回 metric dict 的函数。 |
| callbacks |
List[TrainerCallback] | None | 自定义训练回调,如 EarlyStopping。 |
| optimizers |
(optimizer, scheduler) | None | 自定义优化器和学习率调度器。 |
Trainer 提供训练、评估、预测、推理等 API :
| 方法 | 说明 |
|---|---|
| train(resume_from_checkpoint=None) | 开始训练,可选择从 checkpoint 恢复。 |
| evaluate(eval_dataset=None) | 在验证集上进行评估,返回 metric dict。 |
| predict(test_dataset) | 在测试集上进行预测,返回
PredictionOutput(predictions, label_ids, metrics)。 |
| compute_loss(model, inputs, return_outputs=False) | 可重写来自定义损失计算逻辑(用于 LoRA 或自定义任务)。 |
| save_model(output_dir=None) | 保存当前模型及 tokenizer。 |
| log(metrics) | 手动记录 metric,用于自定义日志记录。 |
| push_to_hub(commit_message=None) | 将训练好的模型推送到 Hugging Face Hub。 |
进阶:
自定义 Callback ,定义一个每10步显示内存分配信息的回调以及过拟合检测回调。
class MemoryMonitorCallback(TrainerCallback):
def on_log(self, args, state: TrainerState, control: TrainerControl, **kwargs):
step = state.global_step
if step % 10 == 0 or step == 1:
print(f"
========== Step {step} ==========")
if torch.cuda.is_available():
print(f"已分配显存 = {torch.cuda.memory_allocated() / 1024 ** 3:.2f} GB")
print(f"总预留显存 = {torch.cuda.memory_reserved() / 1024 ** 3:.2f} GB")
def on_evaluate(self, args, state: TrainerState, control: TrainerControl, metrics=None, **kwargs):
if metrics:
eval_loss = metrics.get("eval_loss", 0)
if len(state.log_history) > 1:
train_loss = state.log_history[-2].get("loss", 0)
print(f"
【过拟合检测】")
print(f" 训练损失: {train_loss:.4f}")
print(f" 验证损失: {eval_loss:.4f}")
if eval_loss - train_loss > 0.5:
print(f"警告:可能出现过拟合!")
# 保存 LoRA 权重
# 把训练好的模型权重与分词器配置完整地保存到指定目录中,便于后续加载与推理
trainer.model.save_pretrained(output_dir)
tokenizer.save_pretrained(output_dir)
拓展: 后续如何使用训练好的模型权重和分词器配置。
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel, PeftConfig
# 1. 加载 PEFT 配置
peft_model_dir = "./output"
config = PeftConfig.from_pretrained(peft_model_dir)
# 2. 加载基础模型
model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path)
# 3. 将 LoRA 权重注入模型
model = PeftModel.from_pretrained(model, peft_model_dir)
# 4. 加载分词器
tokenizer = AutoTokenizer.from_pretrained(config.base_model_name_or_path)

# 本文中
有效批次大小 = 1 * 1 * 8 = 8
总步数 = ceil(504 * 3) / 8 = 189
训练完成日志:
# 定义路径
current_dir = os.path.dirname(os.path.abspath(__file__))
lora_dir = os.path.join(current_dir, "./output/qwen3-4b-qlora")
merged_dir = os.path.join(current_dir, "./output/qwen3-4b-qlora-merged")
model_name = snapshot_download("Qwen/Qwen3-4B-Instruct-2507")
# 加载完整精度的基础模型(不使用量化)
base_model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16, # 使用 FP16,不使用 4-bit 量化
device_map="auto",
trust_remote_code=True,
)
# 加载 LoRA 权重
model_with_lora = PeftModel.from_pretrained(base_model, lora_dir)
# 合并 LoRA 权重
merged_model = model_with_lora.merge_and_unload()
# 保存合并后的模型
merged_model.save_pretrained(merged_dir)
# 保存 tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.save_pretrained(merged_dir)
执行日志及生成的目录文件列表。

微调前后,输出内容对比,
前:

后:


可以看到模型的回答已经很接近我们的训练数据,但是还有很多不足,这需要我们不断的调整训练参数或者数据集来使其完美。这篇文章只是简单的微调教程,后续如何优化,我将在以后的博客中更新。
完整训练代码我已上传到 github : https://github.com/herogus/good_train
huggingface transformers 文档
huggingface peft 文档
Transformers 中文文档
llamafactory 中文文档
LoRA: Low-Rank Adaptation of Large Language Models
QLoRA: Efficient Finetuning of Quantized LLMs
¥8.10
2024考研管理类与经济类综合能力逻辑教程媛媛教逻辑孙江媛教逻辑张伟男数学真题库乃心教写作真题库199/396联考MBA/MPA/MPAcc管综
¥13.00
2023新版小学奥数举一反三一年级二年级四年级五年级AB版全套人教版数学三年级六年级上册奥数教程数学思维训练从课本到奥数应用题
¥31.20
拜厄钢琴基本教程 大音符大字版 钢琴书钢琴谱大全流行歌曲钢琴曲集初学自学入门零基础 红皮书 钢琴初学者练习曲谱乐谱书
¥42.80
【抽阿狸手账本】我的手绘不可能这么萌1+2 菊长大人萌系手帐插画素材教程手帐教程 书简笔画教程插画 彩铅画入门自学手绘
¥11.90
手指速算全6册新编益智教程3-6岁幼儿园教材儿童全脑开发数学思维启蒙书籍学前教育口算加减法同步练习册
¥24.00
【扫码看视频+简谱电子书】成年人简易钢琴教程成人简易钢琴教程自学基础初级教材钢琴谱钢琴书简谱五线谱钢琴曲谱凤凰新华正版