AI大模型系列:(十三)Transformer全量微调介绍与超参优化策略

2025-03-23 02:07
455
0

目前对于大模型的微调已经有很多成熟的框架,基本都只要准备好训练集合测试集,进行一些简单的配置就可以执行起来(当然,你得显卡足够好,显存足够大)。不过入门容易,要微调到理想的模型状态还是要花很多功夫。

一、全量微调简介

全量微调(Full Fine-Tuning)是指在预训练模型的基础上,对所有参数进行重新训练以适应特定任务的技术。与轻量级微调方法(如 LoRA、PEFT)不同,全量微调通过更新模型的全部权重,能够充分挖掘预训练模型的潜力,适用于以下场景:

  • 数据分布显著差异:当目标任务数据与预训练数据分布差异较大时(如领域迁移需求,从通用文本转向医疗领域文本),全量微调能更彻底地调整模型表征。
  • 复杂任务需求:对于需要深度特征交互的任务(如多模态理解、复杂逻辑推理),全量微调能通过全局参数优化提升模型能力。
  • 模型规模适配:较小规模的预训练模型(如 BERT-base)在全量微调时计算成本可控,且更容易在特定任务上达到性能峰值。
  • 高精度要求场景:在医疗诊断、金融风控等对准确率要求极高的领域,全量微调的全面优化能力更具优势。
  • 充足的计算资源:拥有足够的GPU/TPU资源和内存支持全参数更新。
  • 足够的训练数据:有大量高质量的领域或任务特定数据(通常需要数千至数万条样本)。
  • 特定能力强化:需要大幅提升模型在特定功能上的表现,如代码生成、数学推理等。
  • 语言适应:将主要在某种语言上预训练的模型适应到另一种语言。

二、Transformer框架全量微调的超参介绍

PyTorch 是通用的深度学习框架,提供底层计算和训练功能。

Hugging Face Transformers 是基于 PyTorch 的高层 NLP 库,专注于预训练模型的快速使用和微调。

2.1、TrainingArguments超参配置

在全量微调中,超参数的选择直接影响模型的收敛速度与最终性能。以下是 Transformer 模型微调的关键超参数:

  • 学习率(Learning Rate):控制参数更新的步长,过高易导致发散,过低则收敛缓慢。典型范围为 1e-5 至 5e-4,大模型可能需要更小的学习率(1e-6至5e-6)。
  • 批次大小(Batch Size):每次迭代处理的样本数量,较大的批次有助于稳定梯度,但受限于内存容量。典型范围:4-32,根据GPU内存和模型大小调整。
  • 训练轮数(Epochs):模型遍历整个训练集的次数。过多可能导致过拟合,过少可能训练不充分。典型范围:3-10轮,需结合早停策略避免过拟合。
  • 权重衰减(Weight Decay):正则化参数,用于防止过拟合,通常设置为 0.01 或 0.001。
  • 预热步数(Warmup Steps):在训练初期逐步增加学习率,帮助模型更好地适应初始阶段的参数调整。
  • 预热比例(Warmup Ratio):预热阶段的比例,通常设为0.1。
  • 梯度累积步数(Gradient Accumulation Steps):累积多个批次的梯度后再更新模型权重。这样就能允许使用更大的有效批次大小。典型范围:4-16步。
  • 梯度裁剪(Gradient Clipping):限制梯度的最大范围,防止梯度爆炸。典型范围:1.0-5.0。
  • 混合精度训练(Mixed Precision Training):使用单精度(FP32)和半精度(FP16)浮点数来进行计算。加速训练。这样能减少内存使用,提高训练速度。在TrainingArguments中,通过设置fp16=True来开启混合精度训练。当fp16设置为True时,Trainer会自动使用半精度(FP16)进行大部分计算,同时保持必要的单精度(FP32)计算以确保数值稳定性。

上述超参数均可在TrainingArguments中直接配置,这是 Hugging Face 框架为简化训练流程提供的便捷方式。通过统一在TrainingArguments中设置这些参数,Trainer会自动集成优化器、学习率调度器等组件,无需手动编写额外代码。

