在使用 get_linear_schedule_with_warmup
(如 Hugging Face Transformers 库中的学习率调度器)时,参数的合理设置需要结合 数据量(dataset size)、批次大小(batch size) 和 训练轮数(epochs) 来确定。以下是分步指南和公式说明:
1. 核心参数解析
get_linear_schedule_with_warmup
的主要参数:
-
num_warmup_steps
: 学习率预热步数(逐渐增大学习率的阶段) -
num_training_steps
: 总训练步数(学习率从峰值线性衰减到 0 的总步数)
2. 参数计算公式
(1) 计算总训练步数 (num_training_steps
)
总训练步数 = 每轮(epoch)的步数 × 训练轮数(epochs)
每轮的步数 = ⌈ 数据总量 / batch_size ⌉ (向上取整)
公式:
num_training_steps=epochs×⌈dataset_size/batch_size⌉
(2) 设置预热步数 (num_warmup_steps
)
经验法则:
-
小规模数据(< 10k 样本): 预热步数占总步数的 10%~20%
-
中/大规模数据(> 10k 样本): 预热步数占总步数的 5%~10%
-
超大数据(> 1M 样本): 预热步数可设为 1%~2%
公式:
num_warmup_steps=max(100,num_training_steps×warmup_ratio)num_warmup_steps=max(100,num_training_steps×warmup_ratio)
(max
确保至少 100 步预热,避免极端情况)
3. 参数设置建议
参数 | 设置原则 |
---|---|
num_warmup_steps | 避免过长(占用过多训练时间)或过短(学习率上升不稳定) |
num_training_steps | 确保准确计算,否则学习率衰减可能提前结束或未完成 |
动态调整策略 | 使用验证集监控,如果模型收敛不稳定,适当增加预热步数或调整预热比例 |
通过合理设置 num_warmup_steps
和 num_training_steps
,可以确保学习率在训练初期稳定上升(预热阶段),随后线性衰减至零,从而优化模型收敛速度和最终性能。根据数据规模和任务特性灵活调整预热比例是关键。
4. 当使用多卡机器与梯度累加步骤结合时,应该如何计算?
可能存在的误区是,梯度累积是在每个卡上独立进行的,还是跨卡同步的。例如,如果每个卡在本地累积了A步梯度,然后进行同步和参数更新,那么总的梯度累积步数仍然是A,而不是卡数乘以A。因此,总的有效批量大小应该是卡数 × 单卡batch size × 梯度累积步数。
此外,在分布式训练中,每个卡处理的样本数是总样本数除以卡数,因此每个卡每个epoch的步数是(总样本数 / 卡数) / 单卡batch size,再乘以梯度累积步数得到参数更新次数。
假设以下参数:
-
总样本数(dataset_size): 50,000
-
每卡批量大小(per_device_batch_size): 32
-
训练轮数(epochs): 3
-
梯度累积步数(gradient_accumulation_steps): 4
-
GPU数量(num_gpus): 4
-
预热比例(warmup_ratio): 10%
计算总的有效批量大小
有效批量大小=num_gpus×per_device_batch_size×gradient_accumulation_steps=4×32×4=512
计算每个epoch的参数更新次数
每个epoch的更新次数=⌈dataset_size/有效批量大小⌉=⌈50,000/512⌉=98
计算总训练步数(num_training_steps)
num_training_steps=每个epoch的更新次数×epochs=98×3=294
计算预热步数(num_warmup_steps)
num_warmup_steps
=max(100,num_training_steps×warmup_ratio)
=max(100,294×0.1)
=max(100,29.4)=100
(若数据量较大,可适当降低预热比例)
5. 代码
from transformers import get_linear_schedule_with_warmup
# 输入参数
dataset_size = 50_000
per_device_batch_size = 32
epochs = 3
num_gpus = 4
gradient_accumulation_steps = 4
warmup_ratio = 0.1 # 10%
# 计算总有效批量大小
effective_batch_size = num_gpus * per_device_batch_size * gradient_accumulation_steps
# 计算每个epoch的更新次数
updates_per_epoch = (dataset_size + effective_batch_size - 1) // effective_batch_size # 向上取整
# 计算总训练步数
num_training_steps = updates_per_epoch * epochs
# 计算预热步数(确保最小100步)
num_warmup_steps = max(100, int(num_training_steps * warmup_ratio))
# 创建调度器
optimizer = ... # 初始化优化器
scheduler = get_linear_schedule_with_warmup(
optimizer,
num_warmup_steps=num_warmup_steps,
num_training_steps=num_training_steps
)