文書の過去の版を表示しています。


縛り。

  • 学習機械にはlm()かrpart()しか使わない。
  • kmeans()を層別に使う。

準備。

install.packages(c("mvtnorm"), dependencies=TRUE)
library(mvtnorm)
library(MASS)

k-means法によるクラスタリング

まず楕円状に分布するデータ(n=1000)を擬似乱数を用いて生成する。

test.data <- rmvnorm(1000,mean=c(1,1),sigma=matrix(c(1,0.5,0.5,1),ncol=2))
plot(test.data)

これにk-means法をかけてみる。k-means法では、クラスタ数kは分析者が指定するものであり、ここでは2としてみる。さらに最小値を求めるために、ランダムに1000の初期値から出発(nstart=1000)して、最も適したクラスタ分けを採用するように指定してある。

test.kmeans <- kmeans(test.data, centers=2, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster)

最初のグラフに色分けがついたはずで、これがクラスタである。 クラスタはデータのみから生成する層であり、これによる層別に技術的な背景はない。 クラスタ数を3, 4, 5と変えてみると、2の場合とは異なった分割が得られることが見て取れるはずである。

4枚のグラフをまとめて描くようにしてみた。

par(mfrow=c(2,2))
test.kmeans <- kmeans(test.data, centers=2, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=2")
test.kmeans <- kmeans(test.data, centers=3, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=3")
test.kmeans <- kmeans(test.data, centers=4, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=4")
test.kmeans <- kmeans(test.data, centers=5, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=5")
par(mfrow=c(1,1))

同じことを、目視でもほぼ2群に分けられそうなデータ(n=2000)でも行ってみる。

test.data <- rbind(rmvnorm(1000,mean=c(2.5,2.5),sigma=matrix(c(1,0.5,0.5,1),ncol=2)),
                   rmvnorm(1000,mean=c(-2.5,-2.5),sigma=matrix(c(1,0.5,0.5,1),ncol=2)))
plot(test.data)

そもそも別々に生成した2群のデータを結合しているので、k=2が一番自然なクラスタ分けを得る。 グラフを描かせるとやはりk=2の場合が最もらしいことが確認できる。 それでも3以上でもk-means法がクラスタを生成する。

par(mfrow=c(2,2))
test.kmeans <- kmeans(test.data, centers=2, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=2")
test.kmeans <- kmeans(test.data, centers=3, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=3")
test.kmeans <- kmeans(test.data, centers=4, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=4")
test.kmeans <- kmeans(test.data, centers=5, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=5")
par(mfrow=c(1,1))

戯れにk=20としてみると、2つの群それぞれを、細かく群分けする様子が見て取れる。

test.kmeans <- kmeans(test.data, centers=20, nstart=1000)
print(test.kmeans)
plot(test.data, col=test.kmeans$cluster, sub="k=20")

これはベクトル量子化と呼ばれる、多次元信号(画像など)の量子化法(デジタル信号への変換)と数理的には同等である。 また個々のクラスタごとに予測モデルを構築することは、学習理論における分割統治の考え方に合致している。

分割統治

この考え方をより進めると、下記のような手法に辿り着く。

  • 委員会機械 (Committee Machine)
  • アンサンブル学習 (Ensemble Learning)
    • ブースティング (Boosting)
    • バギング (Bagging)

k-means法による層別

k-means法は、数値変数でしか用いられないため、データは「tic.learn[, c(1:86)]」と数値変数のフィールドを指定してkmeans()関数を実行する。

tic.learn.kmeans <- kmeans(tic.learn[, c(1:86)], centers=2, nstart=1000)

k-means法の結果の「cluster」という変数を、tic.learnに追加する。

tic.learn$cluster <- tic.learn.kmeans$cluster

centers=に指定する値は、いろいろ変えてみるといい。

変数の値を直接指定した層別(V1の例)

例えばV1で層別する場合、まずその変数を集計して、何種類の値があるかを確認する。

table(tic.learn$V1)

V1は1から41の値を取ることが確認できたら、次のように、clusterという変数をtic.learn内に作り、まず0で埋める。 そして、V1の値ごとに層の値を指定するコードを書き、Rに実行させる。

tic.learn$cluster <- rep(0, dim(tic.learn)[1])
tic.learn$cluster[tic.learn$V1==1] <- 1
tic.learn$cluster[tic.learn$V1==2] <- 2
tic.learn$cluster[tic.learn$V1==3] <- 1
tic.learn$cluster[tic.learn$V1==4] <- 2
tic.learn$cluster[tic.learn$V1==5] <- 2
tic.learn$cluster[tic.learn$V1==6] <- 1
tic.learn$cluster[tic.learn$V1==7] <- 2
tic.learn$cluster[tic.learn$V1==8] <- 2
tic.learn$cluster[tic.learn$V1==9] <- 2
tic.learn$cluster[tic.learn$V1==10] <- 2
tic.learn$cluster[tic.learn$V1==11] <- 2
tic.learn$cluster[tic.learn$V1==12] <- 1
tic.learn$cluster[tic.learn$V1==13] <- 2
tic.learn$cluster[tic.learn$V1==14] <- 2
tic.learn$cluster[tic.learn$V1==15] <- 2
tic.learn$cluster[tic.learn$V1==16] <- 2
tic.learn$cluster[tic.learn$V1==17] <- 2
tic.learn$cluster[tic.learn$V1==18] <- 2
tic.learn$cluster[tic.learn$V1==19] <- 2
tic.learn$cluster[tic.learn$V1==20] <- 2
tic.learn$cluster[tic.learn$V1==21] <- 2
tic.learn$cluster[tic.learn$V1==22] <- 2
tic.learn$cluster[tic.learn$V1==23] <- 2
tic.learn$cluster[tic.learn$V1==24] <- 2
tic.learn$cluster[tic.learn$V1==25] <- 2
tic.learn$cluster[tic.learn$V1==26] <- 2
tic.learn$cluster[tic.learn$V1==27] <- 2
tic.learn$cluster[tic.learn$V1==28] <- 2
tic.learn$cluster[tic.learn$V1==29] <- 2
tic.learn$cluster[tic.learn$V1==30] <- 2
tic.learn$cluster[tic.learn$V1==31] <- 2
tic.learn$cluster[tic.learn$V1==32] <- 2
tic.learn$cluster[tic.learn$V1==33] <- 2
tic.learn$cluster[tic.learn$V1==34] <- 2
tic.learn$cluster[tic.learn$V1==35] <- 2
tic.learn$cluster[tic.learn$V1==36] <- 2
tic.learn$cluster[tic.learn$V1==37] <- 2
tic.learn$cluster[tic.learn$V1==38] <- 2
tic.learn$cluster[tic.learn$V1==39] <- 2
tic.learn$cluster[tic.learn$V1==40] <- 2
tic.learn$cluster[tic.learn$V1==41] <- 2

最後に、0の値が残っていないかを確認するために、集計する。

table(tic.learn$cluster)

変数の値を直接指定した層別(V2とV4の組み合わせの例)

例えばV2とV4の組み合わせで、下記のように層別することを考える。

V2/V4123456
1111133
2222233
3333333
4333333
5333333
6333333
7333333
8333333
9333333
10333333

この場合も、まずその変数を集計して、何種類の値があるかを確認する。

table(tic.learn$V2, tic.learn$V4)

すべての組み合わせを書くのは煩雑なので、最初にcluster変数は3で埋めてしまう。

tic.learn$cluster <- rep(3, dim(tic.learn)[1])

clusterが1になる箇所と2になる箇所だけ、書く。

tic.learn$cluster[tic.learn$V2==1 & tic.learn$V4==1] <- 1
tic.learn$cluster[tic.learn$V2==1 & tic.learn$V4==2] <- 1
tic.learn$cluster[tic.learn$V2==1 & tic.learn$V4==3] <- 1
tic.learn$cluster[tic.learn$V2==1 & tic.learn$V4==4] <- 1
tic.learn$cluster[tic.learn$V2==2 & tic.learn$V4==1] <- 2
tic.learn$cluster[tic.learn$V2==2 & tic.learn$V4==2] <- 2
tic.learn$cluster[tic.learn$V2==2 & tic.learn$V4==3] <- 2
tic.learn$cluster[tic.learn$V2==2 & tic.learn$V4==4] <- 2

最後に、確認のために、集計する。

table(tic.learn$cluster)

層別後の解析

層ごとに回帰分析を適用したり、決定木を適用したりする。