k-means法は古典的な非階層的クラスタリング手法で、サンプルデータをK個のクラスターに分け、中心点からの距離の近さにより分類するという方法です。
クラスタリングの流れ
- クラスタ数をk個指定して、セントロイド(中心点)をランダムにk個配置する
- 各サンプルを近接するセントロイドに割り当てる
- セントロイドに割り当てたサンプルの中心を求め、セントロイドを移動させる
- 2.と3.を繰り返し、中心点が変わらなくなったら、クラスタリング終了
1. Numpyで実装
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris = datasets.load_iris() # irisを読み込む関数
df = pd.DataFrame(
iris.data, # データフレームの要素
columns = iris.feature_names # 各列の名前に特徴名を使う
)
# iris.target には種類が格納されている
df["label"] = iris.target # わかりやすくするためにlabel列を追加、ここにクラス番号を入れておきます。
print(df)
input_data = df.iloc[:,:-1].values # インスタンス属性valuesにアクセスすると、np.arrayが取得できます。
def kmeans(k, X, max_iter=300):
X_size,n_features = X.shape # 150 4
# ランダムに重心の初期値を初期化
centroids = X[np.random.choice(X_size,k)] # X[ 17 105 56]
# 前の重心と比較するために、仮に新しい重心を入れておく配列を用意
new_centroids = np.zeros((k, n_features))
# 各データ所属クラスタ情報を保存する配列を用意
cluster = np.zeros(X_size)
# ループ上限回数まで繰り返し
for epoch in range(max_iter):
# 入力データ全てに対して繰り返し
for i in range(X_size):
# データから各重心までの距離を計算(ルートを取らなくても大小関係は変わらないので省略)
distances = np.sum((centroids - X[i]) ** 2, axis=1)
# データの所属クラスタを距離の一番近い重心を持つものに更新
cluster[i] = np.argsort(distances)[0]
# すべてのクラスタに対して重心を再計算
for j in range(k):
new_centroids[j] = X[cluster==j].mean(axis=0)
# もしも重心が変わっていなかったら終了
if np.sum(new_centroids == centroids) == k:
print("break")
break
centroids = new_centroids
return cluster
cluster=kmeans(3, input_data)
df["cluster"] = cluster
df.plot(kind="scatter", x=0,y=1,c="label", cmap="winter") # cmapで散布図の色を変えられます。
plt.title("true label")
plt.show()
df["cluster"] = cluster
df.plot(kind="scatter", x=2,y=3,c="label", cmap="winter") # cmapで散布図の色を変えられます。
plt.title("true label")
plt.show()
df.plot(kind="scatter", x=0,y=1,c="cluster", cmap="winter") # cmapで散布図の色を変えられます。
plt.title("clustering relust")
plt.show()
df.plot(kind="scatter", x=2,y=3,c="cluster", cmap="winter") # cmapで散布図の色を変えられます。
plt.title("clustering relust")
plt.show()
2. skleanで実装
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
import seaborn as sns
from sklearn.cluster import KMeans
iris = datasets.load_iris()
df = pd.DataFrame(
iris.data,
columns = iris.feature_names
)
df['target'] = iris.target
sns.pairplot(df, hue="target")
plt.show()
df["label"] = iris.target
print(df)
input_data = df.iloc[:,:-1].values
n_clusters = 2
clf = KMeans(n_clusters=n_clusters, init='k-means++', n_init=10, max_iter=300,tol=0.0001)
pred = clf.fit_predict(input_data)
df['label'] = pred
df.plot(kind="scatter", x=0,y=1,c="label", cmap="winter")
plt.title("clustering relust")
plt.show()
まとめ
今回は、非階層的なクラスタリング手法であるk-mean法を、Numpyとskleanを用いて実装する方法を紹介した。