K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

SMOTE

01.8.1

SMOTE

最終更新 2026-03-03 読了時間 3 分
まとめ
SMOTE(Synthetic Minority Over-sampling Technique)は、少数派クラスの各点から k 個の近傍点(既定 k_neighbors=5)を選び、その点と近傍を結ぶ線分上のランダムな位置に新しい点を合成して、少数派を多数派と同じ数まで増やす手法です。同じ点を複製する Random Over-sampling と違い、特徴空間を補間した点を足すので、決定境界が少数派の既存点を丸暗記する過学習を抑えられます。このページでは 95:5 の 2 クラス 2,000 件を imblearn.over_sampling.SMOTE で 1:1 に揃え、RandomForestClassifier の classification_report を SMOTE なし/ありで比べます。カテゴリ特徴量が混ざるデータでは SMOTENC を使います。

直感 #

クレジットカード不正検知では、正常取引が 99%・不正が 1% というデータが典型的です。そのまま学習すると「全部正常」と予測するだけで正解率 99% になり、不正をまったく見つけられないモデルが「高精度」に見えてしまいます。SMOTE は少数派の各点について近い少数派の点を 5 個探し、そのどれかと結んだ線分上の適当な位置に新しい点を置く、という操作を少数派が多数派と同数になるまで繰り返します。少数派の点が密になるので、モデルは少数派の領域を「例外」ではなく「ひとつのクラス」として境界を引けるようになります。

何が起きているか(ステップで見る) #

コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。

見るポイント:新しい点は少数点どうしを結ぶ線分上に作る。コピーではないので境界が少し滑らかになる。6 点しかなかった少数クラス(橙)が、薄い橙の合成点で領域として広がる。

詳細な解説 #

ライブラリとデータ #

SMOTE は scikit-learn 本体には入っておらず、pip install imbalanced-learn で入る imblearn パッケージから読み込みます。

1
2
3
4
5
6
7
8
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier
from imblearn.over_sampling import SMOTE
from collections import Counter

不均衡データの作成 #

次のコードは多数派 95%・少数派 5% の 2,000 件を作り、クラス比を保ったまま訓練 7 割・テスト 3 割に分けます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
X, y = make_classification(
    n_samples=2000, n_features=10, n_informative=5,
    weights=[0.95, 0.05], flip_y=0, random_state=42
)
print("元のクラス分布:", Counter(y))
# Counter({0: 1900, 1: 100})

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)

SMOTE の適用 #

次のコードは訓練データだけに SMOTE をかけます。少数派 70 件が、多数派と同じ 1,330 件まで合成で増えます。

1
2
3
smote = SMOTE(sampling_strategy="auto", k_neighbors=5, random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
print("SMOTE 後:", Counter(y_resampled))

効果の比較 #

次のコードは同じ設定の RandomForestClassifier を、元の訓練データと SMOTE 後の訓練データでそれぞれ学習し、同じテストデータで classification_report を比べます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# SMOTE なし
rf_base = RandomForestClassifier(n_estimators=100, random_state=42)
rf_base.fit(X_train, y_train)
print("=== SMOTE なし ===")
print(classification_report(y_test, rf_base.predict(X_test)))

# SMOTE あり
rf_smote = RandomForestClassifier(n_estimators=100, random_state=42)
rf_smote.fit(X_resampled, y_resampled)
print("=== SMOTE あり ===")
print(classification_report(y_test, rf_smote.predict(X_test)))

SMOTE の派生手法 #

手法特徴使いどころ
SMOTEk近傍の線分上に合成基本手法
Borderline-SMOTE境界付近のサンプルのみ補間決定境界の改善
ADASYN学習困難な領域を重点的に補間密度適応
SMOTENCカテゴリ特徴量に対応混合データ
SMOTE + Tomek Linksオーバーサンプリング + ノイズ除去クリーンな境界

注意点 #

SMOTE は訓練データにのみ適用し、テストデータには使いません。交差検証と組み合わせるときは imblearn.pipeline.Pipeline に SMOTE とモデルを入れると、各 fold の訓練側だけに合成が走り、検証側への漏れを防げます。特徴量が 10 を超えて多くなると、近傍距離がどの点でも似た値になる次元の呪いで、線分上の合成点が少数派の分布から外れやすくなります。RandomForestClassifier(class_weight="balanced") のようにモデル側で少数派の重みを上げる方法もあり、合成点を作りたくない場合の代替になります。