文章目錄
- 前言
- 一、理論背景
- 二、代碼解析
- 2.1. 基本問題和環境設置
- 2.2. 訓練函數
- 2.3. 無學習率調度器實驗
- 2.4. SquareRootScheduler 實驗
- 2.5. FactorScheduler 實驗
- 2.6. MultiFactorScheduler 實驗
- 2.7. CosineScheduler 實驗
- 2.8. 帶預熱的 CosineScheduler 實驗
- 三、結果對比與分析
- 總結
前言
學習率是深度學習優化中的關鍵超參數,決定了模型參數更新的步長。固定學習率可能導致訓練初期收斂過慢或后期在次優解附近震蕩。學習率調度器(Learning Rate Scheduler)通過動態調整學習率,幫助模型在不同訓練階段高效優化,平衡快速收斂與精細調整的需求。本文基于 PyTorch,在 Fashion-MNIST 數據集上使用 LeNet 模型,展示五種學習率調度策略:無調度器、SquareRootScheduler、FactorScheduler、MultiFactorScheduler 和 CosineScheduler(包括帶預熱的版本)。通過代碼實現、實驗結果和可視化,我們將深入探討每種調度器的理論基礎和實際效果,幫助讀者從代碼角度理解學習率調度器的核心作用。
值得注意的是,本文展示的代碼不完整,僅展示了與學習率調度器相關的部分,完整代碼包含了可視化、數據加載和訓練輔助函數,完整代碼可以通過下方鏈接下載。
完整代碼:下載鏈接
一、理論背景
學習率調度器的設計需要考慮以下幾個關鍵因素:
- 學習率大小:過大的學習率可能導致優化發散,過小則使訓練緩慢或陷入次優解。問題條件數(最不敏感與最敏感方向變化的比率)影響學習率的選擇。
- 衰減速率:學習率需要逐步降低以避免在最小值附近震蕩,但衰減不能過快(如 ( O(t^{-1/2}) ) 是凸問題優化的一個合理選擇)。
- 預熱(Warmup):在訓練初期,隨機初始化的參數可能導致不穩定的更新方向。通過逐漸增加學習率(預熱),可以穩定初期優化。
- 周期性調整:某些調度器(如余弦調度器)通過周期性調整學習率,探索更優的解空間。
本文將通過實驗驗證這些因素如何影響模型性能。
二、代碼解析
以下是完整的 PyTorch 實現,包含模型定義、訓練函數和五種調度器實驗。
2.1. 基本問題和環境設置
我們使用 LeNet 模型在 Fashion-MNIST 數據集上進行分類,設置損失函數、設備和數據加載器。
%matplotlib inline
import math
import torch
from torch import nn
from torch.optim import lr_scheduler
import utils_for_train
import utils_for_data
import utils_for_huitudef net_fn():"""定義LeNet神經網絡模型"""model = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.ReLU(), # 輸出: [batch_size, 6, 28, 28]nn.MaxPool2d(kernel_size=2, stride=2), # 輸出: [batch_size, 6, 14, 14]nn.Conv2d(6, 16, kernel_size=5), nn.ReLU(), # 輸出: [batch_size, 16, 10, 10]nn.MaxPool2d(kernel_size=2, stride=2), # 輸出: [batch_size, 16, 5, 5]nn.Flatten(), # 輸出: [batch_size, 16*5*5]nn.Linear(16 * 5 * 5, 120), nn.ReLU(), # 輸出: [batch_size, 120]nn.Linear(120, 84), nn.ReLU(), # 輸出: [batch_size, 84]nn.Linear(84, 10) # 輸出: [batch_size, 10])return model# 定義損失函數
loss = nn.CrossEntropyLoss()# 選擇計算設備
device = utils_for_train.try_gpu()# 設置批量大小和訓練輪數
batch_size = 256
num_epochs = 30# 加載Fashion-MNIST數據集
train_iter, test_iter = utils_for_data.load_data_fashion_mnist(batch_size=batch_size)
解析:
- LeNet 模型:適用于 Fashion-MNIST 的 28x28 灰度圖像分類,包含兩層卷積+池化和三層全連接層。
- 損失函數:交叉熵損失,適合多分類任務。
- 數據加載:批量大小為 256,輸入維度為
[batch_size, 1, 28, 28]
,標簽維度為[batch_size]
。
2.2. 訓練函數
訓練函數支持多種學習率調度器,負責模型訓練、評估和可視化。
def train(net, train_iter, test_iter, num_epochs, loss, trainer, device, scheduler=None):"""訓練模型函數參數:net: 神經網絡模型train_iter: 訓練數據迭代器, 維度: [batch_size, 1, 28, 28], [batch_size]test_iter: 測試數據迭代器, 維度: [batch_size, 1, 28, 28], [batch_size]num_epochs: 訓練輪數, 標量loss: 損失函數trainer: 優化器device: 計算設備(GPU/CPU)scheduler: 學習率調度器, 默認為None"""net.to(device)animator = utils_for_huitu.Animator(xlabel='epoch', xlim=[0, num_epochs],legend=['train loss', 'train acc', 'test acc'])for epoch in range(num_epochs):metric = utils_for_train.Accumulator(3) # [總損失, 準確預測數, 樣本總數]for i, (X, y) in enumerate(train_iter):net.train()trainer.zero_grad()X, y = X.to(device), y.