# 配置训练参数
training_args = TrainingArguments(
    output_dir='./results',  # 训练结果保存的目录
    num_train_epochs=3,  # 训练轮数
    per_device_train_batch_size=16,  # 每个设备的训练批次大小
    per_device_eval_batch_size=64,  # 每个设备的评估批次大小
    warmup_steps=500,  # 预热步数
    weight_decay=0.01,  # 权重衰减
    learning_rate=2e-5,  # 学习率
    logging_dir='./logs',  # 日志保存的目录
    logging_steps=10,  # 每多少步记录一次日志
    evaluation_strategy="steps",  # 评估策略,按步数评估
    eval_steps=500,  # 每多少步进行一次评估
    save_steps=1000,  # 每多少步保存一次模型
    save_total_limit=2,  # 最多保存的模型数量
    gradient_accumulation_steps=2,  # 梯度累积步数
    max_grad_norm=1.0,  # 梯度裁剪
    fp16=True  # 开启混合精度训练
)

2.2、更多高级配置

2.2.1、优化器(Optimizer)

优化器负责在训练过程中更新模型参数,以最小化损失函数。常见优化器包括 SGD、Adam、AdamW 等。Hugging Face 默认使用 AdamW(集成权重衰减的 Adam 优化器),不同优化器对收敛速度和稳定性有显著影响。

  • 默认 AdamW:无需显式定义,通过 TrainingArguments 的 learning_rate 和 weight_decay 控制。
  • 其他自定义优化器:通过 Trainer 的 optimizers 参数传入。

优化器介绍:

  • 随机梯度下降(SGD, Stochastic Gradient Descent):每次迭代随机选取一个或一小批样本计算梯度,并根据梯度更新模型参数。
    • 优点:简单直观,计算效率高,适用于大规模数据集。
    • 缺点:收敛速度较慢,容易陷入局部最优解,且对学习率的选择比较敏感。
  • 自适应矩估计(Adam, Adaptive Moment Estimation):结合了 AdaGrad 和 RMSProp 的优点,计算每个参数的一阶矩估计(均值)和二阶矩估计(方差),并根据这些估计动态调整学习率。
    • 优点:自适应调整学习率,对不同参数采用不同的学习率,收敛速度快,适用于大多数情况。
    • 缺点:可能在某些情况下收敛到次优解,并且需要更多的内存来存储一阶矩和二阶矩的估计值。
  • AdamW:在 Adam 的基础上改进,将权重衰减直接应用于参数更新,而不是像 Adam 那样在梯度计算中隐式地应用权重衰减,避免了 Adam 中权重衰减和学习率调整的相互干扰。
    • 优点:在许多任务中表现更好,特别是在使用预训练模型时,可以有效防止过拟合。
    • 缺点:与 Adam 类似,可能需要调整一些超参数。
  • Adagrad(Adaptive Gradient Algorithm):根据每个参数的历史梯度平方和来调整学习率,对于经常更新的参数,学习率会逐渐减小;对于不经常更新的参数,学习率会相对较大。
    • 优点:自动调整每个参数的学习率,适用于稀疏数据。
    • 缺点:学习率会随着训练的进行不断减小,可能导致后期学习率过小,模型无法继续学习。
  • RMSProp(Root Mean Square Propagation):通过引入一个衰减率来计算梯度平方的移动平均,缓解了 Adagrad 学习率下降过快的问题。
    • 优点:在处理非平稳目标函数时表现较好,能够自适应调整学习率。
    • 缺点:需要调整衰减率等超参数。

自定义优化器示例:

from transformers import AdamW, get_scheduler

# 自定义优化器
optimizer = AdamW(model.parameters(), lr=2e-5, weight_decay=0.01)

# 创建 Trainer 时传入优化器
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    optimizers=(optimizer, None)  # 第二个参数为调度器(可选)
)

2.2.2、学习率调度(Learning Rate Schedule)

学习率调度是通过动态调整学习率来优化模型训练的策略。合理的调度可以在初期快速收敛,后期精细调整,避免陷入局部最优。

在 Hugging Face 的 TrainingArguments 中,lr_scheduler_type 参数用于指定学习率调度策略。以下是lr_scheduler_type 参数值的详细介绍(官方文档):

