ワンサイクルポリシー(ワンサイクルポリシー)
Leslie Smith が 2018 年に提案した学習率スケジューリング手法で、訓練全体を 1 サイクルとして学習率を低→高→低と変化させる。超収束(Super-Convergence)と呼ばれる現象を引き起こし、従来の数分の一のステップ数で同等以上の精度を達成できる。BERT ファインチューニングや中規模モデル訓練で特に有効。
ワンサイクルポリシーとは
ワンサイクルポリシー(1cycle policy / One Cycle Policy)は、Leslie Smith が 2018 年の論文「Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates」で提案した学習率スケジューリング手法である。訓練全体を単一のサイクルとして、学習率を以下の 3 フェーズで変化させる:
- Phase 1 (Warmup): 最小学習率(η_max / div_factor)からピーク学習率(η_max)まで上昇
- Phase 2 (Annealing): ピーク学習率から最小学習率まで減衰
- Phase 3 (Final Annihilation): さらにピークの 1/10,000 まで急減衰(全体の最後 5〜10%)
この手法は「超収束」を引き起こし、従来のスケジューリングと比較して 5〜10 倍少ないステップ数で同等の精度を達成できるケースが報告されている。
ワンサイクルの構造と数式
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
| max_lr (η_max) | — | ピーク学習率(LR Range Test で決定) |
| div_factor | 25 | 初期学習率 = max_lr / div_factor |
| final_div_factor | 10,000 | 最終学習率 = max_lr / (div_factor × final_div_factor) |
| pct_start | 0.3 | ウォームアップに使う訓練の割合 |
| anneal_strategy | 'cos' | 'cos'(コサイン減衰)or 'linear' |
| cycle_momentum | True | Momentum を学習率と逆に変動 |
| base_momentum | 0.85 | Momentum の最小値 |
| max_momentum | 0.95 | Momentum の最大値 |
超収束のメカニズム
超収束が発生する理由は完全には解明されていないが、以下の仮説が有力:
- 大学習率による正則化効果: ピーク付近の大きな学習率がノイズを注入し、鋭い局所解を回避
- Momentum との協調: 学習率が上昇する Phase 1 では Momentum を下げ、学習率が下降する Phase 2 では Momentum を上げることで、パラメータ更新の総量を制御
- 平坦な解への誘導: 大きな学習率フェーズが鋭い谷(Sharp Minima)を飛び越え、平坦な谷(Flat Minima)に着地
LR Range Test による最適学習率の発見
ワンサイクルポリシーを効果的に使うには、事前に LR Range Test で最適なピーク学習率を特定する必要がある:
- 学習率を 1×10⁻⁷ から 10 まで指数的に増加させながら数百ステップ訓練
- 損失が最も急速に減少する領域の学習率を max_lr に設定
- 一般的には損失が最小になる点の 1/3〜1/10 を max_lr にする
from torch_lr_finder import LRFinder
finder = LRFinder(model, optimizer, criterion)
finder.range_test(train_loader, end_lr=10, num_iter=300)
finder.plot() # 損失 vs 学習率のグラフで最適値を目視確認
PyTorch での実装
from torch.optim.lr_scheduler import OneCycleLR
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5)
scheduler = OneCycleLR(
optimizer,
max_lr=5e-5, # LR Range Test で決定
total_steps=10000, # 総ステップ数
pct_start=0.3, # 30% をウォームアップに
div_factor=25, # 初期 LR = 5e-5 / 25 = 2e-6
final_div_factor=10000, # 最終 LR = 2e-6 / 10000 = 2e-10
anneal_strategy='cos' # コサイン減衰
)
for batch in dataloader:
loss = model(batch).loss
loss.backward()
optimizer.step()
scheduler.step()
optimizer.zero_grad()
コサインアニーリングとの比較
| 項目 | ワンサイクル | コサインアニーリング |
|---|---|---|
| 学習率の動き | 低→高→低→極小 | 高→低(warmup付きなら低→高→低) |
| 最適用途 | ファインチューニング、中規模訓練 | 大規模事前学習 |
| 超収束 | 発生しやすい | 発生しない |
| 必要ステップ数 | 少ない(1/5〜1/10) | 多い(標準) |
| Momentum 制御 | あり(逆相関) | なし |
| 採用例 | BERT FT, FastAI, 中規模CV | Llama 3, GPT-4, Mistral |
| 実装の容易さ | LR Range Test 必要 | 直感的 |
| LLM 事前学習での実績 | 限定的 | 広範 |
適用シナリオ
有効なケース
- BERT/RoBERTa のファインチューニング: 3〜10 エポックの短期訓練で超収束を発揮
- 中規模モデル(数億パラメータ)の事前学習: 計算リソースが限られる場合に訓練時間を短縮
- FastAI エコシステム: Jeremy Howard が強力に推奨、fastai ライブラリのデフォルト
不向きなケース
- LLM 大規模事前学習(数十億パラメータ): Llama 3 / GPT-4 クラスでは検証が不十分。コサインアニーリングが安全策
- 非常に長い訓練(数兆トークン): ワンサイクルの Phase 3 比率の設定が困難
FAQ
Q1: ワンサイクルポリシーの div_factor は何を意味する?
div_factor は初期学習率を決定するパラメータで、初期学習率 = max_lr / div_factor となる。デフォルトの 25 では、max_lr=5×10⁻⁵ の場合、初期学習率は 2×10⁻⁶ になる。この値が大きいほどウォームアップの幅が広くなり、初期の安定性が増す。
Q2: LLM の事前学習にワンサイクルを使ってはいけない?
使えないわけではないが、数十億パラメータ規模の LLM での大規模な検証事例が少ない。コサインアニーリングは Llama 3・GPT-4・Mistral で実証済みであり、リスクを避けるなら後者が推奨される。ただし、計算予算が限られる場合にワンサイクルで訓練時間を短縮する戦略は合理的。
Q3: pct_start の最適値は?
デフォルトの 0.3(全体の 30%)が多くのタスクで良好に機能する。ファインチューニングでは 0.1〜0.3、事前学習では 0.2〜0.4 が推奨範囲。pct_start が小さすぎるとウォームアップ不足で不安定、大きすぎるとピーク学習率での訓練時間が長くなり過学習リスクが上がる。