【Rによるデータサイエンス】多次元尺度法(つづき) 非軽量MDS
「【Rによるデータサイエンス】多次元尺度法」の続き。
前回は、多次元尺度法とは何かから初めて、計量MDSまで練習した。
今回は、計量MDSについてメモする。
非計量MDSは、距離の性質を満たさない類似性データも視野に入れ、計量MDSを発展させたもの。
非計量MDSでは、個体間の類似度あるいは距離をもとに配置すべくk次元における距離を推測する。
なんとなく言っていることは分かるけど、じゃあ「類似度」って何?「距離」って何?と思うわけ。何をもって、2つのものが類似していると見なすのか。
ネットで調べたら良い資料があった!同じ本を読んでいる。このシリーズ、かなり( ・∀・)イイ!!
いい資料があるから、ここで同じことをやっても仕方ないといえば仕方ないのはわかっているけど、同じことでもやった感を出して自分のモチベーションを高めることが1つの目的なので実際にやってみるw。
【非計量的MDSのケーススタディ】
◎isoMDS関数を使う
入力は距離行列と次元とする。
出力は、座標値($points)と最終のストレス($stress)。
使う前に距離の求め方の確認。
例えば、
という2次の正方行列を考える。
これに対してdist関数を使用すると、各行ベクトルのユークリッド距離を求めることができる。
> tmp [1] 1 3 5 12 > mat<-matrix(tmp, nrow=2,ncol=2,byrow=TRUE) > mat [,1] [,2] [1,] 1 3 [2,] 5 12 > distMat<-dist(mat) > distMat 1 2 9.848858
dist実行結果として、9.848858という値が求められたが、これは行ベクトル(1,3)と(5,12)のユークリッド距離に等しい。
> sqrt((5-1)^2+(12-3)^2) [1] 9.848858
ちなみに、dist関数のオプションを指定して、行列で表示すると次のようになる。
> distMat<-dist(mat,diag=FALSE,upper=TRUE) > distMat 1 2 1 9.848858 2 9.848858 > distMat<-dist(mat,diag=TRUE,upper=TRUE) > distMat 1 2 1 0.000000 9.848858 2 9.848858 0.000000
さて、このデータでisoMDSを使ってみる。意味は無いけど。。。
> isoMDS(distMat,k=2) 以下にエラー cmdscale(d, k) : 'k' must be in {1, 2, .. n - 1} > isoMDS(distMat,k=1) initial value 0.000000 final value 0.000000 converged $points [,1] [1,] -4.924429 [2,] 4.924429 $stress [1] 0
この結果の$pointsは座標値で、これはdistの2分の1の値。
で?そういった考察はもう少し慣れるまで、とりあえず据え置き。。。
◎sammon関数を使う
sammon関数はisoMDS関数と使い方は基本的に同じ。
ストレス($stress)は百分率ではない。
isoMDSもsammonも、初期に与えた座標を初期として、用いたストレス統計量が最小になるように計算を繰り返す。sammonでは100、isoMDSでは50が繰り返し数のデフォルト値となっているらしい。
> sammon(distMat, k=1) Initial stress : 0.00000 stress after 10 iters: 0.00000, magic = 0.500 $points [,1] [1,] -4.924429 [2,] 4.924429 $stress [1] 0 $call sammon(d = distMat, k = 1)
◎metaMDS関数を使う
パッケージmlbenchの中の関数mlbench.cornersを用いて、複数クラスの多次元(d)ガウシアン球面形の人工データを生成する。
> install.packages("mlbench") > library(mlbench) > install.packages("e1071") > set.seed(100) > p<-mlbench.corners(n=160) > lab=as.numeric(p$classes) > x.dist<-dist(p$x) > library(MASS) > par(mar=c(4.5,4.5,1,1), mfrow=c(2,2)) > plot(cmdscale(x.dist),pch=lab,col=lab) > plot(sammon(x.dist)$points,pch=lab,col=lab) Initial stress : 0.09075 stress after 10 iters: 0.07876, magic = 0.092 stress after 20 iters: 0.06195, magic = 0.500 stress after 30 iters: 0.06164, magic = 0.014 stress after 40 iters: 0.06157, magic = 0.500 > plot(isoMDS(x.dist)$points,pch=lab,col=lab) initial value 25.145154 iter 5 value 23.437529 iter 5 value 23.421336 iter 5 value 23.421336 final value 23.421336 converged > install.packages("vegan") > x.dist2<-as.matrix(x.dist) > plot(metaMDS(x.dist)$points,pch=lab,col=lab) > install.packages("vegan") > library(vegan) 要求されたパッケージ permute をロード中です 要求されたパッケージ lattice をロード中です This is vegan 2.0-10 > plot(metaMDS(x.dist2)$points,pch=lab,col=lab) Run 0 stress 0.2339668 Run 1 stress 0.4154951 Run 2 stress 0.242835 Run 3 stress 0.2465906 Run 4 stress 0.2406426 Run 5 stress 0.239285 Run 6 stress 0.239285 Run 7 stress 0.239285 Run 8 stress 0.236982 Run 9 stress 0.2339668 ... New best solution ... procrustes: rmse 1.280621e-05 max resid 6.089163e-05 *** Solution reached