监督微调(Supervised Fine-Tuning,SFT)是微调大语言模型(LLM)的关键步骤,通常紧随预训练之后,用于使模型适应具体的任务或遵循指令。
预训练之后,大模型变得知识丰富,但“未经驯化”,需要经过监督微调,从而让大模型学会遵循指令、理解任务格式、生成符合人类期望的回答。
每条数据通常是一个字典,包含:
instruction:任务描述或指令。
input:(可选)上下文或输入信息。
output:期望的回答(或动作)。
system:(可选)系统提示,设定助手角色。
如下所示:
{
"instruction": "翻译成英文",
"input": "今天天气真好",
"output": "The weather is really nice today."
}
人工标注:高质量但成本高(如OpenAI的InstructGPT数据)。
合成数据:用强模型(如GPT-4)生成指令-回答对。
开源数据集:如Alpaca、Dolly、ShareGPT等。
基座模型:选择预训练好的LLM(如LLaMA、Qwen、BLOOM等)。
参数调整:通常微调全部参数,也可用LoRA等高效微调技术。
将数据条目转换为模型输入的提示文本,例如:
[INST] <<SYS>>\n{system_prompt}\n<</SYS>>\n\n{instruction} {input} [/INST]
实际格式取决于模型训练时的模板(如ChatML、Alpaca模板等)。
训练时,只计算回答部分(output) 的损失,指令部分不参与梯度计算。
通过attention mask实现:指令部分的token被mask掉,不贡献损失。
| 超参数 | 典型值 | 说明 |
|---|---|---|
| 学习率 | 1e-5 到 5e-5 | 较小,避免灾难性遗忘 |
| 批量大小 | 16-128 | 根据GPU内存调整 |
| 训练轮数 | 1-5 | 过多易过拟合 |
| 优化器 | AdamW | 常用 |
| 学习率调度 | cosine衰减 | 稳定训练 |
| 最大长度 | 2048或4096 | 根据模型和任务调整 |
LoRA:仅训练低秩适配矩阵,大幅减少参数量。
QLoRA:量化+LoRA,在有限资源下微调大模型。
Prefix-tuning:在输入前添加可训练的前缀向量。
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
import datasets
# 加载模型和分词器
model_name = "meta-llama/Llama-2-7b-hf"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token # 设置填充token
# 加载和预处理数据
def format_data(example):
prompt = f"[INST] {example["instruction"]} {example["input"]} [/INST]"
target = example["output"]
text = prompt + target + tokenizer.eos_token # 添加EOS表示结束
return {"text": text}
dataset = datasets.load_dataset("json", data_files="sft_data.jsonl")
dataset = dataset.map(format_data, remove_columns=dataset["train"].column_names)
# 分词
def tokenize_function(examples):
return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=512)
tokenized_dataset = dataset.map(tokenize_function, batched=True)
# 设置训练参数
training_args = TrainingArguments(
output_dir="./sft_model",
num_train_epochs=3,
per_device_train_batch_size=8,
gradient_accumulation_steps=4,
learning_rate=2e-5,
fp16=True, # 混合精度训练
logging_steps=10,
save_strategy="epoch",
evaluation_strategy="no",
)
# 创建Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset["train"],
)
# 开始训练
trainer.train()
自动评估:使用BLEU、ROUGE等指标(但可能与人类判断不一致)。
人工评估:随机抽样,评估回答的质量、相关性和安全性。
迭代:根据评估结果调整数据或超参数。
灾难性遗忘:避免过长时间训练,可混合预训练数据(比例约1-5%)。
过拟合:早停(early stopping)和验证集监控很重要。
安全性:SFT数据需过滤有害内容,或后续进行RLHF/DPO对齐。
格式化一致性:训练和推理时使用相同的提示模板。
多任务SFT:混合多种任务数据,提升模型泛化能力。
两阶段SFT:先通用指令微调,再特定领域微调。
结合RLHF/DPO:SFT后进一步对齐人类偏好。