本文へスキップ
ひもとくAI

訓練データとテストデータ

レッスン 4/6

「過去問の丸暗記」問題

モデルを作ったら、それが本当に役に立つかを確かめる必要があります。では、学習に使ったデータで予測させて、正解率を測ればよいでしょうか。

これは、学校のテストに例えると分かりやすくなります。ある生徒が、過去問の答えを丸暗記したとします。本番のテストが過去問とまったく同じ問題なら、この生徒は100点を取れます。しかし、それで「この生徒は内容を理解している」と言えるでしょうか。問題が少し変わっただけで、まったく解けないかもしれません。

モデルも同じです。学習に使ったデータで評価すると、モデルが「理解」しているのか「丸暗記」しているのかを区別できません。 前のレッスンで見たように、深い決定木は学習データをほぼ完璧に覚え込めるので、この方法では正解率がほぼ100%になってしまいます。

本当に知りたいのは、まだ見たことのない新しいデータに対して、どれくらい正しく予測できるか です。実際にモデルを使う場面では、予測の対象は必ず「学習のときには無かったデータ」だからです。

そこで、手元のデータを最初に2つに分けます。

  • 訓練データ: モデルの学習(fit)に使うデータ
  • テストデータ: 学習には一切使わず、最後の評価だけに使うデータ

テストデータは、いわば「モデルがまだ見たことのない本番のテスト」の役割を果たします。

train_test_splitでデータを分ける

scikit-learnでは、train_test_splitという関数でデータを訓練用とテスト用に分けられます。

from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0
)

model = DecisionTreeClassifier(max_depth=3, random_state=0)
model.fit(X_train, y_train)          # 学習には訓練データだけを使う

model.score(X_test, y_test)          # テストデータで正解率を測る

1つずつ見ていきましょう。

  • test_size=0.25: 全体の25%をテストデータにする、という意味です。100件なら、75件が訓練データ、25件がテストデータになります
  • 分割はランダムに行われます。random_state=0のように数値を指定すると、何度実行しても同じ分け方になります。結果を他の人が再現できるように、実務でも指定しておくのが一般的です
  • 戻り値は X_train, X_test, y_train, y_test の順で4つ返ってきます。順番を間違えやすいので注意しましょう
  • 分類モデルのscoreは、正解率(予測が当たった割合)を返します

大事なのは、fitには必ず訓練データを、評価には必ずテストデータを渡す という役割分担を守ることです。

データリーク:テストの答えが漏れていないか

データを分けても、気づかないうちにテストデータの情報が学習に紛れ込んでしまうことがあります。これを データリーク(情報漏洩) と呼びます。リークが起こると、テストの正解率は高く出るのに、実際に使うと全然当たらないモデルが出来上がってしまいます。

よくある例を3つ挙げます。

  1. 分割する前に、データ全体を使って前処理をしてしまう 例えば、欠損値を「全データの平均値」で埋めてから分割すると、その平均値にはテストデータの情報が含まれています。前処理に使う値は、訓練データだけから計算するのが原則です
  2. 同じ人・同じものが、訓練とテストの両方に入ってしまう 1人の患者から何枚も撮った画像を、ランダムに分けると、同じ患者の画像が両方に入ります。モデルは「その人の特徴」を覚えるだけで高得点を取れてしまいます
  3. テストデータの結果を見ながら、何度もモデルを調整してしまう テストデータで正解率を見てはmax_depthを変えて…と繰り返すと、テストデータに合わせた「過去問対策」になってしまいます。調整用には、訓練データの中からさらに「検証データ」を分けて使います

振り返り

  • 学習に使ったデータで評価しても、本当の実力は分からない
  • データは訓練データとテストデータに分け、テストデータは最後の評価だけに使う
  • テストデータの情報が学習に紛れ込む「データリーク」に注意する

演習

演習を読み込んでいます…