体系 › 動画で学ぶ AIのしくみ(シリーズ)
·無料·15分で読めます

覚えるのと分かるのはどう違うのか — 訓練・検証・テストで過学習を見抜く【ゼロから学ぶAI 第2回】

訓練データでは満点の曲線と、少し外す直線。どちらが良いかは、学習に見せていないデータで測るまで分かりません。前回の5人に、見せていない5人(検証)と最後まで封をしておく5人(テスト)を足して、過学習の曲線、3つに分ける理由、くねくねに罰金をかける正則化までを、すべて手で検算できる数字で追います。動画版つき。

要点

  • 学習に使ったデータ(訓練データ)での損失だけでは、新しいデータでどれだけ当たるかは分からない。学習に見せていないデータで測る。
  • この記事の例では、訓練で損失0の4次曲線が、見せていない5人では損失5.13。訓練で0.8の直線は0.2だった。
  • 多項式の次数を0から4へ上げると、訓練の損失は8.8→0.8→0.57→0.07→0と下がり続けるが、検証の損失は8.8→0.2→0.80→1.23→5.13と、次数1を底に上がる。
  • 検証データはモデル選びに使った時点で『見た』データになる。最後の成績は、一度だけ開けるテストデータで測る(この例では直線のテスト損失0.4)。
  • 正則化は、損失に『係数の2乗和×λ』の罰を足して、くねくねした曲線を選びにくくする。この例では λ=0.01 で4次曲線の検証損失が5.13から0.52に下がった。

出典: Deep Learning, Chapter 5: Machine Learning Basics · Deep Learning, Chapter 7: Regularization for Deep Learning · Cross-validation: evaluating estimator performance · sklearn.model_selection.train_test_split ほか2件(末尾)

対象textタスクbasics

このシリーズについて — 「ゼロから学ぶ AIと技術のしくみ」は、第1回から順に読めば(見れば)積み上がるように作った解説シリーズです。各回に同じ内容の動画版があります。この第2回は第1回(AIは何を「学習」しているのか)の続きです。損失(平均二乗誤差)が分かっていれば読めます。

前回の宿題: 損失0の曲線は良いモデルか

前回は、5人の生徒の勉強時間 xx と小テストの点数 yy(説明用の架空のデータ)に、2つのルールを当てはめました。

勉強時間 xx(時間) 1 2 3 4 5
点数 yy(点) 2 5 5 7 11

数字だけ見れば曲線の勝ちです。でも曲線は、0時間勉強した人を −14点、7時間勉強した人を 0点と予想しました。どうも怪しい。では、「怪しい」を数字で言うにはどうすればよいか。それが今回のテーマです。

過去問を丸暗記した生徒

試験勉強にたとえます。過去問を5回分もらった生徒が2人いるとします。

過去問の点数だけを見れば、Aさんのほうが上です。でも本番の試験は、過去問と違う問題が出ます。本当に知りたいのは本番の点数で、それはまだ見ていない問題を解かせてみるまで分かりません。

機械学習でも同じです。学習に使ったデータを訓練データと呼びます。訓練データでの損失は「過去問の点数」にあたります。知りたいのは、まだ見ていないデータでの損失、つまり本番の点数のほうです。

見せていないデータで測る: 検証データ

そこで、新たに5人分のデータを用意し、学習には一切使わずに取っておきます。これを検証データと呼びます(こちらも架空のデータです)。

勉強時間 xx(時間) 0.5 1.5 2.5 3.5 4.5
点数 yy(点) 1 3 6 7 9

前回の5人で作った2つのルールに、この5人の点数を予想させます。

直線 y^=2x\hat{y}=2x の予想は 1, 3, 5, 7, 9 点。正解との差は 0, 0, 1, 0, 0 です。差の2乗の平均は

L検証=02+02+12+02+025=15=0.2L_{\text{検証}} = \frac{0^2+0^2+1^2+0^2+0^2}{5} = \frac{1}{5} = 0.2

4次曲線の予想は次のとおりです。

勉強時間 xx 0.5 1.5 2.5 3.5 4.5
正解 yy 1 3 6 7 9
曲線の予想 y^\hat{y} −3.55 4.38 4.95 5.63 8.95

いちばん大きく外したのは0.5時間の人で、正解1点に対して −3.55点。この1人だけで差の2乗は約20.7です。5人の平均を取ると、曲線の検証損失は 5.13 になります。

訓練の損失(前回の5人) 検証の損失(見せていない5人)
直線 0.8 0.2
4次曲線 0 5.13

