はじめに
この実験では、k-means クラスタリングアルゴリズムとその仮定を検討します。異なる分布を持つデータを生成し、k-means がこのデータをどのようにクラスタに分割するかを視覚化します。また、アルゴリズムのいくつかの制限とそれらを克服するための可能な解決策についても議論します。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。
時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。
学習中に問題に遭遇した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。
データ生成
scikit-learn のmake_blobs関数を使って、異なる分布を持つさまざまなデータセットを生成します。次のコードブロックでは、4 つのデータセットを生成します。
- ガウスブロブの混合
- 異方的に分布するブロブ
- 分散が異なるブロブ
- サイズが不均一なブロブ
import numpy as np
from sklearn.datasets import make_blobs
n_samples = 1500
random_state = 170
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X, y = make_blobs(n_samples=n_samples, random_state=random_state)
X_aniso = np.dot(X, transformation) ## 異方的なブロブ
X_varied, y_varied = make_blobs(
n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
) ## 分散が異なる
X_filtered = np.vstack(
(X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])
) ## サイズが不均一なブロブ
y_filtered = [0] * 500 + [1] * 100 + [2] * 10
データの可視化
生成したデータセットを可視化するために Matplotlib を使います。次のコードブロックでは、各データセットの真のクラスタを示す 2x2 のプロットを作成します。
import matplotlib.pyplot as plt
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12))
axs[0, 0].scatter(X[:, 0], X[:, 1], c=y)
axs[0, 0].set_title("Mixture of Gaussian Blobs")
axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y)
axs[0, 1].set_title("Anisotropically Distributed Blobs")
axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_varied)
axs[1, 0].set_title("Unequal Variance")
axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_filtered)
axs[1, 1].set_title("Unevenly Sized Blobs")
plt.suptitle("Ground truth clusters").set_y(0.95)
plt.show()
K-Means クラスタリング
scikit-learn のKMeansクラスを使ってデータをクラスタリングします。次のコードブロックでは、各データセットに対して k-means によって得られたクラスタを示す 2x2 のプロットを作成します。
from sklearn.cluster import KMeans
common_params = {
"n_init": "auto",
"random_state": random_state,
}
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12))
y_pred = KMeans(n_clusters=2, **common_params).fit_predict(X)
axs[0, 0].scatter(X[:, 0], X[:, 1], c=y_pred)
axs[0, 0].set_title("Non-optimal Number of Clusters")
y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_aniso)
axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
axs[0, 1].set_title("Anisotropically Distributed Blobs")
y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_varied)
axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
axs[1, 0].set_title("Unequal Variance")
y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_filtered)
axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
axs[1, 1].set_title("Unevenly Sized Blobs")
plt.suptitle("Unexpected KMeans clusters").set_y(0.95)
plt.show()
可能な解決策
k-means クラスタリングの制限に対するいくつかの可能な解決策について議論します。次のコードブロックでは、最初のデータセットに対して正しいクラスタ数を見つける方法と、ランダム初期化の数を増やすことでサイズが不均一なブロブを処理する方法を示します。
y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.title("Optimal Number of Clusters")
plt.show()
y_pred = KMeans(n_clusters=3, n_init=10, random_state=random_state).fit_predict(
X_filtered
)
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("Unevenly Sized Blobs \nwith several initializations")
plt.show()
ガウス混合モデル
異方的および分散の異なる分布を処理できるガウス混合モデルの使用を検討します。次のコードブロックでは、GaussianMixtureを使って 2 番目と 3 番目のデータセットをクラスタリングします。
from sklearn.mixture import GaussianMixture
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))
y_pred = GaussianMixture(n_components=3).fit_predict(X_aniso)
ax1.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
ax1.set_title("Anisotropically Distributed Blobs")
y_pred = GaussianMixture(n_components=3).fit_predict(X_varied)
ax2.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
ax2.set_title("Unequal Variance")
plt.suptitle("Gaussian mixture clusters").set_y(0.95)
plt.show()
まとめ
この実験では、k-means クラスタリングアルゴリズムとその仮定を検討しました。異なる分布を持つさまざまなデータセットを生成し、k-means がこのデータをどのようにクラスタに分割するかを可視化しました。また、アルゴリズムのいくつかの制限とそれを克服するための可能な解決策についても議論しました。それには、正しいクラスタ数を見つけること、ランダム初期化の数を増やすこと、およびガウス混合モデルを使用することが含まれます。