【llm对话系统】大模型post-training之 SFT:让 LLM 学会“听懂人话”

如果说预训练是教 LLM 说话,那么 SFT 就是教 LLM “听懂人话”,学会按照指令完成任务。今天,我们就来深入了解 SFT 的数据和训练流程。

一、SFT 是什么?

SFT,全称 Supervised Fine-tuning,中文叫做有监督微调。它是指使用带有标注的数据集对预训练的 LLM 进行进一步训练,以提升 LLM 在特定任务上的性能。

在 SFT 阶段,我们不再像预训练那样让 LLM 预测下一个词,而是让 LLM 根据 指令 (Instruction) 和 输入 (Input) 生成 期望的输出 (Output)。

简单来说,SFT 就是用大量的 (指令, 输入, 输出) 样本来训练 LLM,让它学会根据指令执行任务。

二、SFT 的数据

SFT 的数据质量和多样性直接决定了微调后模型的性能。

1. 数据格式

SFT 的数据通常由以下几个部分组成:

  • Instruction (指令): 描述任务的要求,例如“请总结这段文字的主要内容”、“请将这句英文翻译成中文”、“请根据以下要求写一首诗”等等。
  • Input (输入): 可选,提供任务相关的输入数据,例如需要被总结的文本、需要被翻译的英文句子、写诗的主题等等。
  • Output (输出): 期望 LLM 生成的输出,例如文章摘要、中文翻译、符合要求的诗歌等等。

数据示例:

以下是一些 SFT 数据的示例:

示例 1 (文本摘要):

{
  "Instruction": "请总结这段文字的主要内容。",
  "Input": "大型语言模型 (LLM) 是指包含数百亿个参数的语言模型,它们在海量文本数据上进行训练,可以生成各种类型的文本内容。",
  "Output": "大型语言模型 (LLM) 是一种参数量巨大的语言模型,通过海量数据训练,能够生成各种文本。"
}

示例 2 (机器翻译):

{
  "Instruction": "请将以下英文句子翻译成中文。",
  "Input": "This is an example sentence.",
  "Output": "这是一个例句。"
}

示例 3 (代码生成):

{
  "Instruction": "请写一个 Python 函数,实现快速排序算法。",
  "Input": "",
  "Output": "```python\ndef quicksort(arr):\n  if len(arr) <= 1:\n    return arr\n  pivot = arr[len(arr) // 2]\n  left = [x for x in arr if x < pivot]\n  middle = [x for x in arr if x == pivot]\n  right = [x for x in arr if x > pivot]\n  return quicksort(left) + middle + quicksort(right)\n```"
}

2. 数据来源

构建 SFT 数据集通常有以下几种途径:

  • 人工标注: 人工编写指令和对应的输出,这是最耗时但通常也是最有效的方法。
  • 现有数据集转换: 将已有的 NLP 数据集,例如问答数据集、翻译数据集等,转换成 SFT 需要的 (指令, 输入, 输出) 格式。
  • LLM 生成: 使用已有的 LLM (例如 ChatGPT) 来生成 SFT 数据,然后人工进行校验和修改。
  • 开源的 SFT 数据集: 例如:
    • Alpaca: 包含 52K 条由 GPT-3 生成的指令遵循数据。
    • Flan: 包含多个任务、多种格式的数据,可以用于进行指令学习。
    • OpenAssistant Conversations Dataset: 一个众包、多语言的对话数据集。

3. 数据多样性

为了让 LLM 具备更强的泛化能力,SFT 数据需要尽可能多样化,包括:

  • 任务多样性: 覆盖各种类型的任务,例如文本生成、问答、翻译、代码生成等等。
  • 指令多样性: 对于同一个任务,可以使用不同的指令来描述,例如“请总结这段文字”、“请概括这段文字的主要内容”、“请提取这段文字的核心观点”等等。
  • 输入多样性: 提供各种类型的输入数据,例如不同长度、不同领域的文本。
  • 输出多样性: 对于同一个指令和输入,可以提供多种不同的输出,例如不同的表达方式、不同的风格等等。