linear:线性 warmup 后线性衰减。

  • 解释:学习率在 warmup_steps 内从 0 线性增加到初始值,然后在剩余训练步数中线性衰减至最小值(默认为 0)。
  • 适用场景:通用任务(如文本分类、问答),平衡训练初期的稳定性和后期的收敛速度。

cosine:余弦退火调度。

  • 解释:学习率在 warmup_steps 后按余弦曲线衰减,最终趋近于最小值(默认为初始学习率的 1e-7)。
  • 适用场景:深层模型或需要避免局部最优的复杂任务(如语言生成模型),平滑的学习率下降,适合需要稳定收敛的任务。。

cosine_with_restarts:带重启的余弦退火调度。

  • 解释:学习率在每个周期内按余弦曲线衰减,到达最小值后重启,重新开始衰减。有助于模型跳出局部最优解。
  • 相关字段:通过 num_cycles 参数控制重启次数(默认 1 次)。
  • 适用场景:需要多次探索不同学习率区域的任务,例如超参数调优或困难样本的训练。

polynomial:多项式衰减调度。

  • 解释:学习率在 warmup_steps 后按多项式函数衰减,衰减速度由 power 参数控制(默认为 1.0,即线性衰减)。
  • 适用场景:需要精细控制衰减节奏的任务,例如小样本学习或对过拟合敏感的场景。

constant:常数调度。

  • 解释:学习率保持不变,不进行热身或衰减。
  • 适用场景:简单任务或需要稳定学习率的场景,例如小规模数据集的快速验证。

constant_with_warmup:仅含 warmup 的常数调度。

  • 解释:学习率在 warmup_steps 内从 0 线性增加到初始值,之后保持恒定。
  • 适用场景:希望模型在训练初期快速适应,后期保持稳定学习率的任务。

inverse_sqrt:平方根衰减调度。

  • 解释:学习率与训练步数的平方根成反比递减。
  • 适用场景: 常用于 Transformer 模型(如 BERT),尤其在预训练阶段表现良好,通过逐步降低学习率来稳定训练。

educe_lr_on_plateau:基于指标的动态调整调度。

  • 解释:当验证指标(如准确率、损失)在指定步数内没有提升时,学习率按固定比例衰减。
  • 注意: 需要额外配置监控的指标,需要结合 metric_for_best_model 和 load_best_model_at_end 参数使用。
  • 适用场景:需要根据验证效果动态调整学习率的任务,例如超参数调优或防止过拟合。

cosine_with_min_lr:带最小学习率的余弦退火调度。

  • 解释:学习率在 warmup_steps 后按余弦曲线衰减,但最低不低于 min_lr(默认 1e-7)。
  • 相关字段:通过 min_lr 参数控制最小学习率。
  • 适用场景:防止学习率过低导致训练停滞,适用于需要长期稳定训练的任务(如生成模型的微调)。

warmup_stable_decay:warmup 后稳定学习率再衰减。

  • 解释:学习率在 warmup_steps 内线性增加到初始值,然后保持恒定一段时间(通过 stable_steps 参数),最后线性衰减至最小值。
  • 相关字段:需结合 stable_steps 参数使用。
  • 适用场景:希望模型在训练中期保持稳定学习率以巩固优化,后期再衰减的任务。

2.2.3、早停(Early Stopping)

早停是通过监控验证指标(如验证损失或准确率)提前终止训练的策略,用于防止过拟合并节省计算资源。

在 Hugging Face 的 Transformer 库中,配置早停(Early Stopping)需要通过 TrainingArguments 中的特定参数实现。早停的核心是监控验证集指标(如损失或准确率),当指标在指定步数内不再改善时提前终止训练。

关键参数说明

  • evaluation_strategy:设置评估策略,可选 'no'(不评估)、'steps'(按步数评估)或 'epoch'(按 epoch 评估)。早停需至少设置为 'steps' 或 'epoch'。
  • metric_for_best_model:指定监控的指标(如 'eval_loss' 或 'eval_accuracy')。
  • early_stopping_patience:允许指标不改善的最大连续评估次数。若超过该次数,训练停止。
  • early_stopping_threshold(可选):指标改善的最小阈值。只有指标变化超过该阈值时,才认为是有效改善。
  • load_best_model_at_end:若为 True,训练结束后会加载最佳模型。

