🤖 STEP 5: データの分割とホールドアウト法
なぜデータを分割するのか、その重要性を理解します
📋 このステップで学ぶこと
- なぜデータを分割するのか
- 訓練データ・検証データ・テストデータの役割
- train_test_splitの実装
- ホールドアウト法の実践
- random_stateの重要性
練習問題: 2問
🎯 1. なぜデータを分割するのか?
機械学習では、モデルを作った後に「このモデルはどれくらい良いか?」を評価する必要があります。しかし、評価の方法を間違えると、実際よりも良い結果に見えてしまうことがあります。
🎓 学校のテストに例えると
生徒が問題集を解いて勉強する
→ テストは同じ問題集から出題
→ 生徒は満点を取れる!
でも、これって本当に理解してる?
問題を丸暗記しただけかもしれません。新しい問題が出たら解けない可能性があります。
生徒が問題集を解いて勉強する
→ テストは見たことのない問題から出題
→ 生徒の本当の実力がわかる!
これなら、「本当に理解しているか」がわかります。
🤖 機械学習でも同じ
機械学習のモデルも、訓練に使ったデータで評価してはいけません。なぜなら、モデルが「データを丸暗記しただけ」なのか、「本当にパターンを学習した」のかわからないからです。
「訓練に使っていないデータで評価する」ことで、モデルが「新しいデータに対応できるか」を確認します。
これができないモデルは、実務では役に立ちません。
📊 2. 訓練・検証・テストデータの役割
データは通常、3つに分割します。それぞれに明確な役割があります。
① 訓練データ(Training Data)
モデルが「パターンを学ぶ」ためのデータです。このデータから、モデルは重みやパラメータを決定します。
- 割合:全データの60〜80%
- 使い方:
model.fit(X_train, y_train) - 例え:学校で授業を受ける、問題集を解く
② 検証データ(Validation Data)
モデルのハイパーパラメータを調整したり、どのモデルが良いかを比較したりするデータです。
- 割合:全データの10〜20%
- 使い方:
model.score(X_val, y_val)で精度確認 → 調整 - 例え:模擬試験を受けて、弱点を把握する
③ テストデータ(Test Data)
モデルが完成した後、一度だけ使うデータです。「このモデルは実際にどれくらいの性能か」を測定します。
- 割合:全データの10〜20%
- 使い方:最後に一度だけ
model.score(X_test, y_test) - 例え:本番の入学試験(やり直しはできない)
- 重要:テストデータを見てモデルを調整してはいけない
🍳 料理に例えると
テストデータは「最後の砦」です。
テストデータでの結果を見て、「もう少し改善しよう」とモデルを調整すると、テストデータに「過学習」してしまいます。
テストデータは一度だけ、最後に使うようにしましょう。改善したければ、検証データを使います。
📊 シンプルな場合(2分割)
実務では、検証データを使わずに訓練とテストの2分割で済ませることも多いです。特にデータ量が少ない場合や、モデルの調整をあまり行わない場合です。
💻 3. train_test_splitの実装
Scikit-learnのtrain_test_split関数を使うと、簡単にデータを分割できます。
基本的な使い方
⚙️ 重要なパラメータ
| パラメータ | 説明 |
|---|---|
| test_size |
テストデータの割合を指定 ・0.2 = 20% ・0.3 = 30% 一般的には0.2〜0.3(20〜30%) |
| random_state |
乱数のシード値(再現性のため) ・同じ値にすると、毎回同じ分割になる ・よく42が使われる(意味はない) ・0、1、123、2023なども可 |
| stratify |
層化抽出(分類問題で重要) ・クラスの比率を保ったまま分割 ・stratify=y とすることが多い ・不均衡データで特に重要 |
| shuffle |
分割前にシャッフルするか ・デフォルトはTrue ・時系列データの場合はFalseにする |
⚠️ stratify(層化抽出)の重要性
データが不均衡な場合(例:クラス0が90%、クラス1が10%)、普通に分割すると問題が起きることがあります。
- 分類問題全般(特に不均衡データ)
- クラスの比率を保ちたいとき
- テストデータにすべてのクラスを含めたいとき
回帰問題では通常stratifyは使いません(連続値なので比率という概念がない)。
🔄 4. ホールドアウト法とは?
📌 ホールドアウト法の定義
データを訓練とテストに一度だけ分割して評価する方法です。最もシンプルで、最もよく使われる方法です。
📊 メリット・デメリット
| 項目 | 説明 |
|---|---|
| メリット |
・シンプルでわかりやすい ・計算が速い(一度だけ学習すればOK) ・データ量が多い場合に有効 |
| デメリット |
・運に左右される(分割の仕方で結果が変わる) ・データ量が少ないと、評価が不安定 ・一部のデータしか評価に使えない |
⚠️ ホールドアウト法の問題点
ホールドアウト法の「運に左右される」問題を解決するため、交差検証(Cross-Validation)という方法があります。
データを複数回に分けて、それぞれで評価し、平均を取る方法です。より安定した評価ができます。
STEP 22で詳しく学びます。
🎲 5. random_stateの重要性
🔍 random_stateとは?
random_stateは、乱数のシード値を設定するパラメータです。同じ値にすると、毎回同じ結果が得られます。
再現性(Reproducibility)のためです。
実験や研究では、「同じ条件なら、同じ結果が出る」ことが重要です。random_stateを設定することで、誰がいつ実行しても同じ結果になります。
❌ random_stateなし vs ✅ random_stateあり
❓ random_stateの値は何でもいい?
random_stateの値自体に特別な意味はありません。42がよく使われるのは、「銀河ヒッチハイク・ガイド」という小説で「生命、宇宙、そして万物についての究極の疑問の答え」が42だったことに由来します(つまり、単なるジョーク)。
0、1、123、2023など、何でもOKです。
大切なのは、同じプロジェクト内では同じ値を使うことです。
🔧 6. 実践:シンプルなデータセットで体験
完全なコード例
📊 結果の解釈
① 訓練精度とテスト精度が近い場合(差が5%以内)
→ モデルは適切に学習している(良い状態!)
例:訓練96%、テスト95% ← 上の例はこれ
② 訓練精度 >> テスト精度の場合(訓練99%、テスト60%など)
→ 過学習(Overfitting)が起きている
→ モデルを単純にする、データを増やすなどの対策が必要
③ 訓練精度もテスト精度も低い場合(両方60%など)
→ 過小適合(Underfitting)が起きている
→ モデルが単純すぎる、または特徴量が不足
📝 STEP 5 のまとめ
- データ分割は「カンニング」を防ぐために必要
- データは訓練・検証・テストの3つに分ける(シンプルな場合は2分割)
- train_test_splitで簡単に分割できる
- stratifyを使うと、クラスの比率を保てる(分類問題で重要)
- random_stateで再現性を確保できる
- ホールドアウト法は最もシンプルな評価方法
- テストデータは最後に一度だけ使う
「訓練データで学習、テストデータで評価」
これが機械学習の基本中の基本です。この原則を守らないと、モデルの本当の性能はわかりません。
STEP 6では、いよいよScikit-learnのインストールと基本APIを学びます。
実際にコードを書きながら、機械学習の世界を体験していきましょう!
📝 練習問題
データ分割の目的
次のうち、データを訓練とテストに分割する最も重要な理由はどれですか?
- A. 計算を速くするため
- B. モデルが未知のデータでどれくらい性能を発揮するか確認するため
- C. データ量を減らすため
- D. 複数のモデルを同時に訓練するため
なぜBが正解なのか?
データ分割の最も重要な理由は、「モデルが未知のデータでどれくらい性能を発揮するか確認するため」です。
詳しい理由:
- 訓練に使ったデータで評価すると、「カンニング」状態になる
- モデルがデータを丸暗記しただけでも、高精度に見えてしまう
- テストデータ(未知のデータ)で評価することで、真の性能がわかる
- 実務では「新しいデータに対応できるか」が重要なので、これを確認する
他の選択肢が間違いの理由:
A(計算を速くするため)が間違いの理由:
データ分割自体は計算速度に影響しません。むしろ、訓練データが減る分だけ訓練が速くなることはありますが、それは主目的ではありません。
C(データ量を減らすため)が間違いの理由:
データ量を減らすことが目的ではありません。むしろ、データ量が減ると評価の精度が下がるデメリットがあります。データ分割は「評価の正確性」のために行います。
D(複数のモデルを同時に訓練するため)が間違いの理由:
複数のモデルを訓練することとデータ分割は直接関係ありません。複数のモデルを比較する場合でも、それぞれのモデルで同じ分割を使います。
適切なデータ分割
あなたは1000件のデータで分類モデルを作っています。
データは、クラス0が900件、クラス1が100件と不均衡です。
どのようにデータを分割すべきですか?
- A. train_test_split(X, y, test_size=0.2)
- B. train_test_split(X, y, test_size=0.2, random_state=42)
- C. train_test_split(X, y, test_size=0.2, stratify=y)
- D. train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
なぜDが正解なのか?
不均衡データを分割する場合、random_stateとstratifyの両方を設定するのがベストです。
stratify=y が必要な理由:
- データが不均衡(クラス0:90%、クラス1:10%)
- stratifyなしだと、運が悪いとテストデータにクラス1が1つも含まれない可能性がある
- stratifyを使うと、訓練とテストで同じ比率(90:10)を保てる
- これにより、すべてのクラスに対する評価ができる
random_state=42 が必要な理由:
- 再現性を確保するため
- 実験結果を他の人が再現できる
- デバッグがしやすい(同じ分割で問題を調査できる)
- 42という値に特別な意味はない(何でもOK)
他の選択肢が不十分な理由:
A が不十分な理由:
stratifyもrandom_stateもない → 不均衡データに対応できず、再現性もない。最も問題のある選択肢。
B が不十分な理由:
random_stateはあるが、stratifyがない → 再現性はあるが、テストデータにクラス1が含まれない可能性がある。不均衡データには不十分。
C が不十分な理由:
stratifyはあるが、random_stateがない → クラス比率は保たれるが、再現性がない。実行するたびに異なる分割になる。
実務でのベストプラクティス:
分類問題では、常にrandom_stateとstratify=yの両方を設定しましょう。特に不均衡データでは必須です。
学習メモ
機械学習入門 - Step 5