学習率の調整#
学習率は,パラメータの更新幅を制御するための重要なハイパーパラメータであり,オプティマイザの中で動的に学習率を調整する手法(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()`. "
他にもスケジューリングの方法は提案されており,PyTorchのリファレンスより確認できるので確認されたい.