訓練では曲線が勝ち、検証では直線が圧勝しました。曲線は前回の5人の点数を丸暗記していただけで、勉強時間と点数の関係をつかんでいなかったのです。このように、訓練データにだけ合いすぎて、見ていないデータで外すことを過学習と呼びます。

直線の検証損失(0.2)が訓練損失(0.8)より小さいのは、たまたまです。5人ずつしかいないと、どの5人が入ったかという運で数字が大きく動きます。「検証は訓練より必ず悪くなる」わけではありません。大事なのは、学習に見せていないデータで測ることです。

過学習の曲線: 次数を上げると何が起きるか

直線と4次曲線の間にも、ルールの候補はあります。多項式の次数を0から4まで変えて、それぞれ前回の5人(訓練データ)でいちばん損失が小さくなるように当てはめ、訓練と検証の損失を並べます。

次数 0 1 2 3 4
訓練の損失 8.8 0.8 0.57 0.07 0
検証の損失 8.8 0.2 0.80 1.23 5.13

2本の線にすると、形がはっきりします。

左側(次数0)は、ルールが単純すぎて、手元のデータにすら合っていない状態です。これを学習不足(アンダーフィッティング)と呼びます。右側(次数3・4)は、訓練の損失はほぼ0なのに検証の損失が上がっていく状態で、これが過学習です。訓練と検証の差が開いていくことが、過学習のいちばん分かりやすいサインです。

この例でいちばん検証損失が小さいのは次数1、つまり直線です。私たちはこの表を見て、直線を選びます。

FIG 1次数を動かして、同じ形を自分で確かめる(この図は5人の例とは別の、点の多い架空データ。黒い点が訓練、金の丸が学習に見せていない点で、図中の「テスト」はこの記事の検証データの役)。次数を上げると訓練の誤差は下がり続け、見せていない点の誤差はある所から跳ね上がる

なぜ3つに分けるのか: テストデータ

ここで一つ、落とし穴があります。私たちは5つの候補の中から、検証の損失がいちばん小さいものを選びました。つまり検証データは、もう「選ぶために見た」データです。

たとえるなら、模試の結果を見ながら勉強法を5通り試し、いちばん模試の点が良かった方法を選んだ状態です。選んだ方法の模試の点は、その模試にたまたま合っていた分だけ、良く見えている可能性があります。候補が多いほど、運良く低い数字が出た候補を拾いやすくなります。

そこで、データを3つに分けます。

呼び名 何に使うか たとえ
訓練データ パラメータ(つまみ)の値を決める 過去問で練習する
検証データ 候補(次数など)を比べて選ぶ 模試で勉強法を選ぶ
テストデータ 最後に一度だけ、成績を測る 本番の試験

テストデータは、選び終わるまで封をしておき、最後に一度だけ開けます。このシリーズの例では、さらに5人分をテスト用に取っておきました(架空のデータ)。

勉強時間 xx(時間) 1 2 3 4 5
点数 yy(点) 3 4 6 8 9

選んだ直線 y^=2x\hat{y}=2x の予想は 2, 4, 6, 8, 10 点。差は 1, 0, 0, 0, −1 で、テスト損失は

Lテスト=12+02+02+02+(−1)25=25=0.4L_{\text{テスト}} = \frac{1^2+0^2+0^2+0^2+(-1)^2}{5} = \frac{2}{5} = 0.4

外に向けて報告するのは、この 0.4 です。検証の0.2ではありません。

テストの結果を見てから、また次数を選び直したらどうなるでしょう。そのときテストデータは「選ぶために見た」データになり、検証データと同じ立場に落ちます。テストは何度も開けない、というのが3つに分ける意味です。

実際の分け方は、ここでの5人ずつよりずっと大きく取ります。scikit-learn の train_test_split は、割合を指定しないとデータの25%をテスト側に回します。件数が少なくて固定の検証データを取る余裕がないときは、訓練データを何通りかに分けて順番に検証役を回す交差検証を使います(検証データの割合は何対何にするのかで、割合と件数のどちらが効くかを実測しています)。

正則化: くねくねに罰金をかける

過学習を防ぐ方法は、単純なモデルを選ぶことだけではありません。曲がれる自由は残したまま、むやみに曲がるのを嫌がらせる方法もあります。これを正則化と呼びます。

4次曲線を、係数を使って書きます。

y^=c0+c1x+c2x2+c3x3+c4x4\hat{y} = c_0 + c_1 x + c_2 x^2 + c_3 x^3 + c_4 x^4

5点を全部通る曲線では、係数は c1≈27.08c_1 \approx 27.08、c2≈−13.79c_2 \approx -13.79、c3≈2.92c_3 \approx 2.92、c4≈−0.21c_4 \approx -0.21 でした。大きな係数どうしが打ち消し合って、無理やり5点を通っています。そこで、損失に係数の大きさの罰を足します。

