【Python初心者】 直感的に理解できるクラスタリング k-means

スポンサーリンク
Python
初心者に人気のプログラミング言語Pythonは独学可能か?
Pythonは非常に人気のあるプログラミング言語で、まったくの初心者でも独学が可能と言われています。 Pythonはさまざまな目的に使える、汎用性のあるプログラミング言語です。 プログラミングは「独学が難しい」と言われていま...
ゼロ知識の初心者がデータサイエンスを完全無料で学習する方法5選
データサイエンスの知識や技術、またはPythonについて学びたい。でも「大学に行くほど本気度がない」、「スクールに行くほどお金がない」、なんせ「時間がない」という方も多いはずです。というよりほとんどの方がそうだと思います(当然わたし...

機械学習には、教師あり学習・教師なし学習・強化学習があります。
教師なし学習は、正解かどうかは教えずに、データだけを与えて各集団に分類させる方法です。
教師なし学習のひとつである「クラスタリング」について、Pythonのコードから理解してみましょう。
クラスタリングとは、似ているデータを集めて、いくつかの集団に分類することです。
今回は、クラスタリングの中で最も一般的なK-Means法について理解を深めていきましょう。

必要なライブラリをインポート

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')

from sklearn.datasets import make_moons

クラスタリングが難しいデータセットを使って、動きを見てみましょう。
moonsは現実世界では、ほぼあり得ないデータだが、クラスタリングの性能が分かりやすいと思います。

moonsデータセットの確認

X,y = make_moons(n_samples=200,noise=0.05,random_state=0)

plt.scatter(X[:,0],X[:,1])

出力:

こんなデータです。

moonsの名のまま、半月型のデータが2つありますね。

Xとyのデータをみてみましょう。

np.set_printoptions(threshold=0)  # 全部表示しないようにしている
X

出力:

Xは2列のデータが、200あることが分かります。(200は上コードの「make moons」のなかの、n_samples=200でデータの個数を指定しています。)

y

出力:

0と1の二値で表されています。

グラフの上の半月と下の半月の二値に分類できればいいですね。
理想の分類を見てみましょう。

plt.scatter(X[:,0],X[:,1],c=y)

上の半月は紫色、下の半月は黄色になっています。

Xのデータだけで、yの二値を正確に分類できれば、クラスタリング成功です。

K-Meansの実装

from sklearn.cluster import KMeans

kmeans=KMeans(n_clusters=2,random_state=0)
kmeans.fit(X)
y_pred=kmeans.predict(X)

これで、K-Meansは完了です。簡単でしたね。
KMeans(n_clusters= )の数値は何個の集団に分類にするかを指定します。今回は2つの集団に分類したいので、2を指定します。
では、グラフを描いて、K-Meansで行った分類を色分けしてみましょう。

plt.scatter(X[:,0],X[:,1],c=y_pred)

出力:

ぜんぜん上手く分類できていないですね。やはり、半月型が2つが重なるようなデータではクラスタリングが難しいようですね。K-Means法はデータに重心を作成し、その重心に近いデータを一つの集団に分類させれます。ではその重心を見てみましょう。

plt.scatter(X[:,0],X[:,1],c=y_pred)
plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],
           marker='^',c=["purple","y"],s=300,linewidth=2)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

出力:

グラフの▲がK-Means法で作成した2つの集団の重心の位置です。

やはり重心の位置は正確ではありません。というより半月型のデータを1つの重心で分類するのは難しいですね。

では、どうすればいいでしょうか

2つの集団に分類するのが難しいなら、もっと多くの集団に分類させてみましょう。

K-Means法で10個の集団に分類する

kmeans=KMeans(n_clusters=10,random_state=0)
model=kmeans.fit(X)

分類結果を見てみましょう。

model.labels_

出力:

0から9の数値で10個の数値で分類されています。

ではグラフにして上手くクラスタリングできているか確認してみましょう。

plt.scatter(X[:,0],X[:,1],c=model.labels_,cmap="Paired")
plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],
           marker="^",c=range(kmeans.n_clusters),s=500,linewidth=2,cmap="Paired")
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

出力:

上の半月に5つの集団、下の半月に5つの集団にクラスタリングできました。

クラスタリングされたラベルをグラフで確認してみましょう。

plt.scatter(X[:,0],X[:,1],c=model.labels_,cmap="Paired")
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
for i in range(len(kmeans.cluster_centers_)):
    plt.scatter(kmeans.cluster_centers_[i,0],kmeans.cluster_centers_[i,1],
            marker="$"+str(i)+"$",s=300,c="black")

出力:

10個の集団の重心位置を確認してみましょう。

for i in range(len(kmeans.cluster_centers_)):
    print(i,"の座標:",kmeans.cluster_centers_[i,:])

出力:

[ ]内の1つめの数値はx軸、2つめの数値はy軸です。

上の半月は9,0,8,2,4、下の半月は6,3,1,7,5のラベルでした。
このままでもいいですが、これは二値分類なので、0と1の二値に変換しましょう。

import pandas as pd
y_pred_seri=pd.Series(model.labels_).replace([9,0,8,2,4],0) # (9,0,8,2,4)を0に変換
y_pred_seri=pd.Series(y_pred_seri).replace([6,3,1,7,5],1)   # (6,3,1,7,5)を1に変換

0と1に変換して、「y_pred_seri」という名前をつけました。
結果を正解ラベルである「y」と一緒に表示させてみましょう。

for i in range(20):
    print(y[i], y_pred_seri[i])

出力:

一緒ですね。

sum(y==y_pred_seri)

出力:
200

データは200個あったので、すべてのデータが正解という結果になりました。
半月のデータはクラスタリングが難しいですが、集団の個数を変化させることで、うまくいく場合があります。
自分が分類したい個数に固執することなく、集団の個数を変えてみてはいかがでしょうか。

【初心者】複数の機械学習モデルの性能を比較する(回帰問題編)

【初心者】複数の機械学習モデルの性能を比較する(分類問題編)

コメント

タイトルとURLをコピーしました