📚 模块7:使用TRL(Transformer强化学习)进行训练配置

7.1 什么是TRL以及为什么使用它?

TRL(Transformer强化学习)是Hugging Face专门设计用于训练语言模型的库,支持现代方法:从监督微调(SFT)到高级技术如RLHF(人类反馈强化学习)和DPO(直接偏好优化)。

对于我们的情况——使用LoRA/QLoRA进行监督微调——我们将使用SFTTrainer,这是一个扩展了Hugging Face标准Trainer但针对文本生成任务优化的类。关键优势:

  • 自动处理可变长度序列。
  • 内置支持指令数据集(Alpaca格式)。
  • 与PEFT和量化原生兼容。
  • 与Weights & Biases(wandb)等监控工具集成。
  • 为高效训练提供内存和性能优化。

7.2 安装和初始设置

# 安装TRL(如果之前未安装)
!pip install -q trl

# 导入关键组件
from trl import SFTTrainer
from transformers import TrainingArguments

7.3 配置TrainingArguments

TrainingArguments定义所有训练超参数:批量大小、周期数、学习率、检查点、日志记录等。

training_args = TrainingArguments(
    output_dir="./results",              # 保存检查点和日志的目录
    num_train_epochs=3,                  # 完整训练周期数
    per_device_train_batch_size=4,       # 每个GPU的批量大小(根据内存调整)
    gradient_accumulation_steps=4,       # 累积梯度以模拟更大的批量
    optim="paged_adamw_8bit",            # 内存高效优化器(对QLoRA至关重要)
    save_steps=500,                      # 每500步保存检查点
    logging_steps=100,                   # 每100步记录指标
    learning_rate=2e-4,                  # LoRA学习率(典型值:1e-4到3e-4)
    weight_decay=0.01,                   # L2正则化
    fp16=True,                           # 混合精度训练(FP16)
    bf16=False,                          # 除非GPU支持BF16(A100, H100)否则禁用
    max_grad_norm=0.3,                   # 梯度裁剪以确保稳定性
    warmup_ratio=0.03,                   # 线性学习率预热
    lr_scheduler_type="cosine",          # 余弦学习率衰减
    report_to="wandb",                   # 向Weights & Biases报告指标(可选)
    evaluation_strategy="steps",         # 训练期间评估
    eval_steps=500,                      # 每500步评估
    save_total_limit=2,                  # 仅保留最新的2个检查点
    load_best_model_at_end=True,         # 结束时加载最佳模型(按评估指标)
    metric_for_best_model="eval_loss",   # 定义"最佳模型"的指标
    greater_is_better=False,             # 损失越小越好
    push_to_hub=False,                   # 不上传到Hugging Face Hub(可选)
)

关键说明:

  • per_device_train_batch_size=4 + gradient_accumulation_steps=4 = 有效批量大小为16。
  • optim="paged_adamw_8bit"对避免QLoRA中的OOM至关重要。
  • fp16=True加速训练并减少内存。如果GPU支持BF16(Ampere+),使用bf16=Truefp16=False
  • report_to="wandb"需要免费的Weights & Biases账户。否则使用report_to="none"

7.4 为SFTTrainer准备数据集

SFTTrainer期望一个带有格式化文本字段的数据集。我们将使用模块6中的format_instruction函数。

from datasets import Dataset

# 假设我们有Alpaca格式的示例
dataset_dict = {
    "instruction": [
        "为科技产品写一个简短的描述。",
        "将以下文本概括为一句话。",
    ],
    "input": [
        "产品:带降噪功能的无线耳机。价格:$129.99。",
        "生成式AI正在通过实现高质量内容的自动化创建来改变教育、娱乐和医疗保健等行业。",
    ],
    "output": [
        "通过这些高保真无线耳机享受无干扰的音乐。主动降噪功能和长达30小时的电池续航,非常适合旅行、工作或放松。仅售$129.99。",
        "生成式AI正在通过自动化高质量内容的创建来革新关键行业。",
    ]
}

# 转换为Hugging Face数据集
dataset = Dataset.from_dict(dataset_dict)

# 应用格式化
def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs = examples["input"]
    outputs = examples["output"]
    texts = []
    for instruction, input_text, output in zip(instructions, inputs, outputs):
        text = f"### 指令:\n{instruction}\n\n### 输入:\n{input_text}\n\n### 响应:\n{output}"
        texts.append(text)
    return texts

# SFTTrainer将使用此函数格式化示例

7.5 创建并启动SFTTrainer

trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    formatting_func=formatting_prompts_func,  # 格式化提示的函数
    max_seq_length=512,                       # 最大序列长度
    tokenizer=tokenizer,
    packing=False,                            # 不打包序列(更适合指令调优)
    dataset_text_field="text",                # 包含文本的字段(如果使用formatting_func则不需要)
)

# 开始训练
trainer.train()

重要提示: 如果数据集很大,请将其分为train_dataseteval_dataset并都传递给训练器。这里为了简单起见,我们只使用训练。


Course Info

Course: AI-course3

Language: ZH

Lesson: Module7