猿でもわかるAIプログラミングシリーズ 🐵💻 シャッフルしないとどうなる？データ分割のコツ



## シャッフルしないとどうなる？データ分割のコツと実践

---

## 1. はじめに：精度は高いけど、実はダメなモデル？

機械学習のプロジェクトでよくあるのが、「モデルの精度は高いのに、実運用で全く使えない」というケースです。

原因のひとつとしてよくあるのが、**データの分割ミス**です。

* データの偏りをそのままにして学習してしまった
* シャッフルしなかったために未来の情報を学習してしまった
* クラスの分布が学習データとテストデータで極端に違っていた

こうした状況は、現場でよくある「あるある落とし穴」です。今回はその中でも、特に\*\*「シャッフルしないとどうなるか？」\*\*をテーマに、実際のコードとともに解説します。

---

## 2. データ分割って何のためにやるの？

まず前提として、「なぜデータを分ける必要があるのか」を軽く整理しておきましょう。

| データ種別             | 目的                 |
| ----------------- | ------------------ |
| 学習データ（Train）      | モデルを学習するため         |
| 検証データ（Validation） | ハイパーパラメータ調整や過学習の確認 |
| テストデータ（Test）      | 最終評価用、本番を想定した性能測定  |

この分割が適切でなければ、\*\*過学習やリーク（情報漏れ）\*\*が発生し、モデルの信頼性が著しく下がります。

---

## 3. 実践例：シャッフルしないと精度が“高く見える”落とし穴

では実際に、シャッフルあり／なしの違いを見てみましょう。

### 🔧 使用データ：scikit-learnの`load_breast_cancer`

乳がんの診断を目的としたバイナリ分類です。

```python
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report

# データ読み込み
data = load_breast_cancer()
X = data.data
y = data.target
```

### ❌ ① シャッフルなしで分割

```python
# シャッフルしない（時系列っぽい順番のまま）
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=False)

model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

print(classification_report(y_test, y_pred))
```

実行結果（一例）：

```
              precision    recall  f1-score   support
           0       0.00      0.00      0.00        55
           1       0.74      1.00      0.85       116
```

**→ 完全に1クラスに偏っている。0の予測が全くできていない。**

---

### ✅ ② シャッフルありで分割

```python
# シャッフルあり
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True, random_state=42)

model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

print(classification_report(y_test, y_pred))
```

実行結果：

```
              precision    recall  f1-score   support
           0       0.94      0.90      0.92        64
           1       0.95      0.97      0.96       107
```

**→ バランスの取れた高精度なモデルになった。**

---

## 4. 実務でよくある落とし穴と回避法

### 🧱 よくある失敗パターン

| パターン                  | 内容               | 影響                   |
| --------------------- | ---------------- | -------------------- |
| シャッフルしない              | データが時系列順・クラス順のまま | 特定クラスに偏った学習・未来情報のリーク |
| stratifyを使わない         | クラスの比率が偏る        | テストデータが極端な分布になる可能性   |
| データの前処理をtestにも適用してしまう | スケーリングや正規化など     | 情報リークにつながる           |

### ✅ 回避のためのTips

* `shuffle=True` を忘れずに！（デフォルトはTrueでも、時系列データでは意識が必要）
* クラス分類の場合は `stratify=y` を使って分布を保つ
* スケーリングやPCAは、学習データでfit → テストデータにはtransformのみ
* 時系列の場合は、むしろシャッフルしないで**時系列交差検証**を検討

---

## 5. 応用編：時系列データではどうすべき？

時系列データでは「未来の情報で過去を予測」してしまうミスが頻出です。

その場合、次のような方法を検討します。

### ⏱ 時系列クロスバリデーション（TimeSeriesSplit）

```python
from sklearn.model_selection import TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    # 学習・評価処理
```

この方法では、**過去 → 未来**の順序を保ったまま検証できるため、実運用に近い精度が得られます。

---

## 6. まとめ：シャッフルは小さな設定、大きな影響

| 項目        | 内容                               |
| --------- | -------------------------------- |
| ✅ メリット    | 偏りを防ぎ、モデル精度の信頼性を上げる              |
| ⚠️ 注意点    | 時系列データや不均衡データでは工夫が必要             |
| 🔧 実務Tips | `shuffle=True`と`stratify=y`をまず疑え |

---

### 🚀 今後の展望

データ分割は単なる準備ではなく、**モデルの命運を分ける重要なステップ**です。

特にMLOpsが浸透していく中で、前処理・データ設計の重要性は増すばかり。今回の内容を踏まえて、みなさんも「ちゃんとデータ分けてる？」と確認してみてください！