Rでk平均法を使う

| Topic path: Top / バイオ・データ・マイニング / Rでk平均法を使う

*はじめに [#ye1804ba]
『Rによるバイオインフォマティクスデータ解析』の7.9.1節「[math]k[/math]-menas」を参考にして,[math]k[/math]平均法を行います.

#html{{
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?t=tohgoroh-22&o=9&p=8&l=as1&asins=4320057082&ref=tf_til&fc1=444B4C&IS2=1&lt1=_blank&m=amazon&lc1=444B4C&bc1=FFFFFF&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="https://rcm-fe.amazon-adsystem.com/e/cm?ref=tf_til&t=tohgorohmatsu-22&m=amazon&o=9&p=8&l=as1&IS2=1&detail=1&asins=4320057082&linkId=f6db5311dcfd9a82f5dee20859d39574&bc1=ffffff&lt1=_blank&fc1=444b4c&lc1=444b4c&bg1=ffffff&f=ifr"></iframe>
}}


*準備 [#zf92ac9d]
Rのインストールについては,次のページを見てください.
-[[MacでRを使う>機械学習/MacでRを使う]]
-[[WindowsでRを使う>機械学習/WindowsでRを使う]]

まず,[math](1, 1)[/math] を中心として,[math]x[/math]座標と[math]y[/math]座標をそれぞれ分散0.3として正規分布で100個の点を生成し,これをc1とします.
次に,[math](-1 -1)[/math] を中心として,同じように分散0.3の正規分布で100個の点を生成し,これをc2とします.
c1とc2をまとめて,dataとし,これをプロットします.
#geshi(rsplus){{
> set.seed(123)
> x1 = rnorm(100, mean=1, sd=0.3)
> y1 = rnorm(100, mean=1, sd=0.3)
> c1 <- cbind(x1, y1)
> x2 = rnorm(100, mean=-1, sd=0.3)
> y2 = rnorm(100, mean=-1, sd=0.3)
> c2 <- cbind(x2, y2)
> data1 <- rbind(c1, c2)
> colnames(data1) <- c("x", "y")
> plot(data1)
set.seed(123)
x1 = rnorm(100, mean=1, sd=0.3)
y1 = rnorm(100, mean=1, sd=0.3)
c1 <- cbind(x1, y1)
x2 = rnorm(100, mean=-1, sd=0.3)
y2 = rnorm(100, mean=-1, sd=0.3)
c2 <- cbind(x2, y2)
data1 <- rbind(c1, c2)
colnames(data1) <- c("x", "y")
plot(data1)
}}
#ref(kmeans_data1.png,nolink,50%)


*クラスタリング [#j0ec994d]
クラスタリングは,分類対象のデータ集合をいくつかのグループに分割するものです.
分割された部分データ集合を''クラスター''といいます.

クラスタリングの手法には,主に''階層的アプローチ''と''分割最適化アプローチ''があります.
ここでは,後者の分割最適化アプローチの一つである''[math]k[/math]平均法''を行います.


*k平均法 [#fbb389e4]
[math]k[/math]平均法([math]k[/math]-means)は,データの集合を [math]k[/math] 個のクラスターに分割します.
クラスター数 [math]k[/math] を最初に決めておかなければなりません.

[math]k[/math]平均法は,次の手順で行います.
+各データ [math]\bf{x}_1, \dots, \bf{x}_n[/math] に対して,ランダムにクラスター [math]c_1, \dots, c_k[/math] を割り当てる.
+クラスター [math]c_1, \dots, c_k[/math] ごとに,クラスター [math]c_i[/math] に割り当てられたデータの平均を求め,それを [math]c_i[/math] の中心とする.
+各データ [math]\bf{x}_1, \dots, \bf{x}_n[/math] に対して,データ [math]\bf{x}_i[/math] と各クラスター [math]c_1, \dots, c_k[/math] の中心との距離を求め,[math]\bf{x}_i[/math] を最も中心が近いクラスターに割り当て直す.
+全てのデータについてクラスターの割り当てが変更されなかったら終了する.そうでない場合は,ステップ2へ戻る.

Rで[math]k[/math]平均法を用いるには,''kmeans''関数を用います.
kmeans関数の引数には,分割するデータとクラスター数 [math]k[/math] を与えます.
#geshi(rsplus){{
> data1.kmeans <- kmeans(data1, 2)
data1.kmeans <- kmeans(data1, 2)
}}

