Goodな生活

Goodな生活

2017年、新卒で民間シンクタンク入社。学んだこと、考えたことの記録。

MENU

【統計検定準1級】クラスター分析(2017年6月過去問)

はじめに

この記事では統計検定準1級レベルのクラスター分析について扱います。内容の多くは2017年6月の過去問を参考にしています。

まずは統計検定準1級の出題範囲表を確認します。だいたい以下の内容が抑えられればよしとしましょう。

大項目 小項目 項目例
多変量解析 クラスター分析 階層型クラスター分析・デンドログラム、
k-means法、距離行列

目次

クラスター分析とは

クラスター分析(cluster analysis)とは、異なる性質が混ざった集団から、互いに似た性質のものを集めクラスター(集まり)を作る分析方法です。あらかじめ分類の基準が決まっていない(≒分類のための外的基準が与えられない)教師なしの分類法です。

クラスター分析は、階層型クラスター分析非階層型クラスター分析に大別できます。階層型クラスター分析は、最も似ている組み合わせから順番にクラスターにしていく方法です。途中過程が階層のように表せるため、アウトプットとして樹形図(デンドログラム)を描くことができます。一方、非階層クラスター分析は階層的な構造を持ちません。これはあらかじめクラスターの数を決め、決めた数にサンプルを分割する方法です。アウトプットとして散布図を描くことができます。サンプル数が大きいビッグデータを分析するときに適しています。

階層型クラスター分析

生徒1~生徒5の数学(math)と英語(eng)のテスト結果を用いて、階層型クラスター分析をやってみます。階層型クラスター分析は、次のステップで行います。

  1. データ行列を作成する
  2. この行列に対して、個体間の距離を計算した距離行列を作成する
  3. クラスター間の距離の求め方(最近隣法や最遠隣法等)を選択し、コーフェン行列を求める
  4. コーフェン行列に基づき樹形図を描く

データ行列を作成する

> math <- c(10,10,9,7,6)
> eng <- c(10,8,6,8,7)
> n <- 5
> data <- data.frame(id = paste(1:n),math=math,eng=eng)
> as.data.frame(data)
  id math eng
1  1   10  10
2  2   10   8
3  3    9   6
4  4    7   8
5  5    6   7

散布図を描いてみましょう。

> #scatter plot
> ggplot(data = data, mapping = aes(x = math, y = eng)) +
+   geom_point() + 
+   geom_text(aes(label=id),vjust = -0.5, color="blue")

f:id:good_na_life:20200818074735p:plain

距離行列を作成する

距離行列はデータ間の距離を配列して行列の形に並べたものです。距離の求め方にも様々ありますが、ここではユークリッド距離を用います。

> distance <- dist(data)
> as.matrix(distance)
         1        2        3        4        5
1 0.000000 2.000000 4.123106 3.605551 5.000000
2 2.000000 0.000000 2.236068 3.000000 4.123106
3 4.123106 2.236068 0.000000 2.828427 3.162278
4 3.605551 3.000000 2.828427 0.000000 1.414214
5 5.000000 4.123106 3.162278 1.414214 0.000000


距離行列を確認すると、最も近いのは{生徒4,生徒5}の組の1.41だと分かります。ここでまずクラスターが形成されます。次に小さい距離は{生徒1,生徒2}の組の2.00であり、2番目のクラスターが形成されます。最後に残るのが{生徒3}です。こうして{生徒4,生徒5},{生徒1,生徒2},{生徒3}と3つのクラスターが形成されます。

クラスター間の距離を求める

クラスター間の距離の求め方は最近隣法、最遠隣法、群平均法、メディアン法 、重心法、ウォード法など複数あります。ここでは最近隣法と最遠隣法を扱います。簡単に説明すると、

  • 最近隣法

別名単連結法 (single-linkage) 法。2つのクラスターのそれぞれの中から1個ずつ個体を選び、最も近い個体間の距離をクラスター間の距離とする方法。

  • 最遠隣法

別名完全連結 (complete-linkage) 法。2つのクラスターの中のそれぞれの中から1個ずつ個体を選び、最も離れた個体間の距離をこの2つのクラスター間の距離とする方法。

クラスター間の距離を表す行列をコーフェン行列と呼びます。

> #最近隣法
> single <- hclust(distance, "single")
> #最遠隣法
> complete <- hclust(distance,"complete")
>
> #最近隣法のコーフェン行列
> cophenetic(single)
         1        2        3        4
2 2.000000                           
3 2.236068 2.236068                  
4 2.828427 2.828427 2.828427         
5 2.828427 2.828427 2.828427 1.414214
> #最遠隣法のコーフェン行列
> cophenetic(complete)
         1        2        3        4
2 2.000000                           
3 5.000000 5.000000                  
4 5.000000 5.000000 3.162278         
5 5.000000 5.000000 3.162278 1.414214

樹形図を描く

最後に樹形図を描きます。

