深度学习模型对比实验:baseline对比一定要学习率一致吗?

1次阅读
没有评论

共计 2151 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点:为什么学习率不能一刀切?

刚入门深度学习时,很多同学(包括当年的我)容易陷入一个思维定式:做模型对比实验时,所有超参数必须完全一致才算公平。特别是学习率这个核心参数,经常被机械地固定为 0.001 或 0.0001。但实际操作中会发现:

深度学习模型对比实验:baseline 对比一定要学习率一致吗?

  • 同样的学习率,在小模型上收敛良好,到大模型却震荡发散
  • 加了 BatchNorm 的模型,学习率可以调大 5 -10 倍
  • 不同优化器(如 SGD vs Adam)对学习率的敏感度差异巨大

这就像要求短跑和马拉松运动员用同样的步频比赛——表面公平,实则违背规律。

技术原理:学习率到底在影响什么?

1. 学习率的物理意义

学习率 $\eta$ 在梯度下降中控制参数更新幅度:
$$\theta_{t+1} = \theta_t – \eta \nabla_\theta J(\theta)$$
其本质是 在损失曲面上移动的步长

  • 步长太大:容易越过最优解(震荡)
  • 步长太小:收敛速度慢(卡在局部最优)

2. 网络结构的影响

不同网络对学习率的敏感度:

网络类型 推荐学习率范围 原因
浅层 CNN 1e-3 ~ 1e-2 梯度传播路径短
ResNet50 1e-4 ~ 1e-3 残差连接稳定梯度
Transformer 1e-5 ~ 1e-4 注意力机制梯度波动大

3. 组件的影响

常见组件对学习率的放大效应:

  • BatchNorm:允许使用更大学习率(通常 $\times 5$)
  • 权重初始化:Kaiming 初始化可支持更大学习率
  • 优化器:Adam 自带学习率自适应,比 SGD 更宽容

实验设计:用代码说话

MNIST 对比实验(PyTorch Lightning 实现)

import torch
from torchvision import transforms
from pytorch_lightning import LightningModule, Trainer

class MNISTModel(LightningModule):
    def __init__(self, lr=1e-3):
        super().__init__()
        self.lr = lr
        self.net = torch.nn.Sequential(torch.nn.Conv2d(1, 32, 3),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(2),
            torch.nn.Flatten(),
            torch.nn.Linear(5408, 10)  # 注意计算维度
        )

    def forward(self, x):
        return self.net(x)

    def training_step(self, batch, batch_idx):
        x, y = batch
        y_hat = self(x)
        loss = torch.nn.functional.cross_entropy(y_hat, y)
        self.log('train_loss', loss)
        return loss

    def configure_optimizers(self):
        # 关键对比点:统一使用 SGD 但不同学习率
        return torch.optim.SGD(self.parameters(), lr=self.lr)

# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

# 对比训练(建议在 Colab 运行)models = {'high_lr': MNISTModel(lr=1e-2),
    'medium_lr': MNISTModel(lr=1e-3),
    'low_lr': MNISTModel(lr=1e-4)
}

for name, model in models.items():
    trainer = Trainer(max_epochs=10, deterministic=True)
    trainer.fit(model, train_loader)

结果分析

通过 TensorBoard 可以看到:

  1. 学习率 1e-2:前 3 个 epoch 快速收敛,后期验证 loss 剧烈波动
  2. 学习率 1e-3:稳定收敛,最终准确率 98.2%
  3. 学习率 1e-4:收敛缓慢,10 个 epoch 仍未饱和

避坑指南

学习率与 batch size 的关系

当增大 batch size 时,应按 $\sqrt{batch_ratio}$ 比例增加学习率(线性缩放规则):

base_lr = 1e-3
current_lr = base_lr * (new_batch_size / base_batch_size)**0.5

动态调整策略

推荐监控验证集 loss 实现自动调节:

from torch.optim.lr_scheduler import ReduceLROnPlateau

scheduler = ReduceLROnPlateau(
    optimizer, 
    mode='min', 
    factor=0.1,  # 衰减系数
    patience=3   # 容忍 epoch 数
)

# 每个 epoch 结束时调用
scheduler.step(val_loss)

延伸思考

  1. 模型容量越大,是否应该使用更小的学习率?
  2. 如何设计实验验证学习率与优化器的耦合效应?
  3. 在你的自定义数据集上,最优学习率与 ImageNet 预训练模型相差多少?

建议尝试修改上述代码中的网络深度,观察学习率最优值的变化规律。记住:没有放之四海而皆准的超参数,理解原理比机械复制更重要!

正文完
 0
评论(没有评论)