目前对于大模型的微调已经有很多成熟的框架,基本都只要准备好训练集合测试集,进行一些简单的配置就可以执行起来(当然,你得显卡足够好,显存足够大)。不过入门容易,要微调到理想的模型状态还是要花很多功夫。
一、全量微调简介
全量微调(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,训练结束后会加载最佳模型。
如何配置早停?
- 启用评估:通过 evaluation_strategy 开启评估。
- 指定监控指标:通过 metric_for_best_model 明确早停依据的指标(需与模型评估时的指标名称一致):
- 设置早停参数:配置 early_stopping_patience 和可选的 early_stopping_threshold
- 加载最佳模型(可选):若需在训练结束后自动加载最佳模型,设置 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)
- 较少的训练轮次
- 聚焦于分类头的调整
全部评论