k-means法(k-平均法)についてメモ。
【目次】
前回取り上げた「k-近傍法」とは異なるので注意。
【機械学習_Python】k-近傍法(k-NN) - こちにぃるの日記
k-means法
データのクラスタリングに用いられる手法である。
分類問題における「教師なし学習」に属する。
アルゴリズムは比較的単純で、次の手順となる。
- 特徴空間上にk個のランダムな代表点(セントロイド)をプロットする。クラスタ数のkはハイパーパラメータであり、あらかじめ指定する。
- 各データとセントロイドの距離を求め、各データを最も近いセントロイドのグループに分類する。
- 上記2のグループでの重心(平均)を求め、新たなセントロイドとする。
- 上記2、3を繰り返す。
- セントロイドが更新されなくなれば終了し、分類を確定する。
クラスタ内誤差平方和(Sum of Squared errors of prediction、SSE)
k-means++法
k-means法では、初期値のセントロイドをランダムな位置にプロットするため、複数のセントロイドが近くに位置する可能性があり、分類がうまくいかないことがある。
この問題の改良としてk-means++法があり、セントロイド同士が離れた位置にプロットされやすくなるアルゴリズムである。
エルボー法によるクラスタ数の推定
k-means法でのクラスタ数はハイパーパラメータであり、あらかじめ指定する必要がある。
このクラスタ数の推定方法として「エルボー法」がある。
エルボー法は、クラスタ数ごとのクラスタ内誤差平方和(SSE)を横に並べ、プロットがゆるやかになる位置を最適なクラスタ数とする方法である。
Pythonコード
sklearn の cluster の KMeans で実装できる。
パラメタ説明はコメントアウトに記載する。
#-- k-means法 km1 = KMeans(n_clusters=4 # クラスター数指定。 ,init="k-means++" # 'k-means++' or 'random'(k-means) 。default:'k-means++' ,n_init=10 # k-meansの実行回数 ,random_state=0 # 乱数シード ) Y_km = km.fit_predict(X) # 各データのクラスタ番号を求める #-- SSE値を出力 print("Distortion: %.2f" % km.inertia_)
Irisデータでエルボー法のプロットを作ってみる。
クラスタ数(n_clusters=i
)を1~10までループして、各クラスタ数のSSE(km.inertia_
で取得可)をプロットする。
from sklearn import datasets, cluster import numpy as np import matplotlib.pyplot as plt #-- データ取得 X = datasets.load_iris() #-- エルボー法(クラスタ数10まで) SSE = [] for i in range(1, 11): km = cluster.KMeans(n_clusters = i ,init="k-means++" ,n_init=10 ,random_state=1) km.fit(X.data) SSE.append(km.inertia_) # グラフのプロット plt.plot(range(1, 11), SSE, marker="o") plt.xticks(np.arange(1, 11, 1)) plt.xlabel("クラスタ数") plt.ylabel("クラスタ内誤差平方和(SSE)") plt.show()
参考
sklearn.cluster.KMeans — scikit-learn 0.24.2 documentation
https://www.mext.go.jp/content/20200609-mxt_jogai01-000007843_007.pdf
https://www.jstage.jst.go.jp/article/fss/27/0/27_0_55/_pdf