三、SFT 的训练流程

SFT 的训练流程与预训练类似,都是通过优化模型的参数来最小化预测结果和真实结果之间的差距。

1. 模型选择

通常选择一个预训练的 LLM 作为 SFT 的基础模型,例如 GPT-3、LLaMA、ChatGLM 等。

2. 损失函数

SFT 通常使用交叉熵损失函数 (Cross-Entropy Loss) 来衡量模型的预测结果和真实结果之间的差距。

3. 优化器

常用的优化器包括 Adam、AdamW 等。

4. 训练步骤

SFT 的训练步骤如下:

  1. 将 Instruction、Input 和 Output 拼接成一个完整的序列,输入到 LLM 中。
  2. LLM 根据 Instruction 和 Input 生成文本。
  3. 计算 LLM 生成的文本和 Output 之间的损失。
  4. 使用反向传播算法更新 LLM 的参数。
  5. 重复步骤 1-4,直到模型收敛或达到预定的训练轮数。

代码示例 (使用 Hugging Face 的 Transformers 库):

from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from datasets import load_dataset

# 加载预训练模型和分词器
model_name = "gpt2"  # 以 gpt2 为例
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 加载 SFT 数据集
dataset = load_dataset("your_sft_dataset")  # 替换成你的 SFT 数据集,例如 json 文件

# 数据预处理函数
def preprocess_function(examples):
    # 将 Instruction, Input, Output 拼接成一个序列
    inputs = [f"Instruction: {inst}\nInput: {inp}\nOutput: {out}" for inst, inp, out in zip(examples["Instruction"], examples["Input"], examples["Output"])]
    model_inputs = tokenizer(inputs, max_length=512, truncation=True, padding="max_length")
    # SFT 中 labels 和 inputs 相同
    model_inputs["labels"] = model_inputs["input_ids"].copy()
    return model_inputs

# 对数据集进行预处理
tokenized_datasets = dataset.map(preprocess_function, batched=True)

# 定义训练参数
training_args = TrainingArguments(
    output_dir="./sft_model",
    learning_rate=2e-5,
    per_device_train_batch_size=4,
    num_train_epochs=3,
    weight_decay=0.01,
    logging_dir="./logs",
)

# 定义 Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],  # 使用处理后的数据集
    # ... 其他参数 ...
)

# 开始训练
trainer.train()

# 保存模型
trainer.save_model("./sft_model")

代码解释:

  1. 我们使用 Hugging Face 的 transformers 库进行 SFT 训练。
  2. 我们加载一个预训练的 LLM 和对应的分词器。
  3. 我们加载 SFT 数据集,并定义一个预处理函数,将数据转换成模型需要的格式,其中labels就是需要预测的内容。
  4. 我们定义训练参数,例如输出目录、学习率、批次大小、训练轮数等。
  5. 我们使用 Trainer 类进行模型训练。

四、SFT 的实践技巧

  • 学习率: SFT 的学习率通常比预训练要小,例如 1e-5 或 2e-5。
  • 批次大小: 根据 GPU 显存大小进行调整,例如 4 或 8。
  • 训练轮数: 根据数据集大小和模型收敛情况进行调整,例如 3 或 5。
  • 早停 (Early Stopping): 为了防止过拟合,可以在验证集上监控模型的性能,当性能不再提升时停止训练。
  • LoRA (Low-Rank Adaptation): 一种高效的微调方法, 通过学习低秩矩阵来更新模型参数, 可以显著减少训练参数量和计算开销.

五、小结一下

SFT 是 LLM 后训练的关键步骤,它使用带有标注的数据集对预训练的 LLM 进行微调,让 LLM 学会根据指令执行任务。SFT 的数据质量和多样性至关重要,需要精心设计和构建。SFT 的训练流程与预训练类似,但需要注意一些实践技巧,例如学习率、批次大小、训练轮数等。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kakaZhui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值