作成されたオブジェクトの''cluster''変数には割り当てられたクラスター番号が,''center''変数には各クラスターの中心座標が格納されます.
#geshi(rsplus){{
> data1.kmeans$cluster
data1.kmeans$cluster
}}
#geshi(rsplus)){{
  [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 [51] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 [76] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[101] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[126] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[151] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[176] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
> data1.kmeans$center
}}
#geshi(rsplus){{
data1.kmeans$center
}}
#geshi(rsplus){{
           x         y
1 -0.9638605 -1.010867
2  1.0271218  0.967736
}}

結果をプロットすると次のようになります.
#geshi(rsplus){{
> plot(data1, col=data1.kmeans$cluster, pch=data1.kmeans$cluster)
> points(data1.kmeans$centers, col=1:2, pch=8, cex=2)
plot(data1, col=data1.kmeans$cluster, pch=data1.kmeans$cluster)
points(data1.kmeans$centers, col=1:2, pch=8, cex=2)
}}
#ref(kmeans1.png,nolink,50%)

[math]k[/math]平均法の結果は,最初に行われるランダムな割り当てに依存します.
''nstartオプション''の値(デフォルトは1)を2以上にすると,nstart回実行して最もよい結果を返します.
#geshi(rsplus){{
> data1.kmeans <- kmeans(data1, 2, nstart=10)
}}

また,[math]k[/math]平均法を実行するたびに結果が変わるので,同じ結果を得るには,''set.seed関数''を用いて乱数のシードをセットしてから実行します.
#geshi(rsplus){{
> set.seed(0)
> data1.kmeans <- kmeans(data1, 2)
set.seed(0)
data1.kmeans <- kmeans(data1, 2)
}}


*k平均法が苦手な問題 [#a4275b11]
今度は,もう少し分散を大きくし,かつ,データの個数を同じにしないでやってみます.
#geshi(rsplus){{
> set.seed(123)
> x1 = rnorm(100, mean=1, sd=1)
> y1 = rnorm(100, mean=1, sd=1)
> c1 <- cbind(x1, y1)
> x2 = rnorm(10, mean=-1, sd=1)
> y2 = rnorm(10, mean=-1, sd=1)
> c2 <- cbind(x2, y2)
> data2 <- rbind(c1, c2)
> plot(data2)
set.seed(123)
x1 = rnorm(100, mean=1, sd=1)
y1 = rnorm(100, mean=1, sd=1)
c1 <- cbind(x1, y1)
x2 = rnorm(10, mean=-1, sd=1)
y2 = rnorm(10, mean=-1, sd=1)
c2 <- cbind(x2, y2)
data2 <- rbind(c1, c2)
plot(data2)
}}
#ref(kmeans_data2.png,nolink,50%)
#geshi(rsplus){{
> data2.kmeans <- kmeans(data2, 2)
> plot(data2, col=data2.kmeans$cluster, pch=data2.kmeans$cluster)
> points(data2.kmeans$centers, col=1:2, pch=8, cex=2)
data2.kmeans <- kmeans(data2, 2)
plot(data2, col=data2.kmeans$cluster, pch=data2.kmeans$cluster)
points(data2.kmeans$centers, col=1:2, pch=8, cex=2)
}}
#ref(kmeans2.png,nolink,50%)
すると,データを生成するときに使用した中心 [math](1, 1), (-1, -1)[/math] よりもずれてしまいました.
[math]k[/math]平均法はこういう問題はうまくクラスタリングできません.


*irisデータセット [#ubb56800]

''irisデータセット''でもやってみましょう.

#geshi(rsplus){{
> data(iris)
data(iris)
}}

このデータセットは,アヤメの種類(Species)をがく片の長さ(Sepal.Length),幅(Lepal.Width),花びらの長さ(Petal.Length),幅(Petal.Width)によって分類する問題です.
長さと幅は連続値,種類はsetosa, versicolor, virginicaのいずれかをとる離散値です.

