[教師なし学習] k-means でクラスタリングを行う

IT

はじめに

本記事では、k-means を用いてデータを分類(クラスタリング)します。
Python の機械学習ライブラリである scikit-learn を使用して実装します。

環境

以下が今回の環境です。

$ python -V
Python 3.7.10

$ pip list | grep -e numpy -e pandas -e matplotlib -e seaborn -e scikit-learn
matplotlib            3.5.2
matplotlib-inline     0.1.3
numpy                 1.21.6
pandas                1.3.5
scikit-learn          1.0.2
seaborn               0.11.2

処理の流れ

ライブラリをインポートします。
可視化には seaborn を使用します。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

scikit-learn が提供するサンプルデータを使用するために load_iris をインポートします。
load_irisのデータは、3 種類の品種のアヤメのがく片(Sepal)、花弁(Petal)の幅および長さを計測したデータです。

from sklearn.datasets import load_iris

dataset = load_iris() # データセットの読み込み
x, t, columns = dataset.data, dataset.target, dataset.feature_names # データ、各データの分類、カラム名を取得
print(pd.DataFrame(x, columns=columns))
#      sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
# 0                  5.1               3.5                1.4               0.2
# 1                  4.9               3.0                1.4               0.2
# 2                  4.7               3.2                1.3               0.2
# 3                  4.6               3.1                1.5               0.2
# 4                  5.0               3.6                1.4               0.2
# 5                  5.4               3.9                1.7               0.4
# 6                  4.6               3.4                1.4               0.3
# 7                  5.0               3.4                1.5               0.2
# 8                  4.4               2.9                1.4               0.2
# 9                  4.9               3.1                1.5               0.1
# 10                 5.4               3.7                1.5               0.2
#  ... 
# 149                5.9               3.0                5.1               1.8

# [150 rows x 4 columns]

print(t)
# array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#        0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#        1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
#        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
#        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

クラスタリングのアルゴリズムには k-means を使用します。
クラスタ数は人間が指定する必要があります。最適はクラスタ数は、シルエット分析などの分析結果や、分析対象に関する知識などから導く必要があります。

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, random_state=0)
kmeans.fit(x) # 学習
cluster = kmeans.predict(x) # クラスタリング
print(cluster)
# [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
# 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 2 2 2 0 2 2 2 2
# 2 2 0 0 2 2 2 2 0 2 0 2 0 2 2 0 0 2 2 2 2 2 0 2 2 2 2 0 2 2 2 0 2 2 2 0 2
# 2 0]

グラフを描画して、クラスタリングの結果を確認します。今回は例として”sepal length”と”sepal width”を使用して二次元で描画します。
参考に、正解データも同様にグラフ化し、結果を比較してみると、似た結果になっていることも確認できます。
上がクラスタリング結果、下が実際の分類です。

sns.scatterplot(df_results['sepal length (cm)'], df_results['sepal width (cm)'],
                hue=cluster, palette=sns.color_palette(n_colors=3)
                )
plt.savefig("cluster.png") # グラフの保存
plt.clf() # グラフの初期化

sns.scatterplot(df_results['sepal length (cm)'], df_results['sepal width (cm)'],
                hue=t, palette=sns.color_palette(n_colors=3)
                )
plt.savefig("target.png")

サンプルコードまとめ

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.datasets import load_iris

dataset = load_iris() # データセットの読み込み

x, t, columns = dataset.data, dataset.target, dataset.feature_names # データとカラム名を取得
print(f'x.shape:{x.shape}')

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, random_state=0)
kmeans.fit(x)
cluster = kmeans.predict(x)

df_results = pd.DataFrame(x, columns=columns)
df_results['target'] = t
df_results['predict']=cluster
print(df_results)

sns.scatterplot(df_results['sepal length (cm)'], df_results['sepal width (cm)'],
                hue=cluster, palette=sns.color_palette(n_colors=3)
                )
plt.savefig("cluster.png") # グラフの保存
plt.clf() # グラフの初期化

sns.scatterplot(df_results['sepal length (cm)'], df_results['sepal width (cm)'],
                hue=t, palette=sns.color_palette(n_colors=3)
                )
plt.savefig("target.png")

おわりに

本記事では、k-means を用いてデータを分類(クラスタリング)します。 この記事がどなたかの参考になれば幸いです。

参考

コメント