Loading [MathJax]/extensions/tex2jax.js

[scikit-learn] 11. k-means法によるクラスタリング

matplotlib

はじめに

sklearn.clusterのKMeansでk平均法によるクラスタリングをすることができる。ここではsklearn.datasets.make_blobsで作成したデータに対してクラスタリングを行う方法について説明する。

解説

モジュールのインポートなど

from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
view raw kmeans_1.py hosted with ❤ by GitHub

バージョン

#version
import matplotlib
print(matplotlib.__version__)
3.3.4
import sklearn
print(sklearn.__version__)
0.24.1
view raw kmeans_1.py hosted with ❤ by GitHub

データの生成

# Generate sample data
n_samples = 1000
n_components = 5
X, y = make_blobs(n_samples=n_samples,
centers=n_components,
cluster_std=1,
random_state=10)
view raw kmeans_1.py hosted with ❤ by GitHub

make_blobsによりデータを作成する。make_blobsについては下記記事で解説した。

[scikit-learn] 1. make_blobsによる分類用データの生成
sklearnのdatasets.make_blobsでクラスタリング用のデータを作成することができる。データポイントはガウス分布に従い生成する。ここでは各種パラメータが生成データに及ぼす影響について説明する。

データの塊の数を5とし、データのばらつき(標準偏差)を設定できるcluster_stdを1,random_stateを10とした。データを表示すると以下のようになる。

fig, ax = plt.subplots(dpi=140,figsize=(4,4))
ax.axis("equal")
plt.scatter(X[:, 0], X[:, 1], c=y, marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax.set(xlabel="x",ylabel="y")
plt.savefig("kmeans_1_1.png",dpi=100)
plt.show()
view raw kmeans_1.py hosted with ❤ by GitHub

クラスター数

#n_clusters
n_clusters=5
kmeans_model_5 = KMeans(n_clusters)
n_clusters=10
kmeans_model_10 = KMeans(n_clusters)
fit_5 =kmeans_model_5.fit(X)
fit_10 =kmeans_model_10.fit(X)
y_5_ = fit_5.labels_
y_10_ = fit_10.labels_
view raw kmeans_1.py hosted with ❤ by GitHub

Kmeans法ではクラスター数を自分で決める必要がある。ここでは、クラスター数を5と10にしたときの結果を示す。
KMeans(n_clusters)でモデルを設定する。設定したモデルに.fit(X)とすることでクラスタリングを行い、フィットした結果に.labels_とすることでラベルを得ることができる。

結果の表示

fig, ax = plt.subplots(1,2,dpi=140,figsize=(8,4),sharex=True,sharey=True)
ax[0].set(xlabel="x",ylabel="y")
ax[0].scatter(X[:,0],X[:,1], c=y_5_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[0].scatter(fit_5.cluster_centers_[:,0],fit_5.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[0].set_title("n_clusters=5")
ax[1].set(xlabel="x",ylabel="y")
ax[1].scatter(X[:,0],X[:,1], c=y_10_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[1].scatter(fit_10.cluster_centers_[:,0],fit_10.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[1].set_title("n_clusters=10")
plt.savefig("kmeans_1_2.png",dpi=100)
plt.show()
view raw kmeans_1.py hosted with ❤ by GitHub

cluster_centers_により、クラスタリングして最終的に収束した重心の位置の座標を得ることができる。

初期値

#init
n_clusters=5
kmeans_model_pp = KMeans(n_clusters,init="k-means++",n_init=1,max_iter=1)
kmeans_model_random = KMeans(n_clusters,init="random",n_init=1,max_iter=1)
fit_p =kmeans_model_pp.fit(X)
fit_r =kmeans_model_random.fit(X)
y_p_ = fit_p.labels_
y_r_ = fit_r.labels_
view raw kmeans_1.py hosted with ❤ by GitHub

クラスター中心の初期値をinitにより変更できる。デフォルトは”k-means++”で大体ちょうどいい位置に初期値が設定される。”random”はランダムに初期値が決定される。n_initは初期値を設定する回数でmax_iterは計算を行う回数となる。ここでは両方とも1として初期値の位置を確認する。

結果の表示

fig, ax = plt.subplots(1,2,dpi=140,figsize=(8,4),sharex=True,sharey=True)
ax[0].set(xlabel="x",ylabel="y")
ax[0].scatter(X[:,0],X[:,1], c=y_p_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[0].scatter(fit_p.cluster_centers_[:,0],fit_p.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[0].set_title("init='k-means++'")
ax[1].set(xlabel="x",ylabel="y")
ax[1].scatter(X[:,0],X[:,1], c=y_r_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[1].scatter(fit_r.cluster_centers_[:,0],fit_r.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[1].set_title("init='random'")
plt.savefig("kmeans_1_3.png",dpi=100)
plt.show()
view raw kmeans_1.py hosted with ❤ by GitHub

初期値がk-means++の時は計算回数1でもうまくクラスタリングができている。
randomの場合は初期値がランダムなので、1回の計算ではクラスタリングがうまくいっていないことがわかる。

収束の判断パラメータ tol

#tol
X, y = make_blobs(n_samples=n_samples,
centers=n_components,
cluster_std=2.5,
random_state=10)
n_clusters=5
kmeans_model_tole4 = KMeans(n_clusters,tol=0.0001)#default
kmeans_model_tole1 = KMeans(n_clusters,tol=0.1)
fit_4 =kmeans_model_tole4.fit(X)
fit_1 =kmeans_model_tole1.fit(X)
y_4_ = fit_4.labels_
y_1_ = fit_1.labels_
view raw kmeans_1.py hosted with ❤ by GitHub

誤差がtolの値を下回った時に計算が終了する。ここではtol=0.1の場合とtol=0.0001でクラスタリングした結果を示す。

結果の表示

fig, ax = plt.subplots(1,2,dpi=140,figsize=(8,4),sharex=True,sharey=True)
ax[0].set(xlabel="x",ylabel="y")
ax[0].scatter(X[:,0],X[:,1], c=y_4_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[0].scatter(fit_4.cluster_centers_[:,0],fit_4.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[0].set_title("tol=0.0001,Number of iterations="+str(fit_4.n_iter_)+"")
ax[1].set(xlabel="x",ylabel="y")
ax[1].scatter(X[:,0],X[:,1], c=y_1_,marker='o',alpha=0.5,s=55,linewidths=.1,edgecolor="k",cmap="turbo")
ax[1].scatter(fit_1.cluster_centers_[:,0],fit_1.cluster_centers_[:,1],s=60, marker='D',c='pink')
ax[1].set_title("tol=0.1,Number of iterations="+str(fit_1.n_iter_)+"")
plt.savefig("kmeans_1_4.png",dpi=100)
plt.show()
view raw kmeans_1.py hosted with ❤ by GitHub

.n_iter_により計算回数を得ることができる。tolが0.0001の時の計算回数は6で、tolが0.1の時の計算回数は2回となっている。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

KMeans
Gallery examples: Release Highlights for scikit-learn 1.1 Release Highlights for scikit-learn 0.23 A demo of K-Means clu...
An example of K-Means++ initialization
An example to show the output of the sklearn.cluster.kmeans_plusplus function for generating initial seeds for clusterin...

コメント