R筋

プログラミング、金融、育児

【R】クラスタ分析の解説とRによる実装

クラスタ分析について整理しました。

クラスタ分析とは

クラスタ分析とは、「データのパターンが似ている個体を同じグループにまとめる分析方法」である。機械学習では、正解となる教師データを定めずデータの構造を把握する「教師なし学習」の代表的な手法の一つだ。

先日こんなツイートがバズっていた。


この方を含め、この図を見た大体の人は各都道府県を「東京」「東京以外」というグループに分けた上で、物事を考えるのだと思う。
ただこういう平面上にプロットできるデータであれば、視覚的に判断ができるが、第3軸として「満足度」などがある3次元のグラフになると、直感的にグループ化することは難しくなる。
この問題をクラスタ分析により、「いくつのグループにするか」「各個体(都道府県)をどのグループに所属させるか」を示すことができる。
注意が必要なのは、クラスタ分析によってグループ化した結果は、機械がアルゴリズムに従って出力したものであり、データを解釈した上で何らかの根拠に基づいて分類しているものではないという点である。
「東京」「東京以外」というグループ分けを行ったとしても、「東京」と「東京以外」にどのような違いがあるのかは人間が考えなくてはならない。

サンプルデータ

上記ツイートの出典を参考に年収と物価の表を作成。
f:id:anpontan382:20200225001239p:plain
Rで読み込んで、散布図を作成してみる。

library(maptools)
plot(cluster$収入,cluster$物価)
pointLabel(cluster$収入,cluster$物価,cluster$都道府県)

f:id:anpontan382:20200225224821p:plain
若干ずれていますが、もとのグラフに近いものができた。

階層的クラスタ分析

階層的クラスタ分析とはクラスタ分析の手法の一つである。個体間の類似度に基づき、最も似ている個体から順次クラスタを作る。クラスタが作成されていく過程は樹形図(デンドログラム)で表示される。
とりあえずやってみるとこうなった。

rownames(cluster) <- cluster$都道府県
cluster.d <- dist(cluster)
 hc1 <- hclust(cluster.d, "ward.D2")
plot(hc1)

f:id:anpontan382:20200225233245p:plain

階層的クラスタ分析は次のステップによる。
1)データから距離を求める(dist関数)
2)分析の手法(よく使われるのはウォード法)を決め、
コーフェン行列を求める(hclust関数)
3)樹形図を作成する(plot関数)

距離行列を求める手法にはいくつかあり、用いる手法によって結果がクラスタリングの結果が異なる。
最短距離法を用いる場合は、heclust関数のmethodに"single"を指定する。

rownames(cluster) <- cluster$都道府県
cluster.d <- dist(cluster)
 hc2 <- hclust(cluster.d, "single")
plot(hc2)

f:id:anpontan382:20200225233131p:plain
ウォード法の結果と若干異なることがわかる。
いずれが妥当かを判断する方法として、(1)で作成した距離の行列と(2)で作成した樹形図のもととなるコーフェン行列とのコーフェン相関係数を求める方法がある。

cor(cluster.d,cophenetic(hc))
#0.6607074
cor(cluster.d,cophenetic(hc1))
#0.8553172

コーフェン相関係数が大きいほど、コーフェン行列への変換における歪みが小さいといえる。
歪みが小さくても妥当であるとは言えない。前述のクラスタ分析の課題に記載の通り、どの妥当な手法は得られた結果をもとに人間が判断する必要がある。

ただ、やはりいずれの手法でも「東京」と「東京以外」のグループで最大の違いがあることがわかる。
もう少し、「東京以外」を掘り下げてみよう。cutreeにより、樹形図をもとに指定したグループ数に個体を分類することができる。

as.data.frame(cutree(hc1,k=4))

f:id:anpontan382:20200225235147p:plain

非階層クラスタ分析

データ数が増えると、全組み合わせの距離行列を計算する階層的クラスタ分析では計算量が膨大になるため、非階層的クラスタ分析が用いられる。
代表的な方法としては、k平均法(k-means)がある。
先程のデータフレームを3グループに分ける場合は、

rownames(cluster1) <- cluster$都道府県
cluster.km <- kmeans(cluster1,centers = 3)
cluster.km$cluster

f:id:anpontan382:20200227233826p:plain
ずれていて少し分かりづらいが今回は「東京」「大阪」「愛知」「神奈川」が一つのグループになっている。
これはk平均法のアルゴリズムが、最初に決めたクラスタ数(3個)をプロットし、一番近くクラスタに個体を所属させるというものであるからだ。
このあたり、前述の階層的クラスタ分析の結果や、直感とはズレる部分であるが、含まれているのは全部人工の多い都市がある自治体という点をみると、これも妥当な視点なのかもしれない。どの手法を使うにしても、クラスタ化の結果の解釈が重要だということである。

またk平均法では、事前にいくつのグループに分けるかというクラスタ数を指定する必要がある。適切なクラスタ数を決める方法には、シルエット分析とエルボー法といったものがある。
非階層クラスタ分析について可視化するには、clusplot関数を使う。

clusplot(cluster1, cluster.km$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)

f:id:anpontan382:20200228000357p:plain

参考文献