機械学習を実装していると、「lossが全く下がらない」「学習が安定しない」といった状況に誰もが一度は直面します。
この問題は一見単純に見えて、実際には学習率、データ品質、モデル構造、損失関数の設計、実装上のミスなど、複数の要因が絡み合っていることが多いのです。
ここでは、理論的背景 → よくある症状 → 実践的な改善策の流れで、lossが下がらない原因を体系的に解説します。
目次
学習率(Learning Rate)の不適切な設定
理論的背景
学習率は勾配降下法における「一歩の大きさ」を決定します。
- 高すぎる:最適解を飛び越え、lossが発散する。
- 低すぎる:更新が極端に小さく、lossが「ほとんど変わらないように見える」。
よくある兆候
- lossが全く減少しない、または乱高下する。
- Validation lossも安定しない。
NaNやinfが発生する。
改善策
- 代表的な初期値として
1e-3、1e-4、1e-5などを試す。 - 学習率スケジューラ(
ReduceLROnPlateau、CosineAnnealingLRなど)を導入。 - Optimizerに応じて適正範囲を調整(例:Adamは1e-3前後が多い)。
データの問題(スケーリング・品質・クラス不均衡)
理論的背景
モデルはデータ分布に依存して学習します。
入力のスケールやラベルの品質が悪いと、学習は進みません。
主な原因
- 正規化がされていない:画像が[0,255]のまま、特徴量に極端なスケール差。
- ラベルノイズが多い:誤った教師データが含まれている。
- クラス不均衡:特定クラスばかり予測するようになる。
改善策
- 標準化(mean=0, std=1)やmin-maxスケーリングを適用。
- ラベルの正確性を検証。
- 不均衡データには
class_weightやSMOTEを使用。 - lossが下がっても少数派クラスの精度が上がらない場合は、不均衡が疑われる。
モデルの表現力が適切でない
理論的背景
モデルが複雑すぎると過学習、単純すぎるとアンダーフィッティングが起こります。
兆候
- 過小表現力:train lossが下がらない。
- 過大表現力:train lossは下がるがval lossが上がる。
改善策
- ネットワークの層数・ユニット数を調整。
- Dropoutや正則化を導入。
- 転移学習を検討(特に画像・NLP系タスク)。
損失関数の不適切な選択
理論的背景
損失関数は「何を最適化するか」を定義します。
タスクに合っていなければ、lossが下がらないのは当然です。
よくある誤り
- 分類問題に
MSELossを使用(理論上は可能だが非効率)。 - 回帰タスクに
CrossEntropyLossを使用。 - カスタムlossが常に定数を返している。
改善策
- タスク別の推奨例:
- 分類:
CrossEntropyLoss、BCEWithLogitsLoss - 回帰:
MSELoss、L1Loss - セグメンテーション:
DiceLoss、IoULoss
- 分類:
- 出力層との整合性も確認。
- 例:PyTorchでは
CrossEntropyLossにSoftmaxを事前に適用しない(内部で処理される)。
- 例:PyTorchでは
最適化アルゴリズムや勾配の問題
理論的背景
勾配が消失・爆発すると学習が進みません。
特に深層ネットワークやRNNで顕著です。
原因
- 活性化関数(sigmoid, tanh)による勾配消失。
- 重み初期化の不適切さ。
- ネットワークの過度な深さ。
改善策
- 根本対策:初期化方法を見直す(Xavier、He Initialization)。
- 対症療法:勾配クリッピング(
clip_grad_norm_)。 - BatchNorm / LayerNormで勾配を安定化。
- Optimizerを変更(SGD → AdamWなど)。
バッチサイズ・データシャッフルの影響
理論的背景
バッチサイズやデータ順序は勾配のばらつきに影響します。
問題例
- 小さすぎるバッチ:勾配がノイズ的で不安定。
- データがシャッフルされていない:学習が偏る。
改善策
- 適切なバッチサイズ(例:32〜256程度)を試す。
DataLoaderでshuffle=Trueを設定。- データオーグメンテーションで多様性を増やす。
実装上のミス・学習手順の誤り
よくある初歩的なミス
model.train()を呼び忘れる(DropoutやBatchNormが無効化)。optimizer.zero_grad()を毎バッチで呼んでいない。loss.backward()とoptimizer.step()の順序が逆。deviceがCPU/GPUで不一致。- lossを平均せずスケールが崩れる。
チェックリスト
model.train()/model.eval()を正しく切り替えているかzero_grad()→backward()→step()の順序が正しいか- データとモデルが同じデバイスにあるか
過学習・アンダーフィッティング
現象
- 過学習:train lossは下がるがval lossが上昇。
- アンダーフィッティング:train lossすら下がらない。
改善策
- 過学習対策:正則化、データ拡張、EarlyStopping。
- アンダーフィッティング対策:モデル強化、学習率上げ、訓練時間延長。
初期化・ランダム性の影響
初期重みによって学習経路が大きく変わります。
特に深層モデルでは、不適切な初期化が勾配爆発を誘発します。
改善策
- 重み初期化法を変更(He, Xavier)。
torch.manual_seed()などでシード固定。- 複数回初期化して安定性を検証。
ログ・モニタリング不足
「lossが下がっていないように見える」だけで、実際はわずかに減っているケースもあります。
学習過程を可視化・記録することで真の挙動を確認できます。
推奨手法
- TensorBoardでloss・精度をグラフ化。
- 学習率スケジュール・勾配分布を記録。
- Validation lossとの乖離を追跡。
最終チェックリスト
| カテゴリ | 確認ポイント |
|---|---|
| 学習率 | 高すぎないか・低すぎないか? |
| データ | 正規化・ラベル品質・不均衡対応は? |
| モデル | 適度な表現力か?過学習していないか? |
| 損失関数 | タスクに適しているか?実装上のミスは? |
| Optimizer | 勾配が安定しているか? |
| 実装 | 学習ループの順序・デバイスは正しいか? |
| ログ | 学習曲線を追えているか? |
まとめ
lossが下がらない原因は、一見モデルの問題に見えても、実際には「データ前処理」「学習率」「損失関数」「実装手順」などが絡み合っているケースがほとんどです。
まずは上記のチェックリストをもとに、再現性を持って問題を切り分けることが重要です。
以上、機械学習のlossが下がらない原因についてでした。
最後までお読みいただき、ありがとうございました。