> plot(single,hang = -1,main="Single-linkage")
> plot(complete,hang = -1,main="Compete-linkage")

f:id:good_na_life:20200822112606p:plain

樹形図の縦軸は距離(クラスターから伸びる枝の長さ)です。左の最近隣法の方が、クラスター間の距離が近くなっていることが分かります。

階層クラスター分析では、あらかじめクラスター数を決めません。似ているもの同士から順番にクラスターを形成していけばよいので、後からクラスター数を決めることができます。上図の結果を使って、3つのクラスターに分割してみましょう。

> plot(single,hang = -1,main="Single-linkage")
> rect.hclust(single, k=3)
> plot(complete,hang = -1,main="Compete-linkage")
> rect.hclust(complete, k=3)

f:id:good_na_life:20200908235943p:plain


各生徒がどのクラスターに含まれるかはcutree()を使えば確認できます。

> cutree(tree=single,k=3)
[1] 1 1 2 3 3
> cutree(tree=complete,k=3)
[1] 1 1 2 3 3

クラスタリングの過程を確認する

hclust()の中には、クラスタリングの過程を示す行列mergeが含まれています。

> single$merge
     [,1] [,2]
[1,]   -4   -5
[2,]   -1   -2
[3,]   -3    2
[4,]    1    3
> complete$merge
     [,1] [,2]
[1,]   -4   -5
[2,]   -1   -2
[3,]   -3    1
[4,]    2    3

マイナス符号が付いているものは生徒の番号、マイナス符号が付いていないのがクラスターの番号です。行の番号はクラスター形成の順番を示します。

非階層型クラスター分析

k-means法

先ほどと同じデータを使って非階層クラスタリングを行います。ここではk-平均法(k-means method)を使います。k-means法はクラスターの平均(mean)を使い、あらかじめ決められた数のクラスター数(k個)に分割するためのアルゴリズムです。k=2個のクラスターに分割する場合、

  1. 2個のクラスター中心の初期値を選ぶ。
  2. 以下の3,4をクラスター中心の変化が起きなくなるまで繰り返す。
  3. 各観測点をクラスター中心からの距離が近い方のクラスターに割り当てる。
  4. クラスターに割り当てられた観測点の重心を計算し、クラスター中心とする。
  5. クラスターに割り当てられた観測点を出力する。

クラスター中心の初期点を生徒1、生徒2とします。先ほどの距離行列を見ると、生徒3,4,5からはいずれも生徒2までの距離の方が近いため、初期点に対して{1}と{2,3,4,5}の2つのクラスターに割り当てられます。クラスター{2,3,4,5}の重心を計算すると、(8,7.25)だと分かります。これを先ほどの散布図に追加します。

f:id:good_na_life:20200822121737p:plain

ここで新たなクラスター中心は生徒1(10,10)と{2,3,4,5}の重心(8,7.25)となりました。重心(8,7.25)を先ほどの距離行列に加える(下表の6)と、生徒3,4,5は生徒1(10,10)よりも重心(8,7.25)の方が近く、一方生徒2は生徒1(10,10)の方が近くなります。

> distance.add <- dist(data.add)
> as.matrix(distance.add)
        1        2        3        4        5        6
1 0.000000 2.236068 4.582576 4.690416 6.403124 4.164583
2 2.236068 0.000000 2.449490 3.605551 5.099020 2.616056
3 4.582576 2.449490 0.000000 3.000000 3.741657 1.960548
4 4.690416 3.605551 3.000000 0.000000 1.732051 1.530931
5 6.403124 5.099020 3.741657 1.732051 0.000000 2.468552
6 4.164583 2.616056 1.960548 1.530931 2.468552 0.000000

したがって、k-meas法の結果{1,2}と{3,4,5}のクラスターに分割されます。

散布図を描く

Rのコマンドkmeans()とclusplot()を使えば簡単です。

> #set initial centers
> c1 <- c(data[1,2],data[1,3])
> c2 <- c(data[2,2],data[2,3])

> #2-means
> km <- kmeans(data.r,rbind(c1,c2))
> result <- km$cluster
> result
[1] 1 1 2 2 2
> clusplot(data.r, km$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)

f:id:good_na_life:20200822141538p:plain
{1,2}と{3,4,5}のクラスターに分割されることが確認できました。

ちなみにkmeans()の中身には各クラスターの平均等が含まれます。

> (km <- kmeans(data.r,rbind(c1,c2)))
K-means clustering with 2 clusters of sizes 2, 3

Cluster means:
       math eng
1 10.000000   9
2  7.333333   7

Clustering vector:
[1] 1 1 2 2 2

Within cluster sum of squares by cluster:
[1] 2.000000 6.666667
 (between_SS / total_SS =  60.6 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
[6] "betweenss"    "size"         "iter"         "ifault"  

次はより規模の大きなデータを使って非階層クラスタリングをやってみたいと思います。以上、お読みいただきありがとうございました。