クラスタ数を自動で決める!Scikit-learn AffinityPropagationの基本と実践

Python

データ分析で顧客をグループ分けしたり、画像を分類したりする際に「クラスタリング」は非常に強力な手法です。しかし、多くの手法、例えば有名なK-Means法では、「いくつのグループに分けるか(クラスタ数K)」を分析者が事前に決めなければなりません。

「最適なクラスタ数なんて、やってみないとわからない…」

そんな悩みを解決してくれるのが、今回ご紹介するAffinity Propagationです。このアルゴリズムは、データ自身が持つ類似性に基づいて、最適なクラスタ数を自動で推定してくれます。

この記事では、Pythonのscikit-learnライブラリを使い、Affinity Propagationの基本的な考え方から、実際に動かすためのサンプルコード、そして結果の可視化までを分かりやすく解説します。

Affinity Propagationがクラスタ数を自動で決める仕組み

なぜAffinity Propagationはクラスタ数を事前に決める必要がないのでしょうか。その秘密は、データポイント同士が交わす「メッセージ」にあります。

全データ点が「中心候補」から始まる

Affinity Propagationは、まず全てのデータポイントがクラスタの中心(論文ではExemplarと呼ばれます)になる可能性があると考えます。ここがK-Means法との大きな違いです。

メッセージを交換して「代表」を決める

次に、各データポイントは他のデータポイントに対して、2種類のメッセージを繰り返し交換します。

  1. Responsibility(責任): ある点が、別の点をどれくらい自身の「代表」としてふさわしいと考えているかを示すメッセージ。
  2. Availability(利用可能性): ある点が、別の点を自身の「代表」として選ぶことがどれくらい適切かを示すメッセージ。

このメッセージのやり取りを繰り返すことで、各データポイントにとって最もふさわしい代表が徐々に浮かび上がってきます。最終的に、自身が代表だと結論付けたデータポイントがクラスタの中心となり、その他のデータポイントは最も近い代表のクラスタに所属します。

この仕組みにより、データ構造に基づいて自然とクラスタの数と構成が決まるのです。

Scikit-learnでAffinity Propagationを動かしてみよう

それでは、理屈はここまでにして、実際にscikit-learnでAffinity Propagationを使ってみましょう。全体の流れは非常にシンプルです。

Step 1: ライブラリの準備とインストール

まずは、必要なライブラリをインストールします。scikit-learnの他に、データ操作のためのnumpy、可視化のためのmatplotlibを使います。

pip install scikit-learn numpy matplotlib

Step 2: サンプルデータの生成

クラスタリング対象のデータとして、scikit-learnが提供するmake_blobs関数で2次元のサンプルデータを生成します。ここでは、比較のために5つの塊を持つデータを作成します。

from sklearn.datasets import make_blobs

# 5つの中心を持つ300個のサンプルデータを生成
X, y_true = make_blobs(n_samples=300, centers=5, cluster_std=0.9, random_state=42)

# Xにデータ点の座標が格納される
print("データ形式:", X.shape)
print("正解のクラスタラベル(比較用):", y_true[:10])

Step 3: モデルの学習とクラスタリング実行

AffinityPropagationをインポートし、データに適用します。fit_predictメソッドを使えば、学習とクラスタ割り当てを一度に実行できます。

from sklearn.cluster import AffinityPropagation

# AffinityPropagationモデルをデフォルト設定で作成
model = AffinityPropagation(random_state=0)

# モデルにデータを適用し、クラスタラベルを取得
clusters = model.fit_predict(X)

# 推定されたクラスタの中心と数を取得
cluster_centers_indices = model.cluster_centers_indices_
n_clusters = len(cluster_centers_indices)

print(f"推定されたクラスタ数: {n_clusters}")
print("各データのクラスタラベル:", clusters[:10])

実行結果を見ると、centers=5で生成したデータに対し、アルゴリズムが自動でクラスタ数を推定していることがわかります。デフォルト設定では、必ずしも5になるとは限りません。