このデータセットには,setosa, versicolor, virginicaという3種類のアヤメについて,それぞれ50個ずつ,合計150個のデータが含まれています.
ランダムに10個のデータを選択して,見てみましょう.
#geshi(rsplus){{
> iris[sort(sample(1:150,10)),]
iris[sort(sample(1:150,10)),]
}}
#geshi(rsplus){{
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
4            4.6         3.1          1.5         0.2     setosa
22           5.1         3.7          1.5         0.4     setosa
65           5.6         2.9          3.6         1.3 versicolor
97           5.7         2.9          4.2         1.3 versicolor
100          5.7         2.8          4.1         1.3 versicolor
108          7.3         2.9          6.3         1.8  virginica
116          6.4         3.2          5.3         2.3  virginica
122          5.6         2.8          4.9         2.0  virginica
136          7.7         3.0          6.1         2.3  virginica
146          6.7         3.0          5.2         2.3  virginica
}}

ここでは,Speciesを除いた1列目から4列目だけを取り出して使います.
#geshi(rsplus){{
> iris.nolabel <- iris[1:4]
iris.nolabel <- iris[1:4]
}}

4次元データですが,このうちのSepal.LengthとPetal.Lengthだけを取り出して表示します.
データを表示するときの色''col''と形''pch''にはirisのSpeciesを''as.numeric関数''で数値化したものを指定します.
#geshi(rsplus){{
> plot(iris.nolabel$Sepal.Length, iris.nolabel$Petal.Length,
+ col=as.numeric(iris$Species), pch=as.numeric(iris$Species))
plot(iris.nolabel$Sepal.Length, iris.nolabel$Petal.Length,
    col=as.numeric(iris$Species), pch=as.numeric(iris$Species))
}}
#ref(iris.png,nolink,40%)

カテゴリーの数は3だとわかっていますので,[math]k=3[/math] として[math]k[/math]平均法によるクラスタリングを行います.
#geshi(rsplus){{
> iris.nolabel.kmeans <- kmeans(iris.nolabel, 3) 
iris.nolabel.kmeans <- kmeans(iris.nolabel, 3) 
}}

今度は色と形をクラスタリングによって得られたクラスター番号によって指定して表示します.
#geshi(rsplus){{
> plot(iris.nolabel$Sepal.Length, iris.nolabel$Petal.Length,
+ col=iris.nolabel.kmeans$cluster, pch=iris.nolabel.kmeans$cluster)
plot(iris.nolabel$Sepal.Length, iris.nolabel$Petal.Length,
    col=iris.nolabel.kmeans$cluster, pch=iris.nolabel.kmeans$cluster)
}}
#ref(iris_kmeans.png,nolink,40%)


*まとめ [#k4ec4f3a]

[math]k[/math]平均法は,[math]k[/math] 個のクラスターへの割り当てとクラスターの中心の計算を繰り返す,分割最適化アプローチのクラスタリング手法です.

[math]k[/math]平均法では,クラスターの数 [math]k[/math] をユーザーが事前に与えなければなりません.
したがって,いくつかの [math]k[/math] を試して最もうまくいったものを採用するという方法をとることがあります.

[math]k[/math]平均法の結果は,最初に行われるランダムな割り当てに依存します.
nstartオプションで複数回実行して最も良い結果を採用するか,乱数のシードを変えて実行すると,よりよい結果が得られる可能性があります.

また,[math]k[/math]平均法ではうまくいかない問題があることがよく知られています.
そのようなときは,スペクトラル・クラスタリングを用いるとうまくいくかもしれません.




*参考文献 [#q4967b57]

#html{{
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?t=tohgoroh-22&o=9&p=8&l=as1&asins=4320057082&ref=tf_til&fc1=444B4C&IS2=1&lt1=_blank&m=amazon&lc1=444B4C&bc1=FFFFFF&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?t=tohgoroh-22&o=9&p=8&l=as1&asins=4274067033&ref=qf_sp_asin_til&fc1=444B4C&IS2=1&lt1=_blank&m=amazon&lc1=444B4C&bc1=FFFFFF&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="https://rcm-fe.amazon-adsystem.com/e/cm?ref=tf_til&t=tohgorohmatsu-22&m=amazon&o=9&p=8&l=as1&IS2=1&detail=1&asins=4320057082&linkId=f6db5311dcfd9a82f5dee20859d39574&bc1=ffffff&lt1=_blank&fc1=444b4c&lc1=444b4c&bg1=ffffff&f=ifr"></iframe>
}}

-[[クラスタリングとは(クラスター分析とは):http://www.kamishima.net/jp/clustering/]] - 神嶌敏弘さん
-[[Rでスペクトラル・クラスタリングを使う>バイオ・データ・マイニング/Rでスペクトラル・クラスタリングを使う]] - とうごろうぃき
トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS