LASSIC Media らしくメディア
過学習の原因と防ぎ方、正則化と検証データで抑える
監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)
この記事の結論
- 過学習は、学習用データでの誤差は小さいのに、学習に使っていないデータでの誤差との差が大きく開いてしまう状態です。
- 抑える手段は正則化・早期終了・ドロップアウト・データの追加で、どれをどこまで効かせるかは検証用データの誤差で決めます。
- テスト用データは最初に切り離して最後に1回だけ使い、前処理も学習用データの中だけで行うと、見かけの精度にだまされません。
※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。
過学習という言葉は知っていても、手元の評価では精度が高いのに本番で外れが目立つ理由をうまく説明できない。正則化やドロップアウトを入れてはみたものの、どれをどの程度効かせればよいのかが分からない——。機械学習のモデルを業務に組み込む現場では、こうした迷いが起こりがちです。過学習とは、モデルが学習用データの細かなくせや雑音まで覚え込み、学習に使っていないデータに対する誤差が大きくなってしまう状態を指します。
需要の予測や不正な取引の検知など、学習したモデルを使う業務では避けて通れない問題です。ただし万能の対策はなく、抑え込みすぎると今度は学習用データにすら合わない「未学習」に振れます。本記事では、システム開発やIT運用に携わる方に向けて、過学習が起きる仕組み、短いコードで見る具体例、正則化と検証データの使い方、つまずきやすい点、そして外部に頼むときに確認したい点を整理します。
目次
過学習とは
深層学習の教科書として知られるGoodfellowらの『Deep Learning』は、機械学習の出来を決める要素に、学習用データでの誤差を小さくすることと、テスト用データでの誤差との差を小さくすることの2つを挙げています。前者に失敗した状態が未学習、後者に失敗した状態が過学習です。教科書は過学習を「the gap between the training error and test error is too large」、つまり学習時とテスト時の誤差の差が大きすぎる状態と定義しています。*1
機械学習の目的は、学習用データの誤差を下げることそのものではありません。教科書は、新しい入力に対する誤差の期待値を汎化誤差(はんかごさ)と呼び、これを小さくすることが、単なる最適化の問題と機械学習とを分けると説明しています。業務で問われるのも、明日届く注文や来月の取引にどれだけ当たるかです。
scikit-learnの利用者向けガイドは、見たデータの正解をくり返すだけのモデルは、学習に使ったデータでは満点でも、まだ見ていないデータには役に立つ予測ができないとして、これを過学習の例に挙げています。*3 正解のあるデータで学ぶ教師あり学習の全体像は「教師あり学習と教師なし学習の違い」で扱っています。
過学習が起きる仕組み
過学習が起きるかどうかを左右するのが、モデルの容量です。教科書は容量を、さまざまな関数に当てはまる能力と説明し、容量の小さいモデルは学習用データに合わせきれず、容量の大きいモデルは学習用データにしかない性質まで覚え込んで過学習しうるとしています。*1
容量を上げていくと、学習用データの誤差は下がり続けます。一方で汎化誤差は、はじめは一緒に下がるものの、ある所から学習用データの誤差との差が開いて上がり始めます。汎化誤差は容量に対してU字の曲線を描き、上の図はその関係を模式的に描いたものです。
データの量も影響します。統計的学習理論の主要な結果として、学習用データでの誤差と汎化誤差の差の上限は、容量が大きいほど大きく、学習用データの件数が増えるほど小さくなることが知られています。*1 同じモデルでも、データが少ない案件ほど過学習に注意が要ります。
深層学習のモデルは容量がとても大きく、2017年のZhangらの研究は、ラベルを無作為に付け替えた画像でも、ニューラルネットワークが学習用データの誤差を0にできると示しました。その場合のテスト用データでの誤差は、当て推量と変わりません。*4
未学習との違い
2つの状態は、学習用と検証用の誤差を並べると見分けられます。
| 観点 | 未学習 | 過学習 |
|---|---|---|
| 学習用データの誤差 | 大きい | 小さい |
| 検証用データの誤差との差 | 小さい | 大きい |
| よくある原因 | モデルが単純すぎる・特徴量が足りない・学習の回数が足りない | モデルが複雑すぎる・データが少ない・学習を続けすぎる |
| 主な打ち手 | モデルの容量を上げる・特徴量を増やす | 正則化・早期終了・データの追加や水増し |
scikit-learnの公式の例は、余弦関数の一部に雑音を加えたデータに、次数1・4・15の多項式を当てはめて比べています。次数1の直線では学習用データにも合わず、これが未学習です。次数4は真の関数をほぼ再現し、それより高い次数では学習用データの雑音まで覚えて過学習するとしています。*5 打ち手が正反対なので、まずどちらの状態かを数字で確かめます。
具体例:k近傍法で見る過学習
Pythonの標準ライブラリだけで動く例で確かめます。正弦曲線に雑音を加えたデータを学習用に60件、検証用に200件作り、ある点の値を「近い順にk件の学習データの平均」で予測するk近傍法で当てはめます。kが小さいほどモデルは複雑になり、k=1なら学習データを丸ごと覚えているのと同じです。
import math, random
random.seed(0)
def make(n): # sin(x) に雑音を足したデータをn件作る
xs = [random.uniform(0, 6) for _ in range(n)]
return [(x, math.sin(x) + random.gauss(0, 0.4)) for x in xs]
train, valid = make(60), make(200) # 学習用60件、検証用200件
def predict(x, k): # xに近い順にk件の学習データを選び、yの平均を返す
near = sorted(train, key=lambda p: abs(p[0] - x))[:k]
return sum(y for _, y in near) / k
def mse(data, k): # 平均二乗誤差
return sum((predict(x, k) - y) ** 2 for x, y in data) / len(data)
for k in (1, 5, 40):
print(f"k={k:2d} 学習用 {mse(train, k):.3f} 検証用 {mse(valid, k):.3f}")
実行すると、k=1は、どの点にとっても最も近い学習データが自分自身なので学習用の誤差が0.000になりますが、検証用は0.308です。k=5は学習用0.124・検証用0.211で、検証用の誤差が3つの中で最小です。k=40は学習用0.348・検証用0.306で、学習用データにすら合っていません。k=1が過学習、k=40が未学習にあたり、学習用の誤差だけを見てk=1を選ぶと、新しいデータで最も外れやすいモデルを本番に出すことになります。
正則化で抑える考え方
教科書は正則化を、学習用データの誤差ではなく汎化誤差を下げることを狙って、学習アルゴリズムに加える変更と定義しています。*2 代表的な手段は次の4つです。
- L2正則化(重み減衰):重みの二乗の和を罰として目的関数に足し、重みを小さく保つ。リッジ回帰とも呼ばれる
- L1正則化:重みの絶対値の和を罰として足す。一部の重みがちょうど0になり、使う特徴量を絞る効果がある
- 早期終了:検証用データの誤差が下がらなくなった時点で学習を止める
- ドロップアウト:学習中に、ニューラルネットワークの一部の素子を無作為に外す
scikit-learnのRidgeでは、罰の強さを0以上の値をとるalphaで決め、大きいほど係数が強く縮みます。Lassoは係数をちょうど0にできます。*6 教科書は早期終了を、深層学習でおそらく最もよく使われる正則化としています。学習の回数を一つのハイパーパラメータ(学習の前に人が決める設定値)と見れば、検証用の誤差はここでもU字を描きます。*2
ドロップアウトを提案した2014年の論文は、各素子を一定の確率pで残し、pは検証用データで選ぶか、単に0.5とすればよく、この値が幅広いネットワークと課題で最適に近いとしています。入力の素子では、最適な残す確率は0.5より1に近いのがふつうです。*7
Kerasでドロップアウトと早期終了を組み合わせた例です。
import keras
model = keras.Sequential([
keras.Input(shape=(20,)),
keras.layers.Dense(64, activation="relu"),
keras.layers.Dropout(0.5), # 学習中だけ、この層への入力の半分ほどを0にする
keras.layers.Dense(1),
])
model.compile(optimizer="adam", loss="mse")
stop = keras.callbacks.EarlyStopping(
monitor="val_loss", patience=5, restore_best_weights=True)
model.fit(x_train, y_train, validation_data=(x_val, y_val),
epochs=200, callbacks=[stop])
patience=5は、検証用の損失が5エポック続けて改善しなければ止める指定です。restore_best_weightsは既定がFalseで、そのままだと止まった時点の重みが残ります。Trueにしておくと、検証用の損失が最もよかったエポックの重みに戻ります。*8
検証データで見抜く
過学習は、学習に使っていないデータで測らない限り見えません。教科書は、テスト用データをハイパーパラメータを含むモデルの選択に一切使ってはならず、検証用データは学習用データの中から切り出すとしています。目安として、学習用データのおよそ80%を学習に、20%を検証に使うのが一般的だとしています。*1
データが少ないと、20%を検証に回す余裕がありません。そこで使うのが交差検証です。k分割交差検証では学習用データをk個に分け、k−1個で学習して残り1個で評価することをk回くり返し、その平均を成績とします。次のコードは、正則化の強さalphaの候補を5分割の交差検証で比べる例です。X、yは手元のデータに置き換えます。
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.linear_model import Ridge
# 最初にテスト用を切り離す。前処理とモデル選びは学習用の中だけで行う
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
model = make_pipeline(PolynomialFeatures(degree=15), StandardScaler(), Ridge())
grid = {"ridge__alpha": [0.001, 0.01, 0.1, 1, 10]} # 正則化の強さの候補
search = GridSearchCV(model, grid, cv=5) # 5分割の交差検証で選ぶ
search.fit(X_train, y_train)
print(search.best_params_)
print(search.score(X_test, y_test)) # テスト用はここで1回だけ使う
前処理とモデルをmake_pipelineでひとまとめにしているのが要点です。こうしておくと、交差検証の各回で標準化の平均や分散も学習用の分割だけから計算され、評価用の分割の情報が混ざりません。
つまずきやすい点
最も多いのが、評価での情報の漏れです。scikit-learnの注意事項の文書は、予測の時点では手に入らない情報をモデルの構築に使うことをデータリーケージと呼び、楽観的すぎる成績が出て本番で成績が落ちる原因になるとしています。対策は、前処理の前に学習用とテスト用に分け、テスト用データにはfitもfit_transformも使わないことです。*9 検証の成績が不自然に高いときは、まず漏れを疑います。
同じデータを見ながら設定を何十回も調整することも、形を変えた過学習です。テスト用データで設定を調整すれば、その知識がモデルに漏れ、評価の数字は汎化性能を表さなくなります。
分け方にも落とし穴があります。時系列のデータを無作為に分けると、未来のデータで学習して過去を当てることになり、成績が甘く出ます。scikit-learnには、時間の順を守って分けるTimeSeriesSplitがあります。KerasのModel.fitのvalidation_splitは、シャッフルの前にデータの末尾から検証用を取ります。*10 顧客や地域の順に並んだデータをそのまま渡すと、検証用が特定の顧客や地域に偏ります。
ドロップアウトの数字の向きも取り違えやすい点です。原論文のpは素子を残す確率ですが、KerasのDropoutに渡すrateは0にする割合で、残った入力は1/(1−rate)倍に拡大されます。*11 論文の「p=0.8」を入力層にそのまま書くと、8割を落とす設定になります。
本番で精度が落ちる原因は、過学習だけではありません。学習時と本番とでデータの傾向が変わるドリフトは、稼働後の監視で見つけます。監視と再学習の進め方は「MLモデルのドリフト監視・再学習」で扱っています。
外部に委託するときに確認しておきたい点
モデルの開発を外部に頼むときは、まずテスト用データを誰が持つかを決めます。発注側が一部のデータを手元に残して納品物の評価に使えば、委託先がテスト用データに合わせ込む余地はなくなります。
次に、学習用と検証用の誤差を並べた推移を出してもらえば、過学習と未学習のどちらに寄っているかを発注側でも判断できます。データの分け方(無作為か、時間順か、顧客単位か)と、その理由も残してもらいます。
三つ目は再現性です。乱数の種、データの版、正則化の強さ、成績を実験ごとに記録しておけば、同じモデルを作り直せます。記録の仕組みは「MLflow入門」で紹介しています。
最後に、稼働後の扱いです。本番の成績をどの指標で監視し、どこまで下がったら再学習するのか、誰が判断するのかを提案の段階で確かめます。
まとめ:過学習で確かめておきたい3つの点
過学習を防ぐうえで、確かめておきたい点は3つに整理できます。第一に、学習用と検証用の誤差を並べて見て、いまのモデルが過学習と未学習のどちらに寄っているかを数字で判断すること。第二に、正則化・早期終了・ドロップアウトの強さは、検証用データの誤差や交差検証で決めること。第三に、テスト用データは最初に切り離して最後に1回だけ使い、前処理も学習用データの中だけで行うことです。この3点を踏まえておけば、「検証では精度が高かったのに、本番では外ればかり」という事態を避けやすくなります。モデルの評価の設計や検証の進め方に迷いがあれば、外部の手を借りるのも一つの選択肢です。
よくある質問
データが何件あれば過学習を防げますか
決まった件数はありません。必要な量は、モデルの複雑さやデータの雑音の多さで変わります。データを段階的に増やしながら学習用と検証用の誤差の差を見て、差が縮まり続けるなら、データを増やす意味があると判断できます。データが少ない案件では、別の大量データで学習済みのモデルを流用する転移学習も選択肢で、考え方は「転移学習とは」で説明しています。
決定木やランダムフォレストでも過学習は起きますか
起きます。決定木は枝分かれを深くするほど学習用データに細かく合わせられるため、木の深さや葉に残すデータの最小件数を制限して複雑さを抑えます。多数の木の予測を平均するランダムフォレストは1本の木よりばらつきを抑えやすいものの、検証用データでの確認は同じく必要です。
生成AIの追加学習でも過学習は起きますか
起きます。大規模言語モデルを自社のデータで追加学習(ファインチューニング)すると、学習に使った文例の言い回しばかり返すようになることがあります。追加学習に使わない評価用の質問と回答を別に用意し、追加学習の前後で比べるのが基本です。追加学習とRAGの使い分けは「LLMファインチューニングとRAGの使い分け」で扱っています。
過学習かどうかは、どの指標で判断すればよいですか
業務の目的に合った指標を1つ決め、同じ指標で学習用と検証用の値を比べます。分類なら適合率や再現率、数値の予測なら平均二乗誤差などです。値そのものより、学習を進めたときや設定を変えたときに2つの差が開くかを見ると判断しやすくなります。
機械学習モデルの評価と精度改善のご相談
元請(プライムベンダー)として、機械学習モデルの検証の設計から業務システムへの組み込み、保守・運用までご提案します。
Remoguとリラシクなら、機械学習モデルの開発や評価に加わるITエンジニアも探せます。
Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。
出典
- *1 参考:Ian Goodfellow, Yoshua Bengio, Aaron Courville『Deep Learning』第5章 Machine Learning Basics(MIT Press、著者公開版)(https://www.deeplearningbook.org/contents/ml.html)。出典:第5.2節(未学習と過学習の定義・容量・汎化誤差・図5.3の容量と誤差の関係・統計的学習理論の上限・最良の正則化は無いこと)、第5.3節(検証用データの切り出しとおよそ80%と20%の配分)を参照(2026年10月確認)
- *2 参考:Ian Goodfellow, Yoshua Bengio, Aaron Courville『Deep Learning』第7章 Regularization for Deep Learning(MIT Press、著者公開版)(https://www.deeplearningbook.org/contents/regularization.html)。出典:冒頭の正則化の定義、第7.1節(L2正則化・L1正則化)、第7.4節(データの水増し)、第7.8節(早期終了)を参照(2026年10月確認)
- *3 参考:scikit-learn User Guide「3.1. Cross-validation: evaluating estimator performance」(https://scikit-learn.org/stable/modules/cross_validation.html)。出典:過学習の説明、テスト用データでの調整による漏れ、k分割交差検証、パイプラインとの組み合わせ、TimeSeriesSplitを参照(2026年10月確認)
- *4 参考:Chiyuan Zhang ほか「Understanding deep learning requires rethinking generalization」(arXiv:1611.03530、ICLR 2017)(https://arxiv.org/abs/1611.03530)。出典:第1章のうち、無作為に付け替えたラベルでも学習用データの誤差が0になるという実験結果を参照(2026年10月確認)
- *5 参考:scikit-learn Examples「Underfitting vs. Overfitting」(https://scikit-learn.org/stable/auto_examples/model_selection/plot_underfitting_overfitting.html)。出典:余弦関数に次数1・4・15の多項式を当てはめる例と、その説明を参照(2026年10月確認)
- *6 参考:scikit-learn User Guide「1.1. Linear Models」(https://scikit-learn.org/stable/modules/linear_model.html)。出典:第1.1.2節(Ridgeとalpha)、第1.1.3節(Lasso)を参照(2026年10月確認)
- *7 参考:Nitish Srivastava ほか「Dropout: A Simple Way to Prevent Neural Networks from Overfitting」(Journal of Machine Learning Research 15、2014年)(https://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf)。出典:概要と第1章のうち、素子を無作為に外す考え方、残す確率pの選び方(0.5・入力では1に近い値)を参照(2026年10月確認)
- *8 参考:Keras 3 API documentation「EarlyStopping」(https://keras.io/api/callbacks/early_stopping/)。出典:monitor・patience・restore_best_weights(既定はFalse)の説明を参照(2026年10月確認)
- *9 参考:scikit-learn User Guide「12. Common pitfalls and recommended practices」(https://scikit-learn.org/stable/common_pitfalls.html)。出典:第12.2節(データリーケージの定義と避け方)を参照(2026年10月確認)
- *10 参考:Keras 3 API documentation「Model training APIs」(https://keras.io/api/models/model_training_apis/)。出典:Model.fitのvalidation_split(シャッフルの前に末尾のデータを検証用に取る)の説明を参照(2026年10月確認)
- *11 参考:Keras 3 API documentation「Dropout layer」(https://keras.io/api/layers/regularization_layers/dropout/)。出典:rate(0にする割合)と、残った入力を1/(1−rate)倍にする説明を参照(2026年10月確認)