L合計=1N∑i=1N(yi−y^i)2⏟前回の損失  +  λ∑j=14cj2L_{\text{合計}} = \underbrace{\frac{1}{N}\sum_{i=1}^{N}(y_i-\hat{y}_i)^2}_{\text{前回の損失}} \;+\; \lambda \sum_{j=1}^{4} c_j^2

学習は、この合計がいちばん小さくなる係数を探します。データにぴったり合わせようとして係数が大きくなると、罰が増えます。結果として、少しデータから外れても、なだらかな曲線が選ばれやすくなります。この形の罰を使った回帰をリッジ回帰と呼びます。

λ\lambda を変えて、前回の5人で4次曲線を当てはめ直した結果です。

λ\lambda 0 0.001 0.01 0.1 1
係数の2乗和 ∑cj2\sum c_j^2 932 24.7 4.29 1.17 0.04
訓練の損失 0 0.12 0.16 0.28 0.55
検証の損失 5.13 0.65 0.52 0.76 1.39

次数のときと同じ谷の形です。λ\lambda も、検証の損失で選びます。この例では λ=0.01\lambda=0.01 が選ばれます。

ただし、この例では正則化した4次曲線(検証0.52)より、ただの直線(検証0.2)のほうが良い結果でした。データが直線に近い関係でできているからです。正則化は「どんな場合でも勝つ技」ではなく、複雑なモデルを使うときに、過学習を抑えるつまみだと考えてください。深層学習の教科書(Deep Learning 第7章)も、実際の深層学習では、いちばん良いモデルはたいてい「大きなモデルに適切な正則化をかけたもの」だと書いています。

ここで λ\lambda や次数のように、学習の前に人が決める値をハイパーパラメータと呼びます。前回の学習率もそうです。パラメータ(係数)は訓練データで決め、ハイパーパラメータは検証データで決める。この役割分担を覚えておくと、3つに分ける理由が見えやすくなります。

コードで見る

NumPy の polyfit で、次数0から4までの訓練・検証の損失を出すコードです。

import numpy as np

x_tr = np.array([1, 2, 3, 4, 5]);           y_tr = np.array([2, 5, 5, 7, 11])
x_va = np.array([0.5, 1.5, 2.5, 3.5, 4.5]); y_va = np.array([1, 3, 6, 7, 9])
mse = lambda c, x, y: np.mean((np.polyval(c, x) - y) ** 2)

for deg in range(5):
    c = np.polyfit(x_tr, y_tr, deg)
    print(deg, round(mse(c, x_tr, y_tr), 2), round(mse(c, x_va, y_va), 2))

出力:

0 8.8 8.8
1 0.8 0.2
2 0.57 0.8
3 0.07 1.23
4 0.0 5.13

polyfit は訓練データ(x_tr, y_tr)だけを見て係数を決めます。検証データ(x_va, y_va)は損失を測るときにしか使っていない、という点がポイントです。

現場ではこう使う

データサイエンティストや機械学習エンジニアは、新しい予測課題に取りかかると、まずデータを分けてから手を動かします。分ける前にデータを眺めて前処理を決めたり、全体で特徴量を作ったりすると、検証やテストの情報が学習側に漏れ、数字が良く見えすぎるからです。

実際に触る名前

知らないと事故になる落とし穴

面接・実務で問われる問い

まとめ

次回(第3回): ニューラルネットは何が直線と違うのか — 直線を折り曲げる「活性化」と、層を重ねる意味。

もっと詳しく

🎬 この内容の解説動画(Manim・字幕つき)

出典

  1. Deep Learning, Chapter 5: Machine Learning Basics. deeplearningbook.org資料を開く(取得日 2026-10-28)
  2. Deep Learning, Chapter 7: Regularization for Deep Learning. deeplearningbook.org資料を開く(取得日 2026-10-28)
  3. Cross-validation: evaluating estimator performance. scikit-learn.org資料を開く(取得日 2026-10-28)
  4. sklearn.model_selection.train_test_split. scikit-learn.org資料を開く(取得日 2026-10-28)
  5. sklearn.linear_model.Ridge. scikit-learn.org資料を開く(取得日 2026-10-28)
  6. numpy.polyfit — NumPy Manual. numpy.org資料を開く(取得日 2026-10-28)

本文の定義・数値は、上の一次資料で確かめています。食い違う場合は一次資料が正です。

運営: TechAthletes · 編集方針 · 出典の付け方 · 訂正の記録

コメント

コメントにはログインが必要です