STEP 18:クラスタリング基礎

🎯 STEP 18: クラスタリング基礎

K-means、階層的クラスタリング、DBSCANを使った教師なし学習

📋 このステップで学ぶこと

  • 教師なし学習とクラスタリングの概念
  • K-means法の仕組みと実装
  • エルボー法とシルエット分析
  • 階層的クラスタリング
  • DBSCAN(密度ベースクラスタリング)
  • クラスタリング手法の使い分け

演習問題: 8問

🎯 1. 教師なし学習とクラスタリング

📊 教師あり学習 vs 教師なし学習

教師あり学習:正解ラベル(y)がある → 予測モデルを作る
教師なし学習:正解ラベルがない → データの構造やパターンを発見する

【教師なし学習の主なタスク】 1. クラスタリング → データを似たもの同士でグループ分け 2. 次元削減 → 高次元データを低次元に圧縮(PCA、t-SNE) 3. 異常検知 → 通常とは異なるデータを検出
🎯 クラスタリングの目的

「似たもの同士を同じグループに、異なるものを別のグループに」

・クラスタ内の類似度:高い(まとまりがある)
・クラスタ間の類似度:低い(はっきり分かれている)

📊 2. K-means法

🔄 K-meansのアルゴリズム

1. 初期化:K個のクラスタ中心(セントロイド)をランダムに配置
2. 割り当て:各データ点を最も近いセントロイドに割り当て
3. 更新:各クラスタの重心を新しいセントロイドとする
4. 繰り返し:2-3を収束するまで繰り返す

# K-meansの基本実装 import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.datasets import make_blobs # サンプルデータの生成(3つのクラスタ) X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42) # K-meansでクラスタリング kmeans = KMeans(n_clusters=3, random_state=42, n_init=10) y_kmeans = kmeans.fit_predict(X) # 結果の確認 print(“クラスタ中心:”) print(kmeans.cluster_centers_) print(f”\nイナーシャ(SSE): {kmeans.inertia_:.2f}”) print(f”各クラスタのサンプル数: {np.bincount(y_kmeans)}”)
クラスタ中心: [[-1.66 4.31] [ 1.98 0.87] [-1.39 2.56]] イナーシャ(SSE): 158.73 各クラスタのサンプル数: [100 100 100]
⚠️ K-meansの注意点
  • Kの数を事前に決める必要がある(エルボー法で決定)
  • 球状のクラスタを仮定(複雑な形状には不向き)
  • 初期値に依存(n_init で複数回実行)
  • 外れ値に敏感(事前に外れ値を除去)

📈 3. 最適なクラスタ数の決定

エルボー法(Elbow Method)

📊 エルボー法の考え方

クラスタ数(K)を増やすと、イナーシャは減少。しかし、ある点を超えると減少が緩やかになります。この「肘」のような折れ曲がりの点が最適なK。

# エルボー法の実装 inertias = [] K_range = range(1, 11) for k in K_range: kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) kmeans.fit(X) inertias.append(kmeans.inertia_) # プロット plt.figure(figsize=(8, 5)) plt.plot(K_range, inertias, ‘bo-‘, linewidth=2, markersize=8) plt.xlabel(‘クラスタ数 (K)’) plt.ylabel(‘イナーシャ(SSE)’) plt.title(‘エルボー法によるクラスタ数の決定’) plt.xticks(K_range) plt.grid(True, alpha=0.3) plt.show()

シルエット分析

# シルエット分析 from sklearn.metrics import silhouette_score silhouette_scores = [] for k in range(2, 11): kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) labels = kmeans.fit_predict(X) score = silhouette_score(X, labels) silhouette_scores.append(score) print(f”K={k}: シルエットスコア={score:.4f}”) best_k = range(2, 11)[np.argmax(silhouette_scores)] print(f”\n最適なクラスタ数: K={best_k}”)
K=2: シルエットスコア=0.5817 K=3: シルエットスコア=0.6526 ← 最高スコア K=4: シルエットスコア=0.5135 … 最適なクラスタ数: K=3
✅ シルエットスコアの解釈

シルエットスコア:-1〜1
・+1に近い:良くクラスタリングされている
・0付近:クラスタの境界にいる
・-1に近い:間違ったクラスタに割り当てられている

🌲 4. 階層的クラスタリング

📊 凝集型階層的クラスタリング

1. 開始:各データ点を1つのクラスタとする
2. 結合:最も近い2つのクラスタを結合
3. 繰り返し:すべてが1つのクラスタになるまで続ける
4. カット:デンドログラムを任意の高さで切ってクラスタ数を決定

# 階層的クラスタリングの実装 from scipy.cluster.hierarchy import dendrogram, linkage from sklearn.cluster import AgglomerativeClustering # リンケージ行列の計算(Ward法) Z = linkage(X, method=’ward’) # デンドログラムの描画 plt.figure(figsize=(12, 5)) dendrogram(Z, truncate_mode=’lastp’, p=30) plt.title(‘階層的クラスタリング(デンドログラム)’) plt.xlabel(‘サンプル’) plt.ylabel(‘距離’) plt.axhline(y=20, color=’r’, linestyle=’–‘, label=’カットライン’) plt.legend() plt.show() # sklearn の AgglomerativeClustering agg = AgglomerativeClustering(n_clusters=3, linkage=’ward’) y_agg = agg.fit_predict(X) print(f”各クラスタのサンプル数: {np.bincount(y_agg)}”)
リンケージ 距離の定義 特徴
Ward法 結合時の分散増加を最小化 球状のクラスタ向き、最も一般的
完全連結法 クラスタ間の最大距離 コンパクトなクラスタを作る
平均連結法 クラスタ間の平均距離 バランスの良い結果

🔍 5. DBSCAN(密度ベースクラスタリング)

📊 DBSCAN

密度が高い領域をクラスタとし、低密度領域はノイズとして扱う手法。

主要パラメータ:
eps:近傍の半径
min_samples:コアポイントになるために必要な最小サンプル数

# DBSCANの実装(月形データ) from sklearn.cluster import DBSCAN from sklearn.datasets import make_moons # 月形データの生成 X_moons, y_moons = make_moons(n_samples=300, noise=0.05, random_state=42) # DBSCAN dbscan = DBSCAN(eps=0.2, min_samples=5) y_dbscan = dbscan.fit_predict(X_moons) # 結果の確認 n_clusters = len(set(y_dbscan)) – (1 if -1 in y_dbscan else 0) n_noise = list(y_dbscan).count(-1) print(f”クラスタ数: {n_clusters}”) print(f”ノイズ点数: {n_noise}”)
クラスタ数: 2 ノイズ点数: 0
✅ DBSCANの利点
  • クラスタ数を事前に指定する必要がない
  • 任意の形状のクラスタを検出できる
  • 外れ値をノイズとして検出できる
⚠️ DBSCANの注意点
  • epsとmin_samplesの調整が難しい
  • 密度が異なるクラスタには対応しにくい

⚖️ 6. クラスタリング手法の比較

手法 長所 短所 適した場面
K-means 高速、大規模データOK Kを事前指定、球状のみ 球状クラスタ、大規模データ
階層的 Kを後から決定可、デンドログラム 計算量が多い 中小規模データ、階層構造の分析
DBSCAN 任意の形状、外れ値検出 パラメータ調整難 非球状クラスタ、外れ値がある場合
💡 手法選択のガイドライン

1. まずK-meansを試す(高速で理解しやすい)
2. 球状でない場合 → DBSCAN
3. 階層構造を見たい場合 → 階層的クラスタリング
4. 外れ値が多い場合 → DBSCAN

📝 練習問題

問題1 やさしい

教師なし学習の特徴

教師なし学習の説明として正しいものを選んでください。

  • A. 正解ラベルを使って予測モデルを作る
  • B. 正解ラベルなしでデータの構造やパターンを発見する
  • C. 報酬を最大化するように学習する
  • D. 時系列データを予測する
正解:B

教師なし学習は、正解ラベルがない状態でデータの構造やパターンを発見する手法です。

問題2 やさしい

K-meansの手順

K-meansアルゴリズムの手順として正しい順序を選んでください。

  • A. 割り当て → 初期化 → 更新 → 繰り返し
  • B. 初期化 → 割り当て → 更新 → 繰り返し
  • C. 更新 → 初期化 → 割り当て → 繰り返し
正解:B

1.初期化 → 2.割り当て → 3.更新 → 4.収束まで繰り返し

問題3 ふつう

エルボー法

エルボー法でクラスタ数を決定する際、何を見て判断しますか?

  • A. イナーシャが最大になるK
  • B. イナーシャの減少が緩やかになる点(エルボー)
  • C. シルエットスコアが最大になるK
正解:B

「肘」のような折れ曲がりの点が最適なKです。

問題4 ふつう

シルエットスコア

シルエットスコアが0.8の場合、どのように解釈できますか?

  • A. クラスタリングの品質が悪い
  • B. クラスタリングの品質が良い
  • C. データ点がクラスタの境界にいる
正解:B

シルエットスコアは-1〜1の範囲で、+1に近いほど良くクラスタリングされています。

問題5 ふつう

DBSCANの特徴

DBSCANの説明として正しいものを選んでください。

  • A. クラスタ数を事前に指定する必要がある
  • B. 球状のクラスタのみに対応する
  • C. 外れ値をノイズとして検出できる
正解:C

DBSCANは外れ値をノイズ(ラベル=-1)として検出できます。クラスタ数の事前指定不要、任意の形状に対応可能です。

問題6 むずかしい

手法の選択

月形やドーナツ型のような非球状のクラスタがあり、外れ値も含まれるデータに最も適した手法は?

  • A. K-means
  • B. 階層的クラスタリング(Ward法)
  • C. DBSCAN
正解:C(DBSCAN)

任意の形状のクラスタを検出でき、外れ値をノイズとして検出できるため。

問題7 むずかしい

K-meansの実装

Irisデータセットでエルボー法とシルエット分析を行い、最適なクラスタ数を決定してください。

from sklearn.datasets import load_iris from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score iris = load_iris() X = iris.data for k in range(2, 6): kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) labels = kmeans.fit_predict(X) score = silhouette_score(X, labels) print(f”K={k}: inertia={kmeans.inertia_:.1f}, silhouette={score:.4f}”) # 結果: K=3 が最適
問題8 むずかしい

DBSCANのパラメータ

make_moons データでeps を0.1, 0.2, 0.3に変えて結果を比較してください。

from sklearn.datasets import make_moons from sklearn.cluster import DBSCAN X, _ = make_moons(n_samples=300, noise=0.05, random_state=42) for eps in [0.1, 0.2, 0.3]: dbscan = DBSCAN(eps=eps, min_samples=5) labels = dbscan.fit_predict(X) n_clusters = len(set(labels)) – (1 if -1 in labels else 0) n_noise = list(labels).count(-1) print(f”eps={eps}: clusters={n_clusters}, noise={n_noise}”)

eps=0.2が最適(2クラスタ、ノイズ0)

📝 STEP 18 のまとめ

✅ このステップで学んだこと
  • 教師なし学習:正解ラベルなしでパターンを発見
  • K-means:最も基本的なクラスタリング、球状クラスタ向き
  • エルボー法:イナーシャの減少が緩やかになる点でKを決定
  • シルエット分析:クラスタリングの品質を評価(-1〜1)
  • 階層的クラスタリング:デンドログラムで階層構造を可視化
  • DBSCAN:密度ベース、任意の形状、外れ値検出可能
🚀 次のステップへ

次のSTEP 19では、次元削減を学びます。PCA(主成分分析)とt-SNEを使って、高次元データを可視化・圧縮する方法を習得しましょう!

❓ よくある質問

Q1. K-meansの結果が毎回違うのはなぜ?
初期のセントロイド配置がランダムなためです。random_stateを固定するか、n_initで複数回実行して最良の結果を選びましょう。
Q2. クラスタリング前にスケーリングは必要?
はい、推奨されます。K-meansやDBSCANは距離ベースのため、スケールが大きい特徴量に引っ張られます。StandardScalerで標準化してから使用しましょう。
Q3. DBSCANのepsをどう決める?
k-距離グラフを使う方法があります。各点について最近傍k点までの距離をプロットし、急激に増加する点をepsとして選びます。
Q4. 大規模データにK-meansを使うには?
MiniBatchKMeansを使用します。データの一部で更新を行うため、大規模データでも高速に動作します。
Q5. クラスタリングの結果をどう評価する?
内部評価指標:シルエットスコア、Calinski-Harabaszスコア、Davies-Bouldinスコア
正解ラベルがある場合:調整ランド指数(ARI)、正規化相互情報量(NMI)
📝

学習メモ

機械学習入門 - Step 18

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE