学習率の調整

学習率の調整#

学習率は,パラメータの更新幅を制御するための重要なハイパーパラメータであり,オプティマイザの中で動的に学習率を調整する手法(Adamなど)も提案されているが,適切に設定しないと学習の収束が遅くなったり,局所解や発散するような解に到達してしまう.一般的に,学習初期では高めの学習率を,学習後期では学習率を減少させることが多い.

学習率の調整(Learning Rate Scheduling) は,モデルの学習過程で学習率を特定のスケジュールに沿って動的に変更することで,学習効率や汎化性能を改善するためのテクニックである.

PyTorchでは,torch.optimi.lr_scheduler に様々な学習率のスケジューラが実装されており,簡単に利用できる.また学習率は次のようにEpochの終わりに更新されることが多い.

optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
scheduler = ExponentialLR(optimizer, gamma=0.9)

for epoch in range(20):
    for input, target in dataset:
        optimizer.zero_grad()
        output = model(input)
        loss = loss_fn(output, target)
        loss.backward()
        optimizer.step()
    scheduler.step()

よく利用される標準的なスケジューラは

  • 一定のEpoch数ごとに学習率を減少させる StepLR

  • 指数関数に基づき学習率を減衰させる ExponentialLR

  • \(\cos\) 関数に基づいて学習率を上下させる CosineAnnealingLR

である.学習するタスクやモデルに応じてスケジューラもまた適切に設定する必要がある.

学習率の調整の過程を可視化する.

import torch
import matplotlib.pyplot as plt
from torch.optim.lr_scheduler import StepLR, LinearLR, ExponentialLR, CosineAnnealingLR, CyclicLR

initial_lr = 0.1
epochs = 100

lr_histories = {
    "Step Decay": [],
    "Exponential Decay": [],
    "Cosine Annealing": [],
}

for name in lr_histories.keys():
    model = torch.nn.Linear(1, 1)
    optimizer = torch.optim.SGD(model.parameters(), lr=initial_lr)
    
    if name == "Step Decay":
        scheduler = StepLR(optimizer, step_size=25, gamma=0.5)
    elif name == "Exponential Decay":
        scheduler = ExponentialLR(optimizer, gamma=0.95)
    elif name == "Cosine Annealing":
        scheduler = CosineAnnealingLR(optimizer, T_max=20, eta_min=0)
  
    for epoch in range(epochs):
        lr_histories[name].append(optimizer.param_groups[0]["lr"])
        scheduler.step()


plt.figure(figsize=(12, 8))
for name, lr_history in lr_histories.items():
    plt.plot(lr_history, label=name)

plt.xlabel("Epoch")
plt.ylabel("Learning Rate")
plt.title("Learning Rate Scheduling in PyTorch")
plt.legend()
plt.grid()
plt.show()
/home/aizawa/miniconda3/envs/ml-py39/lib/python3.9/site-packages/torch/optim/lr_scheduler.py:143: UserWarning: Detected call of `lr_scheduler.step()` before `optimizer.step()`. In PyTorch 1.1.0 and later, you should call them in the opposite order: `optimizer.step()` before `lr_scheduler.step()`.  Failure to do this will result in PyTorch skipping the first value of the learning rate schedule. See more details at https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate
  warnings.warn("Detected call of `lr_scheduler.step()` before `optimizer.step()`. "
../../_images/ea486cf13f049e22f5554c8c1606d97b9d15bab3af092186a666ff0d5cdab078.png

他にもスケジューリングの方法は提案されており,PyTorchのリファレンスより確認できるので確認されたい.