【scikit-learn】KMeansでk-means法によるクラスタリングをする方法

Python の機械学習ライブラリである sciki-learn の KMeans を使って k-means 法によるクラスタリングを行う方法を解説します。
目次
k-means 法によるクラスタリング
k-means 法とは、教師なし学習で代表的なクラスタリングの中でも有名な手法の 1 つです。分類アルゴリズムの k-近傍法とは異なるため注意しましょう。
k-means 法のアルゴリズムの手順概要は以下のようになります。
- データの中からk個のデータ点を任意に抽出して、初期値のセントロイドとして設定する。その後に、以下の 2、3 のステップを反復する。
- 全てのデータ点を最も近いセントロイドにそれぞれ割り振る。
- 各 k 個のセントロイドに割り振られたデータの重心を計算して、その重心を新しいセントロイドとして更新する。
ここでセントロイドと言っているのは、各クラスタの中心の事です。
k-means 法では、SSE(Sum of Squared Errors)というクラスタ内の誤差平方和を用いて、この SSE を最小化するようにセントロイドが選ばれます。また、k-means 法は、クラスタ数を事前に指定しないとクラスタリングできないことも特徴です。
k-means 法によるクラスタリングは、Python の機械学習ライブラリである scikit-learn にて KMeans として実装がされています。
この記事では、KMeans を使ったクラスタリング方法の実装例を紹介します。また、クラスタ数を決める方法の 1 つであるエルボー法についても説明します。
KMeans を使ったクラスタリング
k-menas 法の使い方(sklearn.cluster.KMeans)
実装例
scikit-learn の make_blogs でクラスタリング用のデータを用意し、KMeans を使ってk-means 法によるクラスタリングをする方法について紹介します。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
def main():
"""メイン関数"""
np.random.seed(1)
# ===== データの生成
k = 5
data, label = make_blobs(n_samples=500, n_features=2, centers=k, cluster_std=1.0)
# ===== k-meansクラスタリング
km = KMeans(n_clusters=k)
pred = km.fit_predict(data)
# ===== SSE値を出力
print(f"SSE: {km.inertia_:.2f}")
# ===== クラスタリング結果を描画する
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
# 元データを表示する
ax[0].scatter(data[:, 0], data[:, 1])
ax[0].set_title("original data")
# クラスタリング結果を表示する
for i in range(k):
ax[1].scatter(data[pred == i, 0], data[pred == i, 1])
ax[1].set_title("k-means clustering")
plt.show()
if __name__ == "__main__":
main()【実行結果】 SSE: 894.48

実装内容の解説
上記で紹介して実装例の各部分ごとに内容を解説していきます。
必要モジュールのインポート
from sklearn.cluster import KMeans
k-means クラスタリングを使用するには、sklearn.cluster から KMeans をインポートします。他にも NumPy 等インポートしていますが説明は省略します。
データセットの準備
np.random.seed(1)
# ===== データの生成
k = 5
data, label = make_blobs(n_samples=500, n_features=2, centers=k, cluster_std=1.0)データは、make_blobs を使用して生成します。引数として指定しているのは以下の項目です。
n_sample:データの点数n_features:データの次元数centers:クラスタの数cluster_std:各クラスタの標準偏差
今回は、5 つのクラスタを作成しています。また、教師なし学習のため、label の方は使用していません。乱数シードは、np.random.seed で設定していますが、make_blobs の random_state 引数で指定することも可能です。
k-means クラスタリングの実行
# ===== k-meansクラスタリング
km = KMeans(n_clusters=k)
pred = km.fit_predict(data)上記の部分で k-means クラスタリングを実行しています。n_clusters でクラスタ数を指定し、クラスタリングは fit_predict メソッドを使って実行します。
SSE(誤差平方和)の取得
# ===== SSE値を出力
print(f"SSE: {km.inertia_:.2f}")計算された SSE(誤差平方和)については inertia_ で取得できます。
クラスタリング結果の表示
# ===== クラスタリング結果を描画する
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
# 元データを表示する
ax[0].scatter(data[:, 0], data[:, 1])
ax[0].set_title("original data")
# クラスタリング結果を表示する
for i in range(k):
ax[1].scatter(data[pred == i, 0], data[pred == i, 1])
ax[1].set_title("k-means clustering")
plt.show()上記の部分は、元データとクラスタリング結果を横に並べて表示している部分です。

結果を再掲しますが、5 クラスのデータに分類できていることが分かります。
エルボー法によるクラスタ数の決定
k-means 法によるクラスタリングでは、実行前にクラスタ数を決めて指定する必要があります。上記例では、方法の説明のために分かりやすいように 5 つのクラスタのデータセットを作り、そのデータセットに対して k=5 で k-means クラスタリングを実行したため、きれいにクラスタリングができていました。
しかし、実際の適用場面では、データがいくつのクラスタになるかは事前に分かりません。では、k の数をどう決めればよいでしょうか。
クラスタ数を決めるときに参考になる手法としてエルボー法という方法があります。エルボー法では、k-means に指定するクラスタ数の数を増やしていったときに SSE がどのように変化するかをプロットし、その結果からクラスタ数を決定する方法です。
クラスタ数を増やしていって SSE をプロットするとグラフが、かくっと曲がって変化が少なくなる部分が出てきます。エルボー法では、この時のクラスタ数を最適とします。なぜ「エルボー」というかというと SSE のプロット形状が肘が曲がっているように見えるためです。
では、エルボー法でクラスタ数を調べてみるサンプルプログラムを見てみましょう。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
def main():
"""メイン関数"""
np.random.seed(1)
# ===== データの生成
k = 5
data, label = make_blobs(n_samples=500, n_features=2, centers=k, cluster_std=1.0)
# ===== エルボー法
sse = []
for k in range(1, 11):
km = KMeans(n_clusters=k)
km.fit(data)
sse.append(km.inertia_)
# ===== SSE値をプロットする
plt.plot(range(1, 11), sse, "o-")
plt.title("elbow method")
plt.xlabel("number of clusters")
plt.ylabel("sse")
plt.show()
if __name__ == "__main__":
main()
上記では、k を 1 ~ 10 まで変えつつ、KMeans を使った k-means クラスタリングを実行しています。そして、図は各 k における SSE の値をリストに蓄積してグラフにプロットしたものになります。
この結果を見るとクラスタ数が 5 のところまでは降下が大きいのに対して 5 以降については緩やかになっているように見えます。このため、k の適切な値は 5 ではないかと予想できます。これがエルボー法での考え方です。
今回は、分かりやすい分類データを使っているため、きれいなプロット図ですが、現実の問題に対しては、これほどきれいにならない場合がほとんどかと思います。
まとめ
Python の機械学習ライブラリである sciki-learn の KMeans を使って k-means 法によるクラスタリングを行う方法を解説してきました。また、k-means にて指定するクラスタ数を決める 1 つの方法であるエルボー法についても紹介しています。
k-means 法は、教師なし学習で代表的なクラスタリングの中でも有名な手法です。scikit-learn の KMeans の使い方も簡単なため、色々な例で試してみてください。
上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。



.jpg)

を用いたデータ分類方法.jpg)
とランダムフォレスト(RandomForest)の使用方法.jpg)
