文章目录
-
- [**1. 理解 LRF(最终学习率因子)**](#1. 理解 LRF(最终学习率因子))
- [**2. 调整原则:当 lr0 增大时**](#2. 调整原则:当 lr0 增大时)
- [**3. 不同场景下的 LRF 设置建议**](#3. 不同场景下的 LRF 设置建议)
-
- [**基础模型训练(YOLOv5/v8 默认)**](#基础模型训练(YOLOv5/v8 默认))
- [**增大 lr0 的场景及调整:**](#增大 lr0 的场景及调整:)
-
- [**场景1:大 batch size(>64)**](#场景1:大 batch size(>64))
- **场景2:使用预训练权重(迁移学习)**
- **场景3:小数据集**
- **场景4:复杂模型(更多参数)**
- [**4. 如何选择最优的 LRF**](#4. 如何选择最优的 LRF)
- [**5. 不同衰减策略对比**](#5. 不同衰减策略对比)
- [**6. 实战建议与经验法则**](#6. 实战建议与经验法则)
- [**7. 调试技巧**](#7. 调试技巧)
- **总结建议**
1. 理解 LRF(最终学习率因子)
在 YOLOv5/8 等框架中:
lr0:初始学习率(初始值)lrf:最终学习率因子(Final Learning Rate factor)- 最终学习率 =
lr0 × lrf
例如:
lr0=0.01,lrf=0.01→ 最终学习率 = 0.0001lr0=0.1,lrf=0.01→ 最终学习率 = 0.001
2. 调整原则:当 lr0 增大时
核心原则:保持最终学习率在合理范围内
python
# 最终学习率的合理范围通常是:
合理的最终学习率 ≈ 1e-4 到 1e-6
# 所以:
# 如果增大 lr0,应该相应减小 lrf
新的_lrf = 期望的最终学习率 / 新的_lr0
具体策略:
策略A:保持最终学习率不变(推荐)
python
# 原始设置
lr0_old = 0.01
lrf_old = 0.01
final_lr_target = lr0_old * lrf_old # = 0.0001
# 增大 lr0
lr0_new = 0.05 # 增大5倍
# 计算新的 lrf 以保持最终学习率不变
lrf_new = final_lr_target / lr0_new # = 0.0001 / 0.05 = 0.002
print(f"lr0: {lr0_old}→{lr0_new}, lrf: {lrf_old}→{lrf_new}")
print(f"最终学习率保持: {final_lr_target}")
策略B:按比例调整(简单但不推荐)
python
# 如果 lr0 增大 N 倍,lrf 减小 N 倍
N = lr0_new / lr0_old # 增大倍数
lrf_new = lrf_old / N
3. 不同场景下的 LRF 设置建议
基础模型训练(YOLOv5/v8 默认)
yaml
# 默认配置(适用于大多数情况)
lr0: 0.01
lrf: 0.01 # 最终学习率 = 0.0001
增大 lr0 的场景及调整:
场景1:大 batch size(>64)
yaml
# 大 batch size 需要更大的 lr0
batch_size: 128
lr0: 0.05 # 增大 5倍
lrf: 0.002 # 减小到 1/5,保持最终学习率 ~0.0001
场景2:使用预训练权重(迁移学习)
yaml
# 预训练模型需要更小的学习率
weights: 'yolov8n.pt'
lr0: 0.001 # 比默认小
lrf: 0.1 # 可以相对大一些,最终学习率 = 0.0001
场景3:小数据集
yaml
# 小数据集容易过拟合
dataset_size: 1000
lr0: 0.005 # 使用更小的初始学习率
lrf: 0.02 # 更快的衰减,最终学习率 = 0.0001
场景4:复杂模型(更多参数)
yaml
# 模型越大,需要越小的学习率
model: 'yolov8x'
lr0: 0.008 # 稍小于默认
lrf: 0.0125 # 最终学习率 = 0.0001
4. 如何选择最优的 LRF
方法1:网格搜索(系统化)
python
# 测试不同组合
lr0_candidates = [0.005, 0.01, 0.02, 0.05]
lrf_candidates = [0.001, 0.01, 0.1]
# 确保最终学习率在合理范围
for lr0 in lr0_candidates:
for lrf in lrf_candidates:
final_lr = lr0 * lrf
if 1e-6 <= final_lr <= 1e-3: # 合理范围
print(f"lr0={lr0}, lrf={lrf}, final={final_lr}")
方法2:根据训练曲线调整
python
# 观察训练损失曲线
if 训练损失_震荡严重:
# 学习率太大
减小_lr0 或 减小_lrf(更快衰减)
elif 训练损失_下降太慢:
# 学习率太小或衰减太快
增大_lr0 或 增大_lrf(更慢衰减)
elif 验证损失_上升(过拟合):
# 衰减不够快
减小_lrf(更快衰减到小学习率)
方法3:余弦退火衰减(更平滑)
yaml
# 使用余弦衰减代替线性衰减
cos_lr: true # 启用余弦衰减
lrf: 0.01 # 最小学习率因子
# 余弦衰减:lr = lr0 * (0.5 * (1 + cos(epoch/total_epochs * π)) * (1 - lrf) + lrf)
5. 不同衰减策略对比
线性衰减(默认)
python
# 线性衰减公式
lr_epoch = lr0 * (1 - (1 - lrf) * epoch / total_epochs)
# 示例:lr0=0.01, lrf=0.01, epochs=300
# epoch 0: 0.01
# epoch 150: 0.00505
# epoch 300: 0.0001
余弦衰减(更平滑)
python
# 余弦衰减公式(启用 cos_lr: true)
lr_epoch = lr0 * ((1 + cos(π * epoch / total_epochs)) / 2) * (1 - lrf) + lrf
# 特点:早期衰减慢,后期衰减快
指数衰减
python
# 指数衰减(某些框架支持)
decay_rate = lrf ** (1 / total_epochs)
lr_epoch = lr0 * (decay_rate ** epoch)
# 特点:早期衰减快,后期衰减慢
6. 实战建议与经验法则
经验法则表格
| 场景 | lr0 | lrf | 最终学习率 | 说明 |
|---|---|---|---|---|
| 标准训练 | 0.01 | 0.01 | 1e-4 | 默认配置 |
| 大batch | 0.02-0.05 | 0.002-0.005 | 1e-4 | 线性缩放规则 |
| 小数据集 | 0.005 | 0.02 | 1e-4 | 防止过拟合 |
| 迁移学习 | 0.001 | 0.1 | 1e-4 | 微调需要小学习率 |
| 复杂任务 | 0.008 | 0.0125 | 1e-4 | 更稳定的训练 |
| 简单任务 | 0.02 | 0.005 | 1e-4 | 快速收敛 |
推荐配置模板
yaml
# 配置文件中的学习率设置
lr0: 0.01 # 初始学习率
lrf: 0.01 # 最终学习率因子
# 最终学习率 = 0.01 * 0.01 = 0.0001
# 如果需要调整:
# 1. 先确定期望的最终学习率(通常 0.00001 - 0.001)
# 2. 根据任务难度调整 lr0
# 3. 计算 lrf = 期望最终学习率 / lr0
自动调整脚本
python
def auto_adjust_lrf(lr0_new, lr0_default=0.01, lrf_default=0.01):
"""
根据新的 lr0 自动调整 lrf
保持最终学习率与默认配置相似
"""
final_lr_default = lr0_default * lrf_default # 0.0001
# 计算新的 lrf
lrf_new = final_lr_default / lr0_new
# 设置边界
lrf_new = max(0.0001, min(0.1, lrf_new))
print(f"建议配置: lr0={lr0_new}, lrf={lrf_new:.4f}")
print(f"最终学习率: {lr0_new * lrf_new:.6f}")
return lrf_new
# 使用示例
lrf_adjusted = auto_adjust_lrf(lr0_new=0.05)
7. 调试技巧
监控学习率变化
python
import matplotlib.pyplot as plt
def plot_lr_schedule(lr0, lrf, epochs=300):
"""绘制学习率衰减曲线"""
lrs = []
for epoch in range(epochs):
# 线性衰减公式
lr = lr0 * (1 - (1 - lrf) * epoch / epochs)
lrs.append(lr)
plt.figure(figsize=(10, 4))
plt.plot(lrs)
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title(f'lr0={lr0}, lrf={lrf}, final={lrs[-1]:.6f}')
plt.grid(True)
plt.show()
# 对比不同配置
plot_lr_schedule(lr0=0.01, lrf=0.01)
plot_lr_schedule(lr0=0.05, lrf=0.002)
训练中验证
bash
# 训练时观察日志
python train.py --lr0 0.05 --lrf 0.002 --epochs 50
# 监控训练曲线
# 1. 损失是否平稳下降?
# 2. 验证精度是否稳定上升?
# 3. 是否有震荡或不收敛?
总结建议
-
基本原则 :当
lr0增大时,lrf应减小,以保持最终学习率在合理范围(1e-4 到 1e-6) -
实用公式:
lrf_new = (期望的最终学习率) / lr0_new # 期望的最终学习率通常取 0.0001 -
推荐流程:
python1. 先用默认配置训练几轮,观察收敛情况 2. 如果收敛慢,尝试增大 lr0(如 0.01→0.02) 3. 按比例调整 lrf:lrf_new = lrf_default * (lr0_default / lr0_new) 4. 重新训练,监控损失曲线 5. 微调 lrf 直到获得最佳效果 -
注意:没有绝对的最优值,最佳配置取决于你的:
- 数据集大小和复杂度
- 模型结构
- 训练硬件(batch size)
- 任务难度
最简单的做法 :如果你只是轻微调整 lr0(比如 0.01→0.02),那么将 lrf 减半(0.01→0.005)通常是个不错的起点。