如何配置早停?

  1. 启用评估:通过 evaluation_strategy 开启评估。
  2. 指定监控指标:通过 metric_for_best_model 明确早停依据的指标(需与模型评估时的指标名称一致):
  3. 设置早停参数:配置 early_stopping_patience 和可选的 early_stopping_threshold
  4. 加载最佳模型(可选):若需在训练结束后自动加载最佳模型,设置 load_best_model_at_end=True

示例:

training_args = TrainingArguments(
    output_dir='./results',
    num_train_epochs=10,  # 最大训练 epoch 数
    evaluation_strategy="epoch",  # 每个 epoch 评估一次
    # 或 evaluation_strategy="steps", eval_steps=1000  # 每 1000 步评估一次
    metric_for_best_model="eval_loss",  # 监控验证集损失
     # 或 metric_for_best_model="eval_accuracy"  # 监控验证集准确率
    early_stopping_patience=3,  # 3 个 epoch 无改善则停止
    early_stopping_threshold=0.001,  # 损失需至少降低 0.001
    load_best_model_at_end=True,  # 训练结束后加载最佳模型
    save_strategy="no",  # 不保存中间模型(可选)
)

三、不同场景下超参初始配置建议

针对不同需求,超参的初始配置需要进行针对性的调整,如下列举出一些场景下超参的配置建议。

1、 迁移学习场景

  • 学习率:采用较低的学习率(如 1e-5 至 5e-5),避免破坏预训练知识。
  • 批次大小:根据 GPU 内存选择,通常 32-128 之间,平衡训练稳定性与速度。
  • 训练轮数:3-5 轮,结合早停机制防止过拟合。
  • 权重衰减:0.01,增强模型泛化能力。

2、领域适应场景

  • 学习率:稍高的学习率(如 5e-5 至 1e-4),加速模型对新领域数据的适应。
  • 批次大小:64-256,利用更大的批次捕捉领域数据的分布特征。
  • 训练轮数:5-8 轮,确保模型充分学习领域特定模式。

3、小样本学习场景

  • 学习率:中等学习率(如 3e-5),避免在少量数据上过快收敛。
  • 批次大小:16-32,减少内存压力的同时保持梯度估计的稳定性。
  • 权重衰减:0.001,降低过拟合风险。
  • 优化器:选择 AdamW 或 Adafactor,对小样本更敏感。

4、模型压缩场景

  • 学习率:较低的学习率(如 1e-5),防止压缩过程中模型性能骤降。
  • 训练轮数:8-10 轮,通过更多轮次优化压缩后的模型结构。

四、微调后超参数的调整策略

1、基于验证损失的调整:验证损失不下降

  • 减小学习率(如降低一个数量级)
  • 增加梯度累积步数
  • 尝试不同的学习率调度器

2、基于验证损失的调整:验证损失下降过慢

  • 适当增加学习率
  • 减少批量大小或增加梯度累积步数
  • 延长预热阶段

3、针对过拟合的调整:训练损失远低于验证损失

  • 增加权重衰减(例如从0.01增至0.05)
  • 减少训练轮次
  • 添加dropout(如果模型支持)
  • 引入更多的训练数据

4、针对欠拟合的调整:训练和验证损失都很高

  • 延长训练时间(增加训练轮次)
  • 增加学习率
  • 减少权重衰减
  • 使用更复杂的模型架构

5、针对不稳定训练的调整:训练过程中损失波动大

  • 减小学习率
  • 增加批量大小
  • 降低梯度裁剪阈值
  • 使用更稳定的优化器(如AdamW)

6、针对特定任务的进一步调整:文本生成任务

  • 降低学习率(1e-6 ~ 5e-6)
  • 使用较长的上下文长度
  • 增加训练轮次

7、针对特定任务的进一步调整:分类任务

  • 较高的学习率(2e-5 ~ 5e-5)
  • 较少的训练轮次
  • 聚焦于分类头的调整

 

全部评论