機械学習ワークフロー
田中VPoE:「機械学習は『モデルを学習させる』だけじゃない。データの準備から評価まで、一連のワークフローがある。特に重要なのがデータの分割だ。ここを間違えると、見かけ上は良い精度が出ているのに、実際にはまったく使えないモデルができてしまう。」
あなた:「データの分割って、そんなに重要なんですか?」
田中VPoE:「カンニングしながらテストを受けたら高得点が出るだろう?でも、それは本当の実力じゃない。機械学習も同じだ。」
機械学習ワークフローの全体像
1. 問題定義 → 2. データ収集 → 3. データ前処理
→ 4. 特徴量エンジニアリング → 5. データ分割
→ 6. モデル学習 → 7. モデル評価 → 8. 改善・再学習
各ステップは反復的に繰り返されます。一度で完璧なモデルができることはほとんどありません。
データ分割の基本
なぜデータを分割するのか
モデルの「本当の実力」を測るためです。学習に使ったデータで評価すると、モデルがそのデータを「暗記」しているだけなのか、本当にパターンを学習しているのかが分かりません。
3つのデータセット
from sklearn.model_selection import train_test_split
# まずテストデータを分離(最終評価用)
X_temp, X_test, y_temp, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 残りを学習データと検証データに分割
X_train, X_val, y_train, y_val = train_test_split(
X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp
)
# 結果: 学習60% / 検証20% / テスト20%
print(f"学習: {len(X_train)}, 検証: {len(X_val)}, テスト: {len(X_test)}")
| データセット | 割合 | 用途 |
|---|---|---|
| 学習データ(Train) | 60% | モデルの学習に使用 |
| 検証データ(Validation) | 20% | ハイパーパラメータ調整・モデル選択 |
| テストデータ(Test) | 20% | 最終的な性能評価(1回だけ使用) |
stratify パラメータの重要性
離反予測のように、クラスの偏りがあるデータでは stratify を指定します。
# 離反率が10%の場合
# stratify=y を指定すると、各分割でも離反率10%が維持される
# 指定しないと、偏った分割になる可能性がある
print(f"全体の離反率: {y.mean():.3f}")
print(f"学習データの離反率: {y_train.mean():.3f}")
print(f"テストデータの離反率: {y_test.mean():.3f}")
過学習(Overfitting)と未学習(Underfitting)
過学習とは
モデルが学習データに過度に適合し、新しいデータに対する予測精度が低下する現象です。
学習データの精度: 99% → 高すぎる
テストデータの精度: 65% → 大幅に低い
→ 過学習の兆候
未学習とは
モデルが十分にデータのパターンを捉えられていない状態です。
学習データの精度: 60% → 低い
テストデータの精度: 58% → やはり低い
→ 未学習の兆候
適切な状態
学習データの精度: 85%
テストデータの精度: 82% → 学習データとの差が小さい
→ 良好な汎化性能
過学習の原因と対策
| 原因 | 対策 |
|---|---|
| モデルが複雑すぎる | シンプルなモデルを使う、正則化 |
| 学習データが少ない | データの追加、データ拡張 |
| 特徴量が多すぎる | 特徴量選択、次元削減 |
| 学習回数が多すぎる | Early Stopping |
# 過学習の検出例
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
train_acc = accuracy_score(y_train, model.predict(X_train))
val_acc = accuracy_score(y_val, model.predict(X_val))
print(f"学習データ精度: {train_acc:.3f}")
print(f"検証データ精度: {val_acc:.3f}")
print(f"差分: {train_acc - val_acc:.3f}")
if train_acc - val_acc > 0.1:
print("過学習の可能性があります")
学習曲線で過学習を可視化する
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
import numpy as np
train_sizes, train_scores, val_scores = learning_curve(
model, X_train, y_train,
train_sizes=np.linspace(0.1, 1.0, 10),
cv=5, scoring='f1'
)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_scores.mean(axis=1), label='学習データ')
plt.plot(train_sizes, val_scores.mean(axis=1), label='検証データ')
plt.xlabel('学習データサイズ')
plt.ylabel('F1スコア')
plt.title('学習曲線')
plt.legend()
plt.grid(True)
plt.show()
学習曲線の読み方:
- 2つの曲線が離れている → 過学習
- 2つの曲線が近いが低い → 未学習
- 2つの曲線が近くて高い → 良好
まとめ
- ML ワークフローはデータ準備から評価まで反復的に進む
- データは学習・検証・テストの3つに分割する
- テストデータは最終評価にのみ使い、何度も評価に使わない
- 過学習は学習データへの過度な適合で、汎化性能が低下する現象
- 学習曲線を使って過学習・未学習を可視化できる
チェックリスト
- データ分割の3つのデータセットの役割を説明できる
- stratify の目的を理解した
- 過学習と未学習の違いを説明できる
- 学習曲線の読み方を把握した
次のステップへ
次のレッスンでは、モデルの評価指標について詳しく学びます。正解率だけでは不十分な理由と、ビジネス目的に応じた指標の選び方を理解しましょう。
推定読了時間: 30分