大模型微调与强化学习训练实战操作手册
大模型微调与强化学习训练实战操作手册

第一部分:PEFT微调核心技术与参数详解
本部分将详细拆解参数高效微调(PEFT)的核心流程,重点解析LoRA/QLoRA的关键参数设置及其背后的数学与工程意义。
1.1 LoRA核心参数详解
在使用LoRA(Low-Rank Adaptation)进行微调时,以下参数直接决定了模型的训练效果和显存占用。
1. lora_rank ®
- 定义:低秩矩阵的秩(Rank)。它决定了LoRA适配器中可训练参数的数量。LoRA将一个大的权重更新矩阵 ΔW\Delta WΔW 分解为两个小矩阵 AAA 和 BBB 的乘积,即 ΔW=B×A\Delta W = B \times AΔW=B×A。其中 BBB 的维度是 d×rd \times rd×r,AAA 的维度是 r×dr \times dr×d。
- 意义:
r越大,模型的可塑性越强,能学习到的特征越复杂,但显存占用和训练时间也会增加,且过大容易导致过拟合。 - 推荐范围:
- 通用任务:
8或16。对于大多数指令微调任务,这个范围已经足够捕捉所需的模式。 - 复杂推理/数学/代码任务:
32、64甚至128。当任务需要模型学习全新的逻辑或大量新知识时,需要更高的秩。 - 极简任务(如简单分类):
4或8。
- 通用任务:
2. lora_alpha
- 定义:LoRA的缩放系数(Scaling Factor)。在训练过程中,LoRA更新的权重会乘以一个缩放因子 αr\frac{\alpha}{r}rα 加到原始权重上。
- 意义:它控制了LoRA新增权重对原始模型权重的影响程度。
alpha越大,LoRA学到的特征在最终推理中占的比重就越大。 - 推荐设置:
- 黄金法则:通常设置为
lora_rank的 2倍。例如,如果r=16,则alpha=32;如果r=64,则alpha=128。 - 原理:这种设置(α=2r\alpha = 2rα=2r)在实践中被证明能提供最稳定的梯度更新,类似于一种自适应的学习率调整。
- 黄金法则:通常设置为
3. lora_dropout
- 定义:在LoRA层中应用的Dropout概率。
- 意义:防止过拟合。在训练过程中随机“丢弃”一部分神经元,迫使模型学习更鲁棒的特征。
- 推荐范围:
- 数据量较少(<1万条):
0.1或0.05。 - 数据量充足(>10万条):
0(可以关闭以加快收敛)或0.05。
- 数据量较少(<1万条):
4. target_modules
- 定义:指定模型中哪些层需要应用LoRA适配器。
- 意义:决定了微调的“深度”和“广度”。
- 推荐设置:
- 全量微调效果(推荐):
["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]。即对Attention层(Q, K, V, O)和MLP层(Gate, Up, Down)全部添加LoRA。这被称为“全模块LoRA”,效果最接近全参数微调。 - 节省显存:仅对
["q_proj", "v_proj"]添加。这是最早LoRA论文中的默认设置,显存占用最小,但效果不如全模块。
- 全量微调效果(推荐):
1.2 训练超参数详解
无论使用哪种工具,以下训练参数都是通用的,且至关重要。
1. learning_rate (学习率)
- 意义:控制模型参数更新的步长。
- 推荐范围:
- LoRA/QLoRA:
1e-4到2e-4。LoRA通常需要比全参数微调(通常1e-5)更大的学习率。 - 全参数微调:
1e-5到5e-5。
- LoRA/QLoRA:
2. num_train_epochs (训练轮数)
- 意义:数据集被完整遍历的次数。
- 推荐范围:
- 指令微调(SFT):
1到3个Epoch。大模型很容易过拟合,通常1-2个Epoch即可,超过3个Epoch往往会导致模型丧失通用能力(Catastrophic Forgetting)。
- 指令微调(SFT):
3. per_device_train_batch_size & gradient_accumulation_steps
- 定义:
batch_size:单次前向传播的数据条数。accumulation_steps:梯度累积步数。
- 实际Batch Size =
batch_size*accumulation_steps*GPU数量。 - 推荐设置:
- 目标:使实际Batch Size达到
64或128。 - 显存受限时:设小
batch_size(如1或2),调大accumulation_steps(如16或32)。
- 目标:使实际Batch Size达到
4. warmup_ratio (预热比例)
- 意义:在训练初期,学习率从0线性增加到设定的最大值,以防止训练初期梯度过大导致模型崩溃。
- 推荐范围:
0.03(3%) 或0.05(5%)。
第二部分:LLaMA-Factory 实战操作指南
LLaMA-Factory 是目前最适合新手的“一站式”微调工具,其WebUI界面覆盖了从数据处理到模型导出的全流程。
2.1 环境准备与启动
- 克隆仓库:
git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .[metrics] - 启动WebUI:
启动后,浏览器访问llamafactory-cli webuihttp://localhost:7860。
2.2 WebUI 操作流程详解
步骤一:模型选择 (Model Selection)
- Model Name: 选择基础模型系列,如
LLaMA-3-8B。 - Model Path: 填写模型在本地的绝对路径,或者Hugging Face的模型ID(如
meta-llama/Meta-Llama-3-8B)。 - Finishing Method: 选择
LoRA。如果显存极度受限(如<16GB),勾选Use QLoRA(这将自动启用4-bit量化加载)。
步骤二:数据集配置 (Dataset)
- Dataset: 在下拉菜单中选择内置数据集(如
identity,alpaca_en),或选择自定义数据集。- 自定义数据格式:在
data/dataset_info.json中注册你的数据文件。标准格式为JSON列表:[ {"instruction": "用户指令", "input": "可选输入", "output": "期望回答"}, ... ]
- 自定义数据格式:在
- Cutoff Length: 截断长度。推荐
1024或2048。如果显存允许且任务涉及长文本,可设为4096。
步骤三:训练参数设置 (Train)
这是最关键的配置面板,请严格按照以下推荐设置:
- Stage: 选择
Supervised Finetuning(SFT)。 - Learning Rate: 输入
2e-4。 - Epochs: 输入
3.0。 - Batch Size: 根据显存调整。24GB显存推荐
4或8。 - Gradient Accumulation: 配合Batch Size,使乘积接近
64。例如Batch Size为4,则此项设为16。 - LR Scheduler: 选择
cosine(余弦退火),这是目前最主流的学习率调度策略。 - Max Samples: 用于调试,设为
1000可快速跑通流程;正式训练留空(使用全部数据)。
步骤四:LoRA参数配置 (LoRA)
点击 “Advanced Configuration” 展开:
- LoRA Rank:
16 - LoRA Alpha:
32 - LoRA Dropout:
0.05 - Target Modules: 默认通常是全选(All),或者手动输入
q_proj,v_proj,k_proj,o_proj,gate_proj,up_proj,down_proj。
步骤五:启动训练
- 点击 Preview Command:查看生成的命令行脚本,确认参数无误。
- 点击 Start:开始训练。
- 监控:右侧会实时显示 Loss 曲线。正常的曲线应呈现平滑下降趋势。如果Loss震荡剧烈,尝试减小学习率;如果Loss下降极慢,尝试增大学习率。
步骤六:模型导出 (Export)
训练完成后,切换到 Export 选项卡:
- Model Path: 自动填充为刚才训练的基础模型。
- Adapter Path: 选择刚才训练保存的Checkpoint路径。
- Export Dir: 设置合并后模型的保存路径。
- Max Shard Size: 设置分块大小,推荐
2GB或5GB。 - 点击 Export,工具会将LoRA权重与基础模型合并,生成一个完整的、可直接加载的模型文件。
第三部分:强化学习微调(DPO/RLHF)详解
在完成SFT(有监督微调)后,模型虽然学会了说话,但可能还不够“听话”或“安全”。强化学习微调(尤其是DPO)是让模型对齐人类偏好的关键步骤。
3.1 DPO (Direct Preference Optimization) 核心参数
DPO不需要训练奖励模型(Reward Model),直接使用偏好数据(Chosen vs Rejected)进行优化。其核心参数如下:
1. beta (DPO Beta)
- 定义:KL散度惩罚系数。它控制了微调后的模型与原始参考模型(Reference Model)之间的差异程度。
- 意义:
beta越大,模型越保守,越倾向于保持原始模型的行为,生成的文本多样性越低。beta越小,模型越激进,越倾向于优化偏好数据的差异,但也更容易过拟合或产生“胡言乱语”。
- 推荐范围:
- 标准设置:
0.1。这是绝大多数DPO论文和实践中的默认值,是一个稳健的起点。 - 激进优化:
0.05。如果你希望模型非常强烈地偏向“Chosen”的回答风格,可以尝试减小此值。 - 保守优化:
0.2-0.5。如果发现模型训练后开始输出乱码或重复内容,增大此值以加强约束。
- 标准设置:
2. learning_rate (DPO学习率)
- 特别注意:DPO的学习率必须比SFT阶段 低一个数量级。
- 推荐范围:
5e-6到1e-6。如果SFT用的是2e-4,DPO千万不要用这么大,否则模型会瞬间崩溃。
3. 数据格式 (Preference Dataset)
DPO需要特定的“三元组”数据格式:
- Prompt: 提示词。
- Chosen: 人类倾向的回答(胜者)。
- Rejected: 人类拒绝的回答(败者)。
- 关键点:Chosen和Rejected的回答必须是针对同一个Prompt的,且两者要有明显的质量差异。
第四部分:Unsloth 代码实战指南
Unsloth 是追求极致效率的开发者的首选。以下是一个完整的Python脚本实战,涵盖从加载模型到DPO训练的全流程。
4.1 环境安装
pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
pip install --no-deps "xformers<0.0.26" "trl<0.9.0" peft accelerate bitsandbytes
4.2 SFT微调实战代码
from unsloth import FastLanguageModel
import torch
from trl import SFTTrainer
from transformers import TrainingArguments
# 1. 加载模型与Tokenizer
# max_seq_length: 设置为2048或4096,根据显存决定
# load_in_4bit: True 开启4bit量化,显存占用极低
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/llama-3-8b-bnb-4bit",
max_seq_length = 2048,
dtype = None, # 自动检测硬件支持的数据类型(float16或bfloat16)
load_in_4bit = True,
)
# 2. 配置LoRA适配器
# 这里是Unsloth特有的API,比官方PEFT库更简洁
model = FastLanguageModel.get_peft_model(
model,
r = 16, # LoRA Rank
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"], # 全模块微调
lora_alpha = 32, # 建议为Rank的2倍
lora_dropout = 0, # Unsloth建议设为0以优化速度
bias = "none", # 不训练偏置项
use_gradient_checkpointing = True, # 开启梯度检查点,节省显存
random_state = 3407,
)
# 3. 准备数据集 (Alpaca格式)
# 假设你已经加载了dataset对象
alpaca_prompt = """Below is an instruction that describes a task...
### Instruction:
{}
### Input:
{}
### Response:
{}"""
def formatting_prompts_func(examples):
instructions = examples["instruction"]
inputs = examples["input"]
outputs = examples["output"]
texts = []
for instruction, input, output in zip(instructions, inputs, outputs):
text = alpaca_prompt.format(instruction, input, output) + tokenizer.eos_token
texts.append(text)
return { "text" : texts, }
# 4. 配置训练参数
training_args = TrainingArguments(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4,
warmup_steps = 5,
max_steps = 60, # 测试用,正式训练建议用num_train_epochs = 1
learning_rate = 2e-4,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 1,
optim = "adamw_8bit", # 使用8bit优化器进一步节省显存
weight_decay = 0.01,
lr_scheduler_type = "linear",
seed = 3407,
output_dir = "outputs",
)
# 5. 开始训练
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = 2048,
dataset_num_proc = 2,
packing = False, # 设为True可以将短数据拼接,加速训练
args = training_args,
)
trainer.train()
4.3 DPO微调实战代码
在SFT训练完成后,我们可以继续进行DPO训练。注意,DPO需要加载两个模型:一个是待训练的模型(Policy Model),一个是参考模型(Reference Model)。Unsloth通过一种巧妙的方式(Patching)避免了显式加载两个模型,从而节省了一半显存。
from unsloth import PatchDPOTrainer
from trl import DPOTrainer
# 1. 应用DPO补丁
PatchDPOTrainer()
# 2. 加载刚刚SFT微调好的模型
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "outputs/checkpoint-60", # SFT的产物
max_seq_length = 2048,
load_in_4bit = True,
)
# 3. 配置DPO训练参数
dpo_trainer = DPOTrainer(
model = model,
ref_model = None, # Unsloth会自动处理Reference Model,无需手动加载
tokenizer = tokenizer,
beta = 0.1, # DPO核心参数:KL惩罚系数
train_dataset = dpo_dataset, # 必须包含 prompt, chosen, rejected 三列
max_length = 1024,
max_prompt_length = 512,
args = TrainingArguments(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 8,
learning_rate = 5e-6, # 注意:比SFT低很多
max_steps = 100,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_first_step = True,
optim = "adamw_8bit",
output_dir = "dpo_outputs",
),
)
dpo_trainer.train()
第五部分:常见问题与避坑指南
5.1 Loss不下降怎么办?
- 检查学习率:如果是SFT,尝试从
2e-4降到1e-4或5e-5。如果是DPO,确保学习率在1e-6级别。 - 检查数据质量:数据中是否存在大量重复、空白或格式错误的样本。
- 检查Prompt格式:确保训练时的Prompt模板与推理时完全一致,包括换行符和特殊token。
5.2 显存爆了(OOM)怎么办?
- 开启4-bit量化:这是最立竿见影的方法(
load_in_4bit=True)。 - 减小Batch Size:将
per_device_train_batch_size设为1,同时成倍增加gradient_accumulation_steps。 - 开启梯度检查点:
gradient_checkpointing=True。这会以时间换空间,显著降低显存,但训练速度会慢20%左右。 - 减少LoRA Rank:将
r从64降到16或8。
5.3 训练后的模型只会复读怎么办?
- 原因:通常是过拟合,或者EOS Token(结束符)没有正确学习。
- 解决:
- 检查数据集中每条样本的末尾是否都添加了
<|end_of_text|>或对应的EOS Token。 - 减少Epoch数。
- 增大
lora_dropout。
- 检查数据集中每条样本的末尾是否都添加了
结语:大模型微调是一门实验科学。本文档提供的参数范围是基于广泛实践的“经验值”,在实际操作中,建议您先使用小批量数据(如500条)进行快速实验,观察Loss曲线和生成效果,再确定最终的全量训练方案。
更多推荐



所有评论(0)