

機械学習には、教師あり学習・教師なし学習・強化学習があります。
教師なし学習は、正解かどうかは教えずに、データだけを与えて各集団に分類させる方法です。
教師なし学習のひとつである「クラスタリング」について、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")
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個あったので、すべてのデータが正解という結果になりました。
半月のデータはクラスタリングが難しいですが、集団の個数を変化させることで、うまくいく場合があります。
自分が分類したい個数に固執することなく、集団の個数を変えてみてはいかがでしょうか。
コメント