推定クラスタ数を調整する重要パラメータ

Affinity Propagationはクラスタ数を自動で決めますが、その挙動をコントロールすることも可能です。特に重要なのがpreferenceパラメータです。

preference:クラスタ中心へのなりやすさを制御

preferenceは、各データポイントがどれだけクラスタ中心(Exemplar)になりやすいかを示す値です。この値を調整することで、生成されるクラスタ数を間接的にコントロールできます。

  • 値を大きくする: 各点が「自分が中心だ!」と主張しやすくなるため、クラスタ数は増加します。
  • 値を小さくする(負の値など): 各点が控えめになり、代表に選ばれにくくなるため、クラスタ数は減少します。

preferenceを指定しない場合は、入力データの類似度の中央値が自動で設定されます。意図的にクラスタ数を調整したい場合は、この値を明示的に設定します。

# preferenceを-50に設定して、クラスタ数を減らしてみる
model_pref = AffinityPropagation(preference=-50, random_state=0)
clusters_pref = model_pref.fit_predict(X)

n_clusters_pref = len(model_pref.cluster_centers_indices_)
print(f"preference=-50 の場合の推定クラスタ数: {n_clusters_pref}")

このコードを実行すると、先ほどよりもクラスタ数が少なくなっているはずです。このようにpreferenceを調整することで、分析の目的に応じた粒度でクラスタリングを行うことができます。

実践:クラスタリング結果を可視化する

最後に、クラスタリング結果をmatplotlibで可視化し、どのようにデータがグループ分けされたかを視覚的に確認しましょう。

サンプルコード全体

データの生成から学習、プロットまでをまとめたコードは以下のようになります。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import AffinityPropagation

# 1. データの準備
X, _ = make_blobs(n_samples=300, centers=5, cluster_std=0.9, random_state=42)

# 2. AffinityPropagationの実行 (preferenceを調整)
model = AffinityPropagation(preference=-50, random_state=0)
clusters = model.fit_predict(X)
cluster_centers_indices = model.cluster_centers_indices_
cluster_centers = X[cluster_centers_indices]
n_clusters = len(cluster_centers_indices)

# 3. 結果の可視化
plt.figure(figsize=(10, 8))

# ユニークなクラスタラベルごとに色を決定
colors = plt.cm.viridis(np.linspace(0, 1, n_clusters))

for k in range(n_clusters):
    # k番目のクラスタに属するデータ点のインデックスを取得
    class_members = clusters == k
    
    # クラスタの中心を取得
    center = cluster_centers[k]
    
    # データ点をプロット
    plt.plot(X[class_members, 0], X[class_members, 1], 'o', markerfacecolor=colors[k], markeredgecolor='k', markersize=8)
    
    # クラスタの中心をプロット
    plt.plot(center[0], center[1], 'o', markerfacecolor=colors[k], markeredgecolor='black', markersize=14)

plt.title(f'Affinity Propagation: Estimated {n_clusters} clusters')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.grid(True)
plt.show()

このコードを実行すると、各クラスタが異なる色でプロットされ、その中心点が大きな点で示されたグラフが表示されます。これにより、アルゴリズムがどのようにデータを解釈し、グループ分けしたのかを一目で理解することができます。

まとめ

今回は、クラスタ数を自動で決定するAffinity Propagationについて、その仕組みからscikit-learnでの実践的な使い方までを解説しました。

  • Affinity Propagationの強み: K-Meansと異なり、クラスタ数を事前に指定する必要がない。
  • 仕組み: データポイント間のメッセージ交換により、データ構造に基づいて代表点(Exemplar)を決定する。
  • 実践: scikit-learnを使えば簡単に実装可能。preferenceパラメータで推定クラスタ数を調整できる。

「最適なクラスタ数が分からない」という場面に遭遇したら、ぜひこのAffinity Propagationを試してみてください。データの隠れた構造を発見するための、強力な武器となるはずです。

コメント

タイトルとURLをコピーしました