この用語『学習率』を理解するうえで併せて押さえたい関連キーワード群です。 クリック(ホバー)で関連用語ページに飛べます。
学習率に関する重要キーワード一覧。 各リンクから本ページの該当セクションへジャンプできます。
🍰 まずはやさしく
学習率は、AIが学ぶときの歩幅のようなものです。
正解にたどり着く速さを決めるために使います。
スマホのアプリが学習するときにも使われています。
ここでは、ちょうど良い値の選び方を読みます。
勾配降下法の更新ステップ幅
🍰 まずはやさしく
学習率は、1回でどれだけ値を更新するかを決める設定です。
AIの学習を安定させて、精度を上げるために使います。
部活の練習で、一度に直す量を変える感覚に似ています。
このページでは、数値の意味について詳しく読みます。
このページは「学習率(learning rate, lr)」の詳細解説です。 ニューラルネットワークの勾配降下法で「1 ステップでどれだけパラメータを更新するか」を決めるハイパーパラメータで、 訓練の収束速度・最終精度・安定性をほぼ単独で支配する最重要パラメータの 1 つです。 大きすぎれば発散、 小さすぎれば収束しない/局所解に捕まる。 SSDSE-B-2026 で回帰モデルを学習するときの「lr=1e-3」の数値が何を意味するかを掘り下げます。
🍰 まずはやさしく
学習率は、山を下りるときの歩幅にたとえられます。
効率よく谷底まで降りるために使います。
買い物で、予算に合わせて買い物を調整する感覚です。
ここでは、使い方のコツや注意点を読みます。
ニューラルネットワークの多層構造を活かした学習。 大量のデータと計算資源、 そして適切な正則化が成功の鍵。
本ページでは 学習率 を、 定義・前提条件・使い方・落とし穴の順に整理して解説します。 厳密な定義より、 まず何を、 いつ、 どう使うかを理解することを優先してください。
比喩:学習率は「山を下りる歩幅」。 急斜面では大股で進めば速いが、 谷底付近で大股のまま行くと反対側の斜面を駆け上ってしまう。 だから「最初は大きく、 だんだん小さく」する学習率スケジュールが王道です。 SSDSE-B-2026 の人口(A1101)と着工建築物数(C3301)の単純線形回帰では、 lr=0.01 がほどよい歩幅、 lr=1.0 では発散、 lr=1e-6 ではほぼ動きません。
学習率は『勾配降下で一歩どれだけ進むか』を決めるパラメータ。 大きすぎると飛び越えて発散、 小さすぎると遅すぎて停滞。 機械学習で最も影響が大きいハイパーパラメータの一つ。 経験的には 1e-1 〜 1e-5 のレンジを対数スケールで探索する。 学習が進むにつれ下げるスケジューリング(warmup → cosine 等)が標準。
学習率(Learning Rate)は単独で覚えるものではなく、 ハイパーパラメータ という大きな枠組みの中での位置づけを理解することで応用範囲が広がります。 本ページの『🌐 関連手法』『🔗 関連用語』『📚 グループ教材』を順に辿ると、 関連概念のネットワークが見えてきます。
特に SSDSE-B のような実データに当てはめてみると、 教科書では抽象的に語られる概念が『47 都道府県の現実』に紐付き、 数字の意味が腑に落ちやすくなります。 次の『🧮 実値で計算してみる』セクションでは、 公開統計データを使って手を動かす例を紹介します。
| 症状 | 原因 | 対処 |
|---|---|---|
| 損失が NaN になる | 学習率が大きすぎて勾配爆発 | lr を 1/10 に。 gradient clipping を導入 |
| 損失が振動する | 学習率がやや大きい | lr を 1/3 に、 momentum を下げる |
| 損失が下がらない | 学習率が小さすぎる or 適切でも収束遅い | lr を 3-10 倍に。 warmup を追加 |
| 初期だけ NaN、 あとで安定 | 初期 step での勾配が大きすぎ | warmup (linear, 500-2000 step) を入れる |
| 訓練損失↓、 検証損失→ | 過学習。 lr 自体は適切な可能性 | 早めに lr を 1/10 にして fine-tune モード |
| 「plateau」になる | 局所解 or 鞍点に捕まる | ReduceLROnPlateau や CosineAnnealing |
学習率 $\eta$ を動かすと、 勾配降下 $x \leftarrow x - \eta\, f'(x)$ の一歩の大きさが変わります。 下の損失曲面は 2 つの谷(左が大域最適、 右が局所解)を持つ非凸関数 $f(x)=0.03\,(x^2-9)^2 + 0.4\,x + 2$。 スライダーで学習率を、 曲面上のドラッグ(タッチ可)で開始点を変えて、 ボールの軌跡と損失の下がり方がどう変わるかを体感してください。 計算は勾配降下の厳密な更新式そのものです。
ここで動かした $\eta$ は全パラメータ共通の固定値でした。 実際の深層学習では、 パラメータごと・時間ごとに実効的な歩幅を自動調整する適応的学習率が主流です。
関連:勾配降下法 / 損失関数 / ハイパーパラメータ。 Adam・SGD・モメンタム・鞍点は本ページ内の該当セクションも参照してください。
🍰 まずはやさしく
学習率は、計算で使うステップの幅のことです。
深層学習(AIの仕組み)を正しく動かすために使います。
テスト勉強で、1日に覚える量を決めることに似ています。
ここでは、数式や使い方のルールについて読みます。
勾配降下法の更新ステップ幅
英語名 Learning Rate。
この用語を理解・使用するときは、 次のような前提を意識してください:
コサイン減衰スケジュール。 $\eta_{\max}$ から滑らかに 0 まで下げる。
数式の各記号が『何の量で、 どの空間に住み、 どんな単位を持つか』を意識すると、 暗記でなく構造として理解できます。 SSDSE-B の都道府県データに当てはめて、 各シンボルが何に対応するかを上の Python 実装で確認しましょう。
まずは本ページの『💡 30 秒で分かる結論』と『🎨 直感で掴む』で全体像を掴み、 次に『🧮 実値で計算してみる』を 手を動かして追体験するのが最短です。 数式や深い理論はその後で十分。
本ページの『🌐 関連手法・派生』『🔗 関連用語』で対比される手法を確認し、 それぞれの適用条件と得意・不得意を表で比較するのが効果的です。 SSDSE-B のような共通データセットで両方走らせて結果を見ると違いが体感できます。
学習率は計算量を変えませんが、 必要な反復回数 $T$ を通じて総コストを何桁も動かします。 凸で滑らかな問題では、 最適な学習率のとき $T = O(1/\epsilon)$(1 次法)で誤差 $\epsilon$ に到達しますが、 学習率が小さすぎると $T$ が比例して増え、 大きすぎると発散していくら回しても到達しません。 目安として、 滑らかさ定数 $L$ に対して $\eta \le 1/L$ が収束条件で、 $\eta > 2/L$ で発散します。 つまり学習率は「速さのツマミ」ではなく「収束するかどうかの境界」です。 実務では小さめから始めて 3 倍ずつ上げ、 損失が跳ねた 1 つ手前を採る、 という探索が手堅い方法です。
『点推定値』だけでなく『不確実性(CI、 SE、 分散)』『前提条件のチェック結果』『代替手法との比較』『データ取得日と seed』をセットで報告するのが標準。 査読・レビューで問われる典型ポイントです。
学習率 η は様々なオプティマイザで「最後にかける係数」として登場します。 主要 3 種類を整理します。
$$ \theta_{t+1} = \theta_t - \eta \,g_t,\quad g_t = \nabla L(\theta_t) $$
$$ v_{t+1} = \mu\, v_t + g_t,\qquad \theta_{t+1} = \theta_t - \eta\, v_{t+1} $$
$$ m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t,\quad v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2 $$ $$ \theta_{t+1} = \theta_t - \eta \cdot \frac{\hat m_t}{\sqrt{\hat v_t} + \epsilon} $$
この「最大ステップサイズ」感覚が、 SGD で lr=0.1 が普通でも Adam では lr=1e-3 がデフォルトという違いの源。 つまり「学習率の絶対値」だけで比較してはいけない。
「学習率を時間とともに変える」のがスケジュール。 主要 8 種類を整理。
| 名前 | 数式 | 使い所 |
|---|---|---|
| Constant | $\eta_t = \eta_0$ | 小規模実験、 デバッグ |
| StepLR | $\eta_t = \eta_0 \gamma^{\lfloor t/s \rfloor}$ | ResNet 訓練、 30/60 epoch で 1/10 |
| ExponentialLR | $\eta_t = \eta_0 \gamma^t$ | 単純減衰 |
| CosineAnnealing | $\eta_t = \eta_{\min} + \tfrac{\eta_0-\eta_{\min}}{2}(1+\cos(\pi t/T))$ | 画像・LLM 標準 |
| CosineWithRestarts | Cosine + 定期的に reset | 局所解脱出 |
| OneCycleLR | linear up → linear down | 超高速訓練 (Smith 2018) |
| Warmup + Linear Decay | 線形上昇後、 線形降下 | Transformer 標準 |
| ReduceLROnPlateau | 監視メトリックが停滞したら 1/γ | ファインチューニング |
Loshchilov & Hutter (2017) の提案で、 現在の LLM・拡散モデル・ViT 訓練で最も使われるスケジュール。
$$ \eta_t = \eta_{\min} + \frac{1}{2}\bigl(\eta_{\max} - \eta_{\min}\bigr)\left(1 + \cos\left(\frac{t}{T}\pi\right)\right) $$
Goyal+ (2017) が「大バッチ訓練の安定化のためには warmup が必須」と示し、 以後デファクト。 訓練の最初 $T_w$ ステップだけ線形に lr を上げる:
$$ \eta_t = \begin{cases} \eta_{\max} \cdot t / T_w & t < T_w \\ \text{schedule}(t-T_w) & t \geq T_w \end{cases} $$
なぜ必要? 訓練の初期は重みがランダムなので勾配のばらつきが大きい。 ここで大きな lr を使うと一気に発散することがある。 warmup で「最初は慎重、 重みが整ってから本番」とする。
典型値:BERT は 10000 step、 GPT-3 は 375M token、 Stable Diffusion は 10000 step。 全訓練の 1-5% を warmup に充てるのが定番。
Goyal+ (2017) の「Accurate, Large Minibatch SGD」が示した経験則:
$$ \eta_\text{new} = \eta_\text{base} \cdot \frac{B_\text{new}}{B_\text{base}} $$
batch size を K 倍にしたら、 学習率も K 倍にする。 理由:勾配推定の分散が 1/K になるので、 同じ更新の「実効標準偏差」を保つには lr を K 倍する必要がある。
注意:あくまで近似で、 batch=8192 以上では「Square Root Scaling」($\sqrt{K}$ 倍)の方が良いという研究もある (You+ 2020, LAMB)。
| batch size | SGD lr | Adam lr |
|---|---|---|
| 32 | 0.001 | 3×10⁻⁵ |
| 256 (ResNet 標準) | 0.1 | 3×10⁻⁴ |
| 1024 | 0.4 | 1×10⁻³ |
| 8192 | 3.2 (要 warmup) | 8×10⁻³ |
「Adam の lr=1e-3」と「SGD の lr=1e-3」は全く違う意味です。 表で比較:
| 項目 | SGD | Adam |
|---|---|---|
| lr の意味 | 勾配の絶対値に直接掛ける | 正規化された勾配(最大 1)に掛ける |
| 画像分類デフォルト | 0.1 | 1×10⁻³ |
| NLP / LLM デフォルト | あまり使わない | 1×10⁻⁴ ~ 5×10⁻⁵ |
| 汎化性能 | 高め(特に画像) | やや劣る(要 weight decay) |
| 収束速度 | 遅い | 速い |
| 推奨 | CV 系(ResNet など)+ momentum 0.9 | NLP・Transformer 全般 |
最新では AdamW(weight decay を Adam から分離した版)が多くの場合で使われ、 lr=1e-4、 wd=0.1 が定番。
学習率を含む更新式 $\theta_{t+1} = \theta_t - \eta \nabla L(\theta_t)$ の各記号を、 一切数式を使わず分解します。
| 記号 | 読み方 | 意味(言葉で) |
|---|---|---|
$\theta_t$ | シータ・ティー | 時刻 t における全パラメータ(重み・バイアス)の束 |
$\theta_{t+1}$ | シータ・ティープラスワン | 1 ステップ更新した後のパラメータ |
$\eta$ | イータ(または lr) | 学習率。 損失曲面のどれだけを 1 歩で下りるか |
$\nabla L(\theta_t)$ | ナブラ L | 損失 L の勾配(最も急に上る方向) |
$-\eta \nabla L$ | マイナス・イータ・ナブラ・L | 下降方向に η ぶん進む変位ベクトル |
つまり「新しい重み=今の重み - 学習率×勾配」という極めて単純な式です。 ここで学習率 η が掛け算の係数として直接効くため、 値を 10 倍すれば 1 ステップの移動量が 10 倍になります。 これが学習率を「ハイパーパラメータの王様」と呼ぶ理由です。
SSDSE-B の総人口(A1101)と着工建築物数(C3301)の線形回帰で、 学習率を変えて 100 epoch 学習し、 train loss の収束カーブを観察。 lr=1e-1 では発散、 lr=1e-4 では収束遅い、 lr=1e-2 が最適という典型パターンを確認。
| 項目 | 条件 / 入力 | 結果 / 解釈 |
|---|---|---|
| lr=1.0 | 発散 | loss inf |
| lr=0.1 | 発散ぎりぎり | loss 振動 |
| lr=0.01 | 良好 | 10 epoch で収束 |
| lr=0.001 | やや遅い | 50 epoch で収束 |
| lr=0.0001 | 非常に遅い | 200 epoch で未収束 |
| lr scheduler | 0.1→0.01→0.001 | 両方の良いとこ取り |
※ 数値は SSDSE-B-2026.csv から抽出した実値、 もしくは典型的な学習設定での目安値です。 細部の数値は前処理・乱数 seed・実装により変動します。
Smith (2017) の「Cyclical Learning Rates for Training Neural Networks」で提案。 「lr を 10⁻⁷ から 1 まで指数的に増やしながら 1 epoch 訓練、 損失曲線を見て『最も急降下している点』の lr を選ぶ」。 fast.ai の実装で広まった。
この方法 1 回で「桁単位で適切な lr」が分かる。 グリッドサーチを 1000 回回すより遥かに効率的。
SSDSE-B-2026 の 47 都道府県データで、 総人口 (A1101) から着工建築物数(C3301)を予測する単純線形回帰を、 5 種類の lr でフィット。 損失曲線がどう変わるか実値で確認します。
💬 この実験は「lr の桁を 1 つ変えるだけで収束時間が 100 倍違う」という事実を可視化。 NN では損失曲面がもっと複雑で、 lr 探索はより慎重に。
| タスク | 推奨 lr | オプティマイザ | スケジュール |
|---|---|---|---|
| ResNet (ImageNet ゼロ学習) | 0.1 | SGD+momentum 0.9 | StepLR (30/60) |
| ViT (画像分類) | 1×10⁻³ | AdamW | Cosine + warmup |
| BERT ファインチューニング | 2×10⁻⁵ ~ 5×10⁻⁵ | AdamW | Linear + warmup |
| GPT-3 ゼロ学習 | 6×10⁻⁴ → 6×10⁻⁵ | AdamW | Cosine + warmup |
| LLaMA-2 7B fine-tuning | 2×10⁻⁵ | AdamW | Cosine + warmup |
| LoRA | 1×10⁻⁴ ~ 3×10⁻⁴ | AdamW | Cosine + warmup |
| DDPM(拡散モデル)学習 | 1×10⁻⁴ | AdamW | Constant(または cosine) |
| RL (PPO) | 3×10⁻⁴ | Adam | Linear decay |
覚え方:「ゼロから学習」より「ファインチューニング」の方が lr は 1-2 桁小さく。 これは「既に学習済みの良い重みを壊さないため」。
学習率スケジューラを 数式 で押さえると、 PyTorch のドキュメントを読まずに挙動を即座に理解できる。 ここでは 6 種類のスケジューラを並べる。
\( \eta_t = \eta_0 \) (全 step で固定)。 古典的だが、 学習後半で振動して loss が下げ止まる欠点がある。
\( \eta_t = \eta_0 \cdot \gamma^{\lfloor t / s \rfloor} \) (\( s \) step ごとに \( \gamma \) 倍)。 典型値は \( \gamma = 0.1, s = 30\,\text{epoch} \)。 ResNet 系の標準。
\( \eta_t = \eta_0 \cdot e^{-\lambda t} \) (連続的に指数減衰)。 \( \lambda \) を 1 つ決めるだけなので調整が楽。
\( \eta_t = \eta_\min + \tfrac{1}{2}(\eta_0 - \eta_\min)\left(1 + \cos(\pi t / T)\right) \) (\( T \) step で \( \eta_0 \) から \( \eta_\min \) へ滑らかに減衰)。 現代の標準。
\( t < t_w \) で線形に \( 0 \to \eta_0 \)、 その後 cosine annealing。 大バッチや Transformer で必須。
1 サイクルで \( \eta_0 / 25 \to \eta_0 \to \eta_0 / 10000 \) と上げて下げる。 短期学習で強い。
| スケジューラ | 向くタスク | 向かないタスク | PyTorch 実装 |
|---|---|---|---|
| Constant | 勾配ブースティング | 深層学習全般 | なし(デフォルト) |
| Step | ResNet, VGG | 短期学習 | StepLR |
| Exponential | 小規模 CNN | 大規模 Transformer | ExponentialLR |
| Cosine | 汎用 | 特になし | CosineAnnealingLR |
| Warmup+Cosine | Transformer, 大バッチ | 小サンプル | SequentialLR で合成 |
| OneCycle | 短期学習、 fine-tune | 非常に長い学習 | OneCycleLR |
→ 「困ったら Warmup + Cosine」「短期決戦なら OneCycle」「勾配ブースティングなら固定」 の 3 つを覚えておけば、 9 割の現場で正しい選択ができる。
学習率に関する文献を読むときに躓きがちな 20 個のキーワード を、 1 行ずつ定義する。
PyTorch で頻出する 5 つの実用レシピ をスニペットで示す。 コピペで動くように、 import から PyTorch のクラス名まで書き下している。 SSDSE-B-2026 など実データに当てはめる際の出発点として使える。
このコードでやること: SGD optimizer に CosineAnnealingLR を組み合わせ、 100 epoch で peak から min まで滑らかに減衰させる。 SSDSE-B-2026 の MLP に直結する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import torch import torch.nn as nn import pandas as pd from sklearn.preprocessing import StandardScaler from torch.utils.data import DataLoader, TensorDataset # ── 学習対象を用意する(総人口・出生数・消費支出 → 一般診療所数)── torch.manual_seed(42) _d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) _d = _d[_d['SSDSE-B-2026'] == 2023] _X = StandardScaler().fit_transform(_d[['A1101', 'A4101', 'L3221']].astype(float)) _y = StandardScaler().fit_transform(_d[['I5102']].astype(float)) X = torch.tensor(_X, dtype=torch.float32) y = torch.tensor(_y, dtype=torch.float32) loader = DataLoader(TensorDataset(X, y), batch_size=8, shuffle=True) class Net(nn.Module): def __init__(self): super().__init__() self.backbone = nn.Sequential(nn.Linear(3, 16), nn.ReLU()) self.head = nn.Linear(16, 1) def forward(self, x): return self.head(self.backbone(x)) model = Net() loss_fn = nn.MSELoss() def train_step(batch, model, optimizer, loss_fn): xb, yb = batch optimizer.zero_grad() loss = loss_fn(model(xb), yb) loss.backward() optimizer.step() return float(loss.detach()) def train_one_epoch(model, loader, optimizer, loss_fn): return sum(train_step(b, model, optimizer, loss_fn) for b in loader) / len(loader) def validate(model, X, y): with torch.no_grad(): return float(loss_fn(model(X), y)) from torch.optim import SGD from torch.optim.lr_scheduler import CosineAnnealingLR # lr=0.1 + momentum=0.9 はこのデータでは発散して loss が nan になる(実測)。 # 学習率は「大きすぎると壊れる」ことがそのまま出るので 0.02 から始める。 optimizer = SGD(model.parameters(), lr=0.02, momentum=0.9) scheduler = CosineAnnealingLR(optimizer, T_max=100, eta_min=1e-4) for epoch in range(100): loss = train_one_epoch(model, loader, optimizer, loss_fn) scheduler.step() print(f'最終 loss = {loss:.4f}') print(f'最終 lr = {scheduler.get_last_lr()[0]:.6f}') |
→ 100 epoch かけて lr=0.1 → 1e-4 まで滑らかに下げる。 画像分類で「とりあえず動く」設定。
このコードでやること: Transformer 系で標準の warmup + cosine を SequentialLR で合成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from torch.optim import AdamW from torch.optim.lr_scheduler import LinearLR, CosineAnnealingLR, SequentialLR optimizer = AdamW(model.parameters(), lr=1e-3, weight_decay=0.01) warmup = LinearLR(optimizer, start_factor=0.01, total_iters=1000) cosine = CosineAnnealingLR(optimizer, T_max=10000) scheduler = SequentialLR(optimizer, [warmup, cosine], milestones=[1000]) # 学習率がどう動くかを実際に 3000 step 分だけ回して確認する lrs = [] for step in range(3000): optimizer.step() # ここでは重み更新の中身は問わない scheduler.step() lrs.append(scheduler.get_last_lr()[0]) for s in [0, 100, 500, 999, 1000, 2000, 2999]: print(f'step {s:>4}: lr = {lrs[s]:.6f}') |
→ 最初の 1000 step で 1e-5 → 1e-3 へ線形に上げ、 その後 cosine で減衰。 BERT fine-tune や ViT pretraining の標準。
このコードでやること: OneCycle で短時間に高性能を狙う。 step ごとに scheduler.step() を呼ぶ点に注意。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from torch.optim import AdamW from torch.optim.lr_scheduler import OneCycleLR optimizer = AdamW(model.parameters(), lr=1e-3) scheduler = OneCycleLR(optimizer, max_lr=1e-2, steps_per_epoch=len(loader), epochs=20) for epoch in range(20): for batch in loader: train_step(batch, model, optimizer, loss_fn) scheduler.step() # step ごと(epoch ごとではない) print(f'最終 lr = {scheduler.get_last_lr()[0]:.8f}') print(f'検証 loss = {validate(model, X, y):.4f}') |
→ max_lr=1e-2 までいきなり上げて下げる。 短期間で同等以上の精度に到達することが多い。
このコードでやること: val_loss が改善しなくなったら lr を 1/10 に自動で下げる。 epoch ごとに val_loss を渡す。
1 2 3 4 5 6 7 8 9 10 11 | from torch.optim.lr_scheduler import ReduceLROnPlateau scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10) for epoch in range(200): train_one_epoch(model, loader, optimizer, loss_fn) val_loss = validate(model, X, y) scheduler.step(val_loss) # val_loss を渡す print(f'最終 val_loss = {val_loss:.4f}') print(f'最終 lr = {optimizer.param_groups[0]["lr"]:.8f}') |
→ 学習曲線を見ながら自動調整。 「とりあえず安全」な選択肢。
このコードでやること: backbone は小さい lr、 head は大きい lr に設定。 fine-tune の決定版。
1 2 3 4 5 6 7 8 9 | from torch.optim import AdamW # 事前学習済みの部分 (backbone) は小さい lr、 新しく付けた部分 (head) は大きい lr optimizer = AdamW([ {'params': model.backbone.parameters(), 'lr': 1e-5}, {'params': model.head.parameters(), 'lr': 1e-3}, ]) for g in optimizer.param_groups: print(f'パラメータ数 {sum(p.numel() for p in g["params"]):>4} : lr = {g["lr"]}') |
→ 「事前学習済の部分は壊さない」「新しい部分は速く学習」のバランス。
→ 以上 5 か条を実践していれば、 学習率に関する 9 割の問題は事前に防げる。 残りの 1 割は最先端の研究領域なので、 本記事の参考リンクから原典論文へ進もう。 学習率は単なる数値ではなく、 モデル・データ・最適化アルゴリズムを 統合的に制御するハンドル である。 ハンドルを使いこなせると、 学習の挙動が予測可能になり、 デバッグ時間も激減する。 そして何より、 自分のモデルが「なぜ動いている/動いていない」のかが直感的に分かるようになる。
f(x) = (x-3)² で異なる lr の収束を計算する。
| lr | x1 | x2 | x3 | 収束 |
|---|---|---|---|---|
| 0.1 | 0.6 | 1.08 | 1.464 | 遅 |
| 0.5 | 3.0 | 3.0 | 3.0 | 最適 |
| 0.9 | 5.4 | 1.08 | 4.536 | 振動 |
| 1.1 | 6.6 | -1.32 | 8.184 | 発散 |
1 2 3 4 5 6 | def f_grad(x): return 2*(x-3) for lr in [0.1, 0.5, 0.9, 1.1]: x = 0.0 for _ in range(3): x = x - lr * f_grad(x) print(f"lr={lr}: x_3 = {x:.3f}") |
💬 手計算 (Step 2) と Python 出力が完全一致。 lr=0.5 で最速、 lr=1.1 で発散。
SSDSE-B-2026 のような公的統計データを Python で扱う際の基本パターン:
1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd import numpy as np # データ読み込み df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) print(df.shape) print(df.dtypes) print(df.describe()) # 「学習率」の文脈で扱う場合の例: # 分野: 深層学習 # 関連手法は同カテゴリの他用語を参照してください。 |
具体的なコードは ニューラルネットワーク基礎 を参照してください。
分析結果を報告するときに含めるべき情報:
公的データ SSDSE-B(47 都道府県社会・人口統計)を読み込み、 学習率 を実際に動かす最小コードです。 引数のパスは平易さ優先で直書きしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) X = df[['A1101']].astype(float).values y = df['C3301'].astype(float).values X = (X - X.mean()) / X.std() y = (y - y.mean()) / y.std() for lr in [1.0, 0.1, 0.01, 0.001, 0.0001]: w, b = 0.0, 0.0 for _ in range(100): pred = w * X.flatten() + b err = pred - y w -= lr * (2 * err * X.flatten()).mean() b -= lr * (2 * err).mean() loss = ((w * X.flatten() + b - y) ** 2).mean() print(f'lr={lr}: final loss = {loss:.4f}') |
※ 上記スニペットは Python 3.10+ / pandas 2.x / numpy / scikit-learn を想定。 環境構築は『conda create -n ds python=3.11 pandas scikit-learn matplotlib』で十分です。
🎯 このコードでやること:SSDSE-B-2026 の総人口→着工建築物数回帰を、 Constant・StepLR・CosineAnnealing・OneCycleLR の 4 種類で訓練し、 損失曲線を比較する。
📥 入力例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import pandas as pd import numpy as np import torch from torch.optim.lr_scheduler import StepLR, CosineAnnealingLR, OneCycleLR df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) X = torch.tensor(df['A1101'].astype(float).values, dtype=torch.float32) y = torch.tensor(df['C3301'].astype(float).values, dtype=torch.float32) X = (X - X.mean()) / X.std() y = (y - y.mean()) / y.std() def train(scheduler_name, lr=0.1, epochs=200): w = torch.zeros(1, requires_grad=True) b = torch.zeros(1, requires_grad=True) opt = torch.optim.SGD([w, b], lr=lr) if scheduler_name == 'step': sched = StepLR(opt, step_size=50, gamma=0.5) elif scheduler_name == 'cosine': sched = CosineAnnealingLR(opt, T_max=epochs) elif scheduler_name == 'onecycle': sched = OneCycleLR(opt, max_lr=lr, total_steps=epochs) else: sched = None losses = [] for ep in range(epochs): pred = w * X + b loss = ((pred - y) ** 2).mean() opt.zero_grad(); loss.backward(); opt.step() if sched: sched.step() losses.append(loss.item()) return losses for name in ['const', 'step', 'cosine', 'onecycle']: l = train(name, lr=0.1) print(f'{name:10}: 最終損失 = {l[-1]:.5f}') |
📤 実行すると次の出力が得られる:
💬 結果の読み方:単純問題ではスケジュール差が見えないが、 ResNet50 を ImageNet で訓練すると差が顕著(Smith 2018 で 90 epoch → 30 epoch 短縮を達成)。
🎯 このコードでやること:SSDSE-B-2026 で 10⁻⁷ → 1 まで lr を指数的にスイープし、 「最も急降下する点」を可視化。
📥 入力例:上のセクションと同じ X, y(正規化済み)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import torch import numpy as np lrs = np.logspace(-7, 0, 100) # 10⁻⁷ から 1 まで 100 段階 losses = [] w = torch.zeros(1, requires_grad=True) b = torch.zeros(1, requires_grad=True) for lr in lrs: pred = w * X + b loss = ((pred - y) ** 2).mean() losses.append(loss.item()) if loss.item() > 10: # 発散したら打ち切り break loss.backward() with torch.no_grad(): w -= lr * w.grad b -= lr * b.grad w.grad.zero_(); b.grad.zero_() # 損失曲線の傾きが最小(最急降下)の点を探す log_lrs = np.log10(lrs[:len(losses)]) grad = np.gradient(losses, log_lrs) best_idx = np.argmin(grad) print(f'最適 lr = {lrs[best_idx]:.4e}') print(f'その時の損失 = {losses[best_idx]:.4f}') print(f'最急降下時の傾き = {grad[best_idx]:.4f}') |
📤 実行すると次の出力が得られる:
💬 結果の読み方:LR Finder は「グリッドサーチ不要で適切な lr が分かる」最強ツール。 PyTorch なら torch_lr_finder パッケージで 3 行で使える。 fast.ai では learn.lr_find() が標準ワークフロー。
🎯 このコードでやること:BERT/GPT 訓練の標準スケジュール「線形 warmup → cosine 減衰」を huggingface transformers の get_cosine_schedule_with_warmup で実装。 SSDSE-B-2026 の特徴量 5 つから人口を回帰する MLP で実演。
📥 入力例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import pandas as pd import torch import torch.nn as nn from transformers import get_cosine_schedule_with_warmup torch.manual_seed(0) # 実行のたびに同じ結果が出るようにする df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) feats = ['A4101', 'A4200', 'B4101', 'H5609', 'L322101'] X = torch.tensor(df[feats].astype(float).values, dtype=torch.float32) y = torch.tensor(df['A1101'].astype(float).values, dtype=torch.float32) X = (X - X.mean(0)) / X.std(0) y = (y - y.mean()) / y.std() model = nn.Sequential(nn.Linear(5, 16), nn.ReLU(), nn.Linear(16, 1)) opt = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=0.01) total_steps = 500 warmup_steps = 50 # 全体の 10% sched = get_cosine_schedule_with_warmup(opt, warmup_steps, total_steps) for step in range(total_steps): pred = model(X).squeeze() loss = ((pred - y) ** 2).mean() opt.zero_grad(); loss.backward(); opt.step(); sched.step() if step % 100 == 0: lr_now = opt.param_groups[0]['lr'] print(f'step {step:3d}: lr={lr_now:.5f} loss={loss.item():.5f}') |
📤 実行すると次の出力が得られる:
💬 結果の読み方:HuggingFace の Trainer は内部でこのスケジュールを使う。 設定したい時は TrainingArguments(lr_scheduler_type="cosine", warmup_ratio=0.1) で 1 行。
🎯 このコードでやること:検証損失が一定期間下がらなくなったら自動で lr を 1/10 にする ReduceLROnPlateau を SSDSE で実演。
📥 入力例:同じ X, y。 train/val を 38/9 で分割。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from torch.optim.lr_scheduler import ReduceLROnPlateau import torch, torch.nn as nn, pandas as pd torch.manual_seed(0) # 実行のたびに同じ結果が出るようにする df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) X = torch.tensor(df[['A4101','B4101','H5609']].astype(float).values, dtype=torch.float32) y = torch.tensor(df['A1101'].astype(float).values, dtype=torch.float32) X = (X-X.mean(0))/X.std(0); y = (y-y.mean())/y.std() X_tr, y_tr = X[:38], y[:38] X_va, y_va = X[38:], y[38:] model = nn.Sequential(nn.Linear(3,8), nn.ReLU(), nn.Linear(8,1)) opt = torch.optim.Adam(model.parameters(), lr=0.01) sched = ReduceLROnPlateau(opt, mode='min', factor=0.1, patience=20) for ep in range(300): model.train(); pred = model(X_tr).squeeze() loss = ((pred-y_tr)**2).mean() opt.zero_grad(); loss.backward(); opt.step() with torch.no_grad(): vl = ((model(X_va).squeeze()-y_va)**2).mean() sched.step(vl) if ep % 50 == 0: print(f'ep {ep:3d}: train={loss.item():.4f} val={vl.item():.4f} lr={opt.param_groups[0]["lr"]}') |
📤 実行すると次の出力が得られる:
💬 結果の読み方:「lr の手動チューニングは時間の無駄」というレベルまで自動化が進んだ。 Adam + ReduceLROnPlateau の組み合わせは多くの実務で十分高性能。
scheduler.step() を毎 step(または毎 epoch)必ず呼ぶ必要。 forgetting すると lr が constant のまま。 ログで lr の推移を必ず確認。lr_find_callbacks や PyTorch の param_groups で実現。『学習率』は『ハイパーパラメータ』カテゴリに属する重要概念で、 以下の関連概念群と密接につながっています。
ハイパーパラメータ
├── 前提
│ └── 数学・統計の基礎
├── 学習率 ← このページ
│ ├── 派生 1
│ ├── 派生 2
│ └── 応用
└── 並列・対比される手法
├── 別アプローチ A
└── 別アプローチ B
完全な概念マップは 🗺 概念マップ で確認できます。
古典的には固定値が使われたが、 2000 年代に SGD with momentum + step decay が標準化。 2017 年の Smith の Cyclical Learning Rate, OneCycle で動的調整が普及。 2018 年以降、 大規模学習のための warmup + cosine annealing が定番。 最近は LR-free optimizer (Schedule-Free 2024) も登場。
学習率の歴史は「固定値 → スケジュール → 適応 → 不要へ」という流れで読めます。 長らく手で決める定数でしたが、 Smith (2017) の Cyclical Learning Rate が「上げ下げを繰り返したほうが速い」という直感に反する結果を示しました。 大規模学習では warmup(最初だけ小さく)が必須になり、 近年は Schedule-Free (2024) のように学習率スケジュール自体を無くす方向の研究も出ています。 「最も原始的なハイパーパラメータが、 いまだに研究対象である」という事実自体が示唆的です。
『学習率』は理論だけでなく、 産業・研究の様々な現場で実用されています。 ここでは代表的な応用を 6 つ挙げます。
どの応用も「何を入力とし、 何を出力すべきか」を整理した上で、 上の Python 実装をベースに拡張するアプローチが定石です。 SSDSE-B のような公開データセットで小さく試し、 動作確認できてから本番データに展開すると安全です。
『学習率』には多くの派生・バリエーションがあります。 代表的なものを精度・特徴で比較した表です。
| 手法 / バージョン | 指標 / 特徴 | 備考 |
|---|---|---|
| 固定 lr | シンプル | 調整必要 |
| Step decay | 段階的に下げる | 古典 |
| Exponential decay | 指数減衰 | 滑らか |
| Cosine annealing | コサインで 0 へ | 終盤強い |
| OneCycle | warmup + decay | 高速学習 |
数値は論文公表時点のもので、 計測条件(データ・前処理・ハイパーパラメータ)が異なります。 自分の問題で再評価することを推奨。
『学習率』は周辺の似た用語と混同されがちです。 ここでは特に紛らわしい用語との本質的な違いを整理します。
data/raw/SSDSE-B-2026.csv。 47 都道府県の社会・人口指標| スケジュール | 数式 | 用途 |
|---|---|---|
| Constant | η_t = η | シンプル、 短時間学習 |
| Step Decay | N epoch ごとに 1/10 | 古典的、 ResNet 用 |
| Exponential | η_t = η * γ^t | 滑らかな減衰 |
| Cosine | η_max * (1+cos(πt/T))/2 | 終盤強い、 標準 |
| Cosine with Warmup | 線形 warmup → cosine | Transformer 標準 |
| OneCycle | 三角波 | 高速学習 |
| ReduceLROnPlateau | val_loss 停滞で減衰 | 適応的 |
| Polynomial Decay | η_t = η_max * (1-t/T)^p | 柔軟 |
バッチサイズを N 倍にする場合、 学習率も N 倍にするのが線形スケーリング則(Goyal 2017)。 ただし大バッチでは warmup が必須(最初の 5〜10 エポックは線形に lr を上げる)。 LARS、 LAMB は大バッチ学習専用 optimizer。
本セクションは『学習率』の技術的核心を深掘りしました。 表面的な使い方を超えて、 内部の仕組みを理解することで、 トラブル時の診断や応用時のカスタマイズが可能になります。 SSDSE-B のような実データに当てはめながら、 ぜひ手を動かして確認してください。
SSDSE-B の人口(A1101)から着工建築物数(C3301)を線形回帰で予測する場合、 標準化後なら lr=0.01〜0.1 で安定収束。 lr=1.0 では振動・発散、 lr=0.0001 では収束まで 1000 エポック以上必要。 同じデータでも optimizer によって最適 lr が変わるため、 各組み合わせで LR Range Test を行うのが堅実。
『学習率』を実務に取り入れる際の実用的な補足知識でした。 理論と実践の往復で理解が深まります。
ここからは 自分で考えてみる ための練習問題セットです。 学習率の挙動・落とし穴・スケジューラ選択について、 短答 → 計算 → 設計 の順で深さを上げていきます。 まずは答えを見ずに紙とペンで考え、 詰まったら本文の該当セクションへ戻ってください。
パラメータ \( w \) を最小化する目的関数を \( L(w) = (w - 3)^2 \) とする。 勾配は \( \nabla L = 2(w-3) \) である。 初期値 \( w_0 = 0 \) から学習率を変えて勾配降下法を 3 ステップ走らせ、 \( w_3 \) と \( L(w_3) \) を計算せよ。
ヒント: 更新式は \( w_{t+1} = w_t - \eta \cdot 2(w_t - 3) \)。 ケース D では振動が増幅して発散する。 ケース B はちょうど 1 ステップで最適解に到達する『理論的最適』学習率である(凸 2 次関数で \( \eta = 1/L_\mathrm{Lipschitz} = 0.5 \) のとき)。
あなたは SSDSE-B-2026(都道府県別の社会・経済統計) を用いて、 出生数(A4101)を他の特徴量から予測する 3 層 MLP を PyTorch で実装する。 サンプル数 47、 特徴量 約 100、 batch_size=16, epochs=200 とする。 このとき:
→ ケース D のように \( \eta \) が 1/L_Lipschitz = 0.5 の 2 倍を超えると、 凸 2 次関数でも振動が増幅して発散する。 これが「lr が大きすぎると死ぬ」のメカニズム。
| 理解度レベル | 基準 | 次の学習方針 |
|---|---|---|
| ★ レベル 0 | Q1 を 2 問以下しか答えられない | 本文の「💡 30 秒で分かる結論」と「🎨 直感で掴む」をもう 1 度読む |
| ★★ レベル 1 | Q1 を全問答えられるが Q2 で詰まる | 「🐍 Python 実装」を写経して動かす、 数式の意味を 1 文ずつ訳す |
| ★★★ レベル 2 | Q1, Q2 はできるが Q3 で答えに迷う | 関連手法(warmup, cosine, OneCycle)の比較表を自分でまとめてみる |
| ★★★★ レベル 3 | 全問答えられるが理由が曖昧 | SSDSE-B-2026 で実際に MLP を組み、 lr を変えながら学習曲線を比較する |
| ★★★★★ レベル 4 | 全問解け、 友人にも説明できる | 上位概念「ハイパーパラメータ」のページへ進む |
学習率の挙動を直感的に把握するため、 SSDSE-B-2026 の実データから生成した 3 種類の図を掲げる。 いずれも本リポジトリ(code/glossary_make_basic_figs.py 系統で生成済み)の実出力であり、 合成データではない。
→ 図 1〜3 から分かる通り、 SSDSE-B-2026 のような 都道府県別の小サンプル・異分散データ では、 学習率の安全圏は教科書の理論値(\( 1/L_\mathrm{Lipschitz} \) など)よりも 1 桁小さい所にある。 特に図 3 のように分散がグループ間で 3 倍以上違う場合、 標準化と学習率の控えめな設定 をセットで採用するのが鉄則。
「学習率の選び方が結果にどれだけ効くか」を実感するための 再現可能な手順 を示す。 47 都道府県、 1 特徴量「人口(A1101)」から「出生数(A4101)」を線形回帰する単純な題材で、 SGD の lr を変えて学習曲線を比較する。
このコードでやること: SSDSE-B-2026 の都道府県別データを読み、 人口(A1101)と出生数(A4101)の対応を取り出す。
📥 入力データ(SSDSE-B-2026 抜粋、 5 行のみ):
このコードでやること: 標準化した特徴量で SGD を 1000 epoch 回し、 lr=1e-5, 1e-4, 1e-3, 1e-2, 1e-1 の 5 種類で MSE の推移を記録する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) x = df['A1101'].values.astype('float64') y = df['A4101'].values.astype('float64') x = (x - x.mean()) / x.std() y = (y - y.mean()) / y.std() def sgd(lr, n_epoch=1000): w, b = 0.0, 0.0 losses = [] for _ in range(n_epoch): pred = w * x + b err = pred - y grad_w = (err * x).mean() grad_b = err.mean() w -= lr * grad_w b -= lr * grad_b losses.append((err ** 2).mean()) return w, b, losses # 標準化済みデータの二乗誤差は曲率が緩いので、 lr=0.1 程度では発散しない。 # 「小さすぎる → 適切 → 発散」の 3 領域を全部見せるには lr=2〜3 まで振る必要がある。 for lr in [1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0, 2.0, 3.0]: w, b, losses = sgd(lr) if not np.isfinite(losses[-1]) or abs(w) > 1e3: print(f'lr={lr:.0e}: 発散(loss が無限大まで膨らんだ)') else: print(f'lr={lr:.0e}: final loss={losses[-1]:.4f}, w={w:.3f}') |
📤 実際に動かすと次の出力が得られる:
💬 結果の読み方: 3 つの領域がはっきり出ている。 (1) 小さすぎる lr=1e-5〜1e-3 は 1,000 epoch 回しても w が 0.010 → 0.623 までしか進まず、 損失が下げ止まらない。 (2) 適切 lr=1e-2〜1.0 はどれも同じ最終損失 0.0277・w=0.986 に到達する ── 収束先は lr に依存せず、 変わるのは「そこに着くまでの速さ」だけ。 (3) 大きすぎる lr=3.0 で損失が無限大へ発散する。
境界が lr=2.0 にあるのは偶然ではない。 標準化済みデータの二乗誤差では損失の曲率(ヘッセ行列の最大固有値)が 1 になるため、 最急降下法の安定条件は $\text{lr} < 2/\lambda_{\max} = 2$。 実際 lr=2.0 はちょうど境界で、 w が 0 のまま振動して収束しない(損失 1.0000 = 何も学習していない状態)。
「発散する学習率」は 0.1 ではない点に注意してほしい。 よく見る「lr=0.1 は大きすぎる」という助言は、 深層ネットワークのように曲率が大きいモデルの話であって、 安全な lr はデータとモデルの曲率で決まる。 だからこそ、 自分のデータで上のような lr スイープ(lr finder)を 1 回やる価値がある。
| 学習率 | 学習曲線の特徴 | 原因の解釈 | 対処 |
|---|---|---|---|
| 1e-5 | 右肩下がりだが平坦に近い | ステップが小さすぎる | lr を 10~100 倍に |
| 1e-4 | 緩やかに下がるが下げ止まらない | epoch 数不足 | epoch を増やすか lr を上げる |
| 1e-3 | 100 epoch で十分収束、 平坦化 | 適切な学習率 | このまま採用 |
| 1e-2 | 20 epoch で収束、 軽い振動あり | 高速だが安定性に注意 | cosine annealing で終盤を抑制 |
| 1e-1 | 数 epoch で NaN へ発散 | 学習率が大きすぎる | 1/10 に下げる、 gradient clipping を併用 |
→ この 5 段階比較は、 「lr finder」の本質を 5 行のコードで体験 することと等価。 自分のデータで同じ実験を 1 回やるだけで、 学習率の感度が劇的に身につく。
学習率がからむ実問題は、 「lr を変えれば解決」とは限らない。 ここでは 5 つの典型シナリオ を示し、 lr 以外に注目すべき要因を整理する。
最も多い症状。 まず lr を 1/10 にする。 それでも NaN なら、 (1) 入力データに NaN/Inf が含まれていないか, (2) log や sqrt の中身が負やゼロにならないか, (3) softmax の入力スケールが大きすぎないか を確認。 lr 以外の要因のことが多い。
これは「lr が高すぎる」サインだが、 step decay の段でも起こり得る。 学習率を下げて滑らかになれば lr 過大、 そうでなければスケジューラの境界設定を疑う。
過学習。 lr ではなく 正則化(weight decay, dropout)と early stopping を導入する。 ただし、 lr を上げると暗黙の正則化効果(SGD は flat minima を好む)が増すため、 lr を上げる戦略も有効。
batch_size を 2 倍にしたら lr も 2 倍にする「linear scaling rule」(Goyal+2017)が基本。 ただし lr が 1e-1 を超える場合は warmup を必須とする(さもないと序盤で発散)。
OneCycleLR + AdamW で「短期間集中」の学習を試す。 1 サイクルで lr を上げて下げるため、 通常 30%~50% 短い学習時間で同等以上の精度に到達する。
| 症状 | 最初に疑う原因 | 2 番目に疑う原因 | 最終手段 |
|---|---|---|---|
| NaN | lr を 1/10 に | 入力に NaN/Inf | gradient clipping (max_norm=1.0) |
| 振動 | lr 過大 | batch_size 不足 | cosine annealing 導入 |
| 過学習 | weight decay | early stopping | データ拡張 |
| 遅い | lr を上げる | linear scaling | OneCycle 採用 |
| 序盤発散 | warmup 不足 | 初期化が悪い | lr を 1/3 に + warmup 1000 step |
A. はい。 これを discriminative learning rate と呼び、 fine-tuning では事実上の標準。 入力に近い層ほど小さく、 出力に近い層ほど大きくする。 PyTorch では optimizer = SGD([{params: layer1.parameters(), lr: 1e-4}, {params: head.parameters(), lr: 1e-2}]) のように指定する。
A. いいえ。 Adam は SGD より「lr の感度が低い」だけで、 完全に気にしなくてよいわけではない。 デフォルトの 1e-3 が常に最適とは限らず、 タスク・モデル・バッチサイズで 1e-4 ~ 3e-3 の範囲で調整する。
A. はい。 lr を上げると学習曲線がノイジーになるため、 「val_loss が patience=10 epoch 連続で改善しない」のような閾値は patience を伸ばすか、 EMA(指数移動平均)で平滑化した val_loss を見るとよい。
A. 概ね同じだが、 強化学習は 分布シフトが大きい ため、 教師あり学習より 1 桁小さい lr を使うのが安全。 PPO のデフォルトが 3e-4 なのもこのため。
A. 変わる。 Bengio (2012) の「Practical Recommendations」では、 「1 つだけハイパーパラメータをチューニングするなら学習率」 と明言されている。 lr を 10 倍間違えれば、 精度が半分になることも珍しくない。
学習率に関する研究は、 ニューラルネットワークの歴史とほぼ同じ長さがある。 ここでは 10 年単位での節目 をまとめる。 用語を「研究者たちの努力の連鎖」として血の通った概念として理解するための補助である。
| 年 | 提案者・出来事 | 何が新しかったか |
|---|---|---|
| 1951 | Robbins & Monro | 確率的近似法。 学習率 \( a_t = a/t \) のように 時間に応じて単調減少 させる定理を確立。 これが「step decay」の理論的起源。 |
| 1986 | Rumelhart, Hinton, Williams | backpropagation の論文で、 lr とモメンタムの組み合わせを実装上のテクニックとして紹介。 |
| 1998 | LeCun, Bottou, Orr & Müller | "Efficient BackProp" で、 入力正規化と学習率のスケール調整、 二次情報を使った lr の自動推定を整理。 |
| 2011 | Duchi, Hazan & Singer (AdaGrad) | 座標ごとに学習率を変える「適応的」スケジューラの嚆矢。 スパース勾配で効果。 |
| 2012 | Hinton (Coursera 講義) | RMSProp を提案。 AdaGrad の lr 減衰が早すぎる問題を、 勾配二乗の指数移動平均で解決。 |
| 2014 | Kingma & Ba (Adam) | Momentum + RMSProp 統合。 デフォルト lr=1e-3 で「とりあえず動く」標準となる。 |
| 2016 | Loshchilov & Hutter | SGDR (Stochastic Gradient Descent with Warm Restarts)。 cosine annealing の原型を提示し、 「学習率を周期的に再起動」する設計を導入。 |
| 2017 | Smith (Cyclical LR / LR Finder) | 「学習率を上げながら 1 epoch 走らせて、 損失最小の lr を探す」LR finder を考案。 fast.ai が実装で広めた。 |
| 2017 | Goyal+ (Facebook AI) | "Accurate, Large Minibatch SGD"。 batch_size に比例して lr を上げる linear scaling rule + warmup を確立。 ImageNet を 1 時間で訓練。 |
| 2018 | Smith (OneCycleLR) | 1 サイクル内で lr を上げて下げる、 短期間学習の決定版。 PyTorch にも標準で実装。 |
| 2019 | Loshchilov & Hutter (AdamW) | Adam の weight decay を正しく分離。 lr スケジューラとの相性が劇的に改善。 |
| 2020 | Liu+ (LAMB) | 超大バッチ(32K~64K)でも学習可能な lr 設計。 BERT を 76 分で訓練。 |
| 2024 | Defazio+ (Schedule-Free Optimizer) | スケジューラ 不要 の最適化手法。 lr 1 つで最終性能を出す可能性を提示。 |
→ 1951 年の Robbins-Monro から 2024 年の Schedule-Free まで、 約 70 年の歴史。 学習率は 「最も古く、 最も新しい」ハイパーパラメータ と言える。
学習率について巷で流布する「神話」を、 根拠を示して潰していく。 ここを 自分で 読み込めば、 SNS や Q&A サイトでの誤情報に振り回されなくなる。
→ 嘘。 小さすぎる lr は、 (a) 学習が遅すぎて時間切れ、 (b) saddle point から抜け出せない、 (c) 暗黙の正則化効果が消えて過学習しやすくなる、 という 3 重の害がある。 「適切な大きさ」が正解。
→ 嘘。 Adam は lr の 感度を下げる が、 ゼロにはしない。 タスク次第で 1e-4 ~ 3e-3 の調整は必須。 また、 Adam のデフォルト 1e-3 は画像認識では妥当だが、 言語モデル fine-tuning では 1e-5 ~ 5e-5 が標準。
→ 嘘。 多くのタスクでは cosine annealing 単独 で十分。 OneCycle や warmup は、 大バッチや短期学習のような 特定状況 でのみ効果を出す。 「困ったら cosine」が無難。
→ 半分嘘。 大規模言語モデルの pretraining は lr=6e-4 程度(GPT-3 は 6e-4)、 fine-tune が 1e-5 ~ 5e-5。 「小さい」のは fine-tune の話で、 pretraining は意外と大きい。
→ 嘘。 lr finder が示すのは 「ここから上は危険」の境界 であり、 採用すべきは境界の 1/10 程度。 自動化できるが、 最終確認は学習曲線の目視が必要。
→ 嘘。 lr 2 倍は確かに収束が速くなることもあるが、 振動と発散のリスクが指数的に増える。 安全に高速化するには batch_size を同時に 2 倍にする「linear scaling rule」が必要。
→ 嘘。 現代のレシピは warmup(最初の数千 step で 0→peak)+ cosine annealing(残りで peak→0) が標準。 「固定 lr」は 2014 年以前の流儀。
あなたが今、 実際の業務や研究で学習を回す前に、 10 項目 を確認しよう。 1 つでも未確認なら、 学習を始める前に戻ってチェックすること。
→ この 10 項目をすべてチェック済の状態で学習を回せば、 lr 起因のトラブルの 8 割は事前に防げる。 残りの 2 割は実行中の学習曲線の挙動で初めて分かる現象なので、 1 つ目の training run を「探索」と位置付けて短時間で回すのが現代の流儀。
学習率の推奨値は ドメイン × モデル × タスク で大きく変わる。 ここでは現場で頻出する 12 組のレシピを表にまとめる。 これらの値は単なる経験則ではなく、 ベンチマーク論文や公式リファレンスの数値に基づいている。
| ドメイン | モデル / タスク | optimizer | lr | スケジューラ |
|---|---|---|---|---|
| 画像分類 | ResNet50 + ImageNet(教師あり) | SGD+momentum | 0.1(batch=256) | step decay (30, 60, 90 epoch) |
| 画像分類 | ViT-Base + ImageNet | AdamW | 1e-3 | warmup 10K step + cosine |
| 物体検出 | YOLOv5/8 | SGD | 0.01 | linear warmup + cosine |
| セグメンテーション | U-Net | Adam | 1e-4 | ReduceLROnPlateau |
| NLP 事前学習 | BERT-Base | AdamW | 1e-4 | warmup 10K + linear decay |
| NLP 事前学習 | GPT-3 (175B) | Adam | 6e-5(peak) | warmup 375M tokens + cosine to 10% |
| NLP fine-tune | BERT / RoBERTa | AdamW | 2e-5 ~ 5e-5 | warmup 10% + linear |
| 音声認識 | Whisper / Wav2Vec2 | AdamW | 5e-5 | warmup + linear |
| 表形式(小サンプル) | XGBoost / LightGBM | — | 0.05 ~ 0.1 | なし(n_estimators で調整) |
| 表形式(深層) | TabNet / FT-Transformer | AdamW | 1e-3 | cosine |
| 強化学習 | PPO(OpenAI Baseline) | Adam | 3e-4 | linear decay to 0 |
| 拡散モデル | Stable Diffusion fine-tune | AdamW | 1e-5 | constant + warmup |
→ 表から見える法則: 「モデルが大きいほど lr は小さい」, 「事前学習 > fine-tune の lr」, 「Adam 系は SGD の 1/10 程度」。 自分のタスクが表のどこに近いかで初期値を決め、 そこから lr finder で微調整するのが現代の流儀。
学習が思うように進まないときの判断フロー。 学習率に 関係する症状 と 関係しない症状 を明確に分離する。
→ このフローを 印刷して机に貼っておく と、 学習が止まった瞬間に lr を疑うのか、 別の要因を疑うのか、 5 秒で判断できる。
学習率は最適化アルゴリズムの中核ハイパーパラメータであり、 前段の正規化と後段のスケジューリング・ウォームアップを統合することで安定収束する。
上流のデータ前処理 (バッチ正規化等) が損失曲面の急峻さを和らげ、 並列の Adam/RMSprop が学習率を自動調整し、 下流の Warmup/Cosine 減衰スケジューラが大規模学習の安定性を確保する流れで「学習率設計」が深層学習の核心になる。
学習率 を実際の課題に当てはめるとき、 用語固有の判断軸に沿って次の 3 段階で適切な選択を行う。
このフローは深層学習における学習率設計の核心。 学習率は単一値ではなく Schedule (時間変化) として設計するのが現代 (2026) の標準であり、 Warmup + Cosine 減衰が事実上のデファクトとなっている。
本ページはすでに広範な解説を持ちますが、 学習率という概念を 「直感 → 落とし穴 → 発展」 の 3 層で一望できるよう、 要点だけを凝縮した追補です。 既存セクションと重複する話題は、 該当セクションや ハイパーパラメータ・勾配降下法 へのリンクで補います。
学習率 $\eta$ は更新式 $\theta \leftarrow \theta - \eta\,\nabla L$ の係数、 すなわち勾配方向へ踏み出す 1 歩の大きさ です。 方向(勾配)は損失曲面が決めますが、 どれだけ進むかは $\eta$ が決めます。 だからこそ「最も影響が大きいハイパーパラメータ」と呼ばれます(Bengio 2012 は「1 つだけ調整するなら学習率」と明言)。
| 落とし穴 | 何が起きるか | 対処 |
|---|---|---|
| ① 大きすぎ発散 | 序盤で損失が NaN/∞ に吹き飛ぶ | $\eta$ を 1/3〜1/10、 gradient clipping、 warmup |
| ② 小さすぎ停滞 | 下がるが下げ止まらない/時間切れ | $\eta$ を 3〜10 倍、 epoch 追加 |
| ③ 固定 vs スケジュール | 固定だと序盤発散↔終盤精度が両立しない | warmup→cosine 減衰(現代の定番) |
| ④ スケール依存(標準化) | 未標準化だと安全 $\eta$ が桁で激変 | 特徴量を mean=0/std=1 に標準化 |
| ⑤ データ/モデル依存 | 他所の最適 $\eta$ が自分の設定で無効 | 自分のデータで LR range test |
| ⑥ warmup 不足 | 初期 step の大勾配で序盤だけ発散 | linear warmup 500〜2000 step |
| ⑦ バッチとの相互作用 | batch を上げたのに $\eta$ 据え置きで学習が遅い | linear scaling(batch K 倍→$\eta$ K 倍) |
「標準化するだけで安全な学習率が何桁も変わる」ことは、 SSDSE-B-2026(2023 年・47 都道府県)の実データで具体的に確認できます。 人口 A1101 から出生数 A4101 を単回帰(バイアスなし、 $\hat y = w\,x$)するとき、 MSE の $w$ に関する曲率は $L = 2\,\overline{x^2}$、 勾配降下の発散境界は $\eta_{\max} = 2/L$ です。 これを 生の人口と標準化後で比べます。
→ 同じデータ・同じモデルでも、 標準化を怠るだけで許される学習率が約 13 桁小さくなる(生では $\eta$ を $10^{-14}$ 台にしないと発散)。 学習率は絶対値だけを他所から真似てはいけない、 という⑤の裏返しでもあります。 上の値は data/raw/SSDSE-B-2026.csv(cp932, skiprows=[1], 2023 年抽出)の実測で、 合成値ではありません。 本ページ『🧪 ミニ実験ノート』の 5 段階スイープと合わせて追体験してください。