[連載]フリーソフトによるデータ解析・マイニング第30回

Rと自己組織化マップ

 1.自己組織化マップとは

 自己組織化マップ(SOM: Self-Organizing Map)は、コホネン(T. Kohonen)[1]により提案された教師なしのニューラルネットワークアルゴリズムで、高次元データを2次元平面上へ非線形写像するデータ解析方法である。
 自己組織化マップは、入力層と出力層により構成された2層のニューラルネットワークである。出力層は競合層とも呼ばれている。
 今、入力層には分析対象となる個体jの特徴ベクトルを xj(xj1,xj2,…,xjp)、 出力層には 個のユニットがあるとする。図1の(a)で示すように、出力層における任意の1つのユニットは、入力層における特徴ベクトルのすべての変数とリンクしている。初期段階では乱数により各変数との間に図1の(b)に示すように重みmi(mi1,mi2,…,mip)が付けられている。

自己組織化マップの基本構造

図1 自己組織化マップの基本構造

SOMのアルゴリズム:
(1) 入力 と出力層におけるすべてのユニットの中から、最も類似しているユニットmcを探し出し、そのユニットを勝者とする。

SOMのアルゴリズムの式

(2) 勝者のユニットおよびその近傍のユニットの重みベクトルmiを更新する。更新は下記の式によって行う。

SOMのアルゴリズムの更新の式
SOMのアルゴリズムの更新の式2

 式の中のhci(t)は近傍関数で、ユニットcとその近傍のユニットiの近さによってxjの影響を調整する。式hci(t)の中のα(t)は学習率係数で、rcriはユニットciの2次元上の座標ベクトルである。σ2(t)はユニット cとニュニッとiの範囲を減少させる関数である。 α(t)は学習回数(あるいは時間)を変数とする単調減少関数であり、σ2(t)座標の分散である。学習回数を変数とする最も簡単な単調減少関数は単調減少関数である。このtは学習回数(あるいは時間、1、2、3、…、 T)、Tは事前に設定した学習の総回数である。

(3) すべての入力特徴ベクトル(j=1,2,…,m)に対して(1)〜(2)を繰り返す。

 SOMは上記のアルゴリズムにより、多次元の空間上の分類対象を2次元平面に射影する。SOMの結果は、出力層の画面に図示される。個体の出力画面のユニットは、格子状(正方形)、蜂の巣状(六辺形)などが提案されているが、蜂の巣状が多く用いられている。蜂の巣状というのは、文字どおり蜂の巣のように、正六角形のユニットを並べ、出力層の画面を構成する。出力層の画面は、上述のアルゴリズムにより、似ているもの同士を同じユニット、あるいはその近辺のユニットに配置する。各ユニットの特徴の図示は、星図、エラーバー付きの折れ線、色彩濃淡などソフトによって異なる。

2.パッケージclass

(1) 関数SOM

 パッケージclassの中には自己組織化マップ関数SOMがある。関数の書き式を次に示す。

SOM(data, grid = somgrid(), rlen = 10000, alpha, radii, init)

 引数dataは解析対象となるデータセットで、ユークリッド距離の計算が可能なデータマトリクスあるいはデータフレームである。
 引数gridでは、関数somgridの書き式に従って出力層の指定を行う。関数somgridを用いて事前に出力層の構造を設定した場合は、関数SOMで重複設定する必要はない。
 初心者としては、必ずしも指定しなくてもよい引数rlen、alpha、radii、initがある。引数rlenは学習回数で、デフォルトは10000回になっている。引数alphaは学習率係数で、学習回数に依存する単調減少関数である。引数radiiは学習回数に依存し、近傍領域の半径の更新をコントロールする。引数initでは初期の参考ベクトルを指定するが、指定しない場合はデータセットからランダムに用られる。
 関数SOMが返す主な結果は、somgridで設定した出力層のユニットの座標($pts)、各ユニットに配置されるデータの特徴ベクトル($codes)である。
 SOMを実行する前に出力層の設定を行う関数somgridの書き式を次に示す。

somgrid(xdim = 8, ydim = 6, topo = c("rectangular", "hexagonal"))

 関数somgridでは、ユニットの配置方法と出力層のサイズとなる列数(xdim)と行数(ydim)を指定する。ユニットの配置方法は引数topoに "rectangular"、 "hexagonal"の中から1つ選択して指定する。"rectangular"は矩形(ユニットを格子状に並る)、"hexagonal"は六辺形(偶数行のユニットを、ユニットの半分のサイズ分ずつ右にずらして並べる)に適した配置方法である。
 SOMの結果の要約は関数summary、結果の図示は関数plotを用いる。関数plotを用いて作成したグラフは、各ユニットに配属される個体の特徴ベクトルの星図である。

(2) データと解析

 使い慣れたデータirisのクラス情報を取り除いて用いることにする。関数SOMを用いるためには、まず関数somgridを用いて出力層のユニットを設定する。

> gr <- somgrid(topo = "hexagonal", xdim=5, ydim=4)
> out.som <- SOM(iris[,1:4], gr)
> out.som

関数somgridを用いた出力層のユニット設定結果

 このように結果は$pts、$xdim、$ydim、$topo、$codesの項目に分かれている。$ptsには指定した20(xdim=5、 ydim=4)の出力層の各ユニットの中心座標値、$xdim、 $ydim、$topoにはsomgridで指定した情報、$codesには各ユニットに配属される個体の特徴となるコード情報が格納される。このSOMの結果を関数plotで図を作成することができる。

> plot(out.som)

irisデータのSOM図1

図2 irisデータのSOM図1

 この図2は、out.som$ptsの座標に作成したout.som$codesの星グラフ(stars)である。この図では、各ユニットに配属される個体の特徴の情報が読み取れる。それぞれの星図は、最下段の左から右の方向にout.som$codesの行のデータを昇順に配置したものである。この星図の4つの軸(横右、縦上、横左、縦下)は反時計回りに、それぞれirisの4つの変数、ガク弁の長さ(Sepal.Length)、 ガク弁の幅(Sepal.Width)、 花弁の長さ(Petal.Length)、花弁の幅(Petal.Width)に対応している。
 個体を見やすく、SOMの出力画面に配置させるためには若干の手間が必要である。次のように関数symbolsを用いて、各ユニットを円で図示し(六辺形の代わり)、個体を配置することもできる。

> symbols(out.som$grid$pts[,1:2],circles=c(rep(0.5, 20)),inches = FALSE,add = TRUE)

 個体がどのユニットに配置されるかは、解析したSOMのコードを基準とし判別分析を行わなければならない。ここでは関数knnを用いて判別を行うことにする。

> haizoku<-as.numeric(knn(out.som$codes,iris[,1:4], 1:20))

 上記のコマンドで得られてる結果haizokuには、150個の個体がそれぞれどのユニットに配属されるかに関してknn分類法を用いて判別した結果が格納されている。このデータを直接ユニットに配置すればよいが、値がユニットの番号になっているので、同じユニットに配属される点がすべて重なってしまう。そこで各点の座標値に小さい正規乱数を加え、同じユニットに配属される個体が重ならないように調整する。

> ransu<- cbind(rnorm(nrow(iris),0, 0.15), rnorm(nrow(iris),0, 0.15))
> out.new<-out.som$grid$pts[haizoku,] +ransu
> points(out.new)

 上記の操作で、図3(a)が作成される。 次のように個体が所属するクラス情報を用いると図3(b)のようにSOMの出力結果の理解と解釈を助ける。クラス情報がない場合は個体の番号を用いることもできる。

> points(out.new,col=c(2:4)[unclass(iris[,5])],pch=c(1:3)[unclass(iris[,5])])

irisデータのSOM図2

図3 irisデータのSOM図2

3.パッケージsom

(1) 関数som

 パッケージsomは、自己組織化マップの専用パッケージで、CRANミラーサイトからダウンロードできる。自己組織化マップのメイン関数はsomである。その書き式を次に示す。このsomは小文字である。

som(data, xdim, ydim,…)

 関数somには幾つかの引数が用意されているが、ここでは必ず指定しなければならない引数のみを示している。引数dataは、解析の対象となるデータセットである。データによっては、パッケージに用意されている標準化関数normalize を用いて標準化した方がよい。引数xdim、ydimは出力画面のユニットの列数と行数である。

(2) データと解析

 前節と同じくデータirisを用いた関数somの使用例を示す。

> library(som)
> iris.n <- normalize(iris[,1:4])
> iris.som<-som(iris.n, xdim=5, ydim=4)
> plot(iris.som)

 関数plotのグラフは、エラーバー付きの折れ線でユニットの特徴ベクトルを図示する。各個体をユニットへプロットするためには、前節と類似の手順を踏む。ただし、関数somは、各個体が属するユニット番号を$visualに記録しているので、前節のように個体の所属を判別するために判別関数を用いる必要がない。実行コマンドおよびその結果を次に示す(図4)。

> ransu<-cbind(rnorm(nrow(iris),0, 0.13),rnorm(nrow(iris), 0, 0.13))
> out.new<-iris.som$visual[,1:2]+0.5+ransu
> points(out.new[,1:2],col=c(2:4)[unclass(iris [,5])],pch=c(1:3)[unclass(iris[,5])])

関数somによる図示

図4 関数somによる図示

 次のようにout.new[,1:2]データを用いてユニットの特徴を表示しない散布図を作成することもできる。

>plot (out.new[,1:2],col=c(2:4)[unclass(iris [,5])],pch=c(1:3)[unclass(iris[,5])])

irisのsom散布図(xdim=5、 ydim=4)

図5 irisのsom散布図(xdim=5、 ydim=4)

 出力層のユニットの数は、結果を大きく左右する。次にirisデータについてユニット数を1000個(xdim=100、 ydim=100)にした結果を示す。

> iris.som2<-som(iris.n, xdim=100, ydim=100)
> out.new2<-iris.som2$visual[,1:2]+0.5+ransu
> plot(out.new2[,1:2],pch=c(1:3)[unclass(iris[,5])],col=c(2:4)[unclass(iris[,5])])

irisのsom散布図(xdim=100, ydim=100)

図6 irisのsom散布図(xdim=100, ydim=100)

 図5と図6を比較すると、図6における個体がより明確に3種類ごとに分類されていることが分かる。

4.パッケージkohonen

パッケージkohonenのは自己組織化マップの専用パッケージである. このパッケージには教師データありの方法と教師データなしの自己組織化マップに関する関数が用意されている. 教師データなしの自己組織化マップの関数はsomである.関数の書き式を次に示す.

som(data, grid=somgrid(), rlen = 100,…)

 ここでは指定が必要であるもっとも基本的な引数のみを示している.引数dataは解析対象となるデータセットで,ユークリッド距離の計算が可能なデータマトリクスあるいはデータフレームである.引数gridでは出力層の構造を指定するが,関数somgridを用いる.関数somgridの書き式を次に示す.

somgrid(xdim = 8, ydim = 6, topo = c("rectangular", "hexagonal"))

関数somgridでは,出力層のサイズとなる列数(xdim)と行数(ydim),ユニットの配列の方法(topo)を指定する.ユニットの配置方法は引数topoに "rectangular", と"hexagonal"の中の1つを用いる."rectangular"はユニットを格子状に並べ,"hexagonal"は蜂の巣状(六辺形)にユニットを並べる. somの結果のリストは関数summary,結果の図示は関数plotを用いる.関数plotにはグラフ種類を指定する引数がある. ここでは使い慣れたデータirisのクラス情報をのぞいて用いることにする.関数somを用いるためには,まず関数somgridを用いて出力層のユニットを設定することが必要である. ここでは10列7行のhexagonal配置法を用いることにする.

> gr<-somgrid(topo="hexagonal",xdim=10,ydim=7)
> iris.som<-som(as.matrix(iris[,1:4]),gr,rlen=200)
> summary(iris.som)
som map of size 10x7 with a hexagonal topology.
Training data included; dimension is 150 by 4
Mean distance to the closest unit in the map: 0.04425241

 関数somの実行結果iris.somには,somgridで設定した10×7個のユニットの座標値および出力画面の設定に関する情報が$gridに,ユニットの座標値は$grid$ptsに格納されている.各ユニットに配置される個体の特徴となるコードは$codesに,用いたデータのそれぞれの個体がどのユニットに配属されるかに関する情報は$classif に格納される.
 自己組織化マップの主な目的は,高次元のデータを2次元平面上に非線形的に射影し,データのパターン分類を行うことである。パッケージkohonenでは,関数plotを用いて関数somの結果を図示することができる。次に関数plotの書き式を示す。

plot.kohonen(x, type = "",labels=NULL, pchs=NULL, ...)

 引数typeには,いくつかの図示種類が用意されているが、ここでは2種類(codes, mapping)について紹介する.引数type = "codes"にすると,用いたデータについて設定した出力画面のユニット特徴の星グラフを表示し,type = "mapping"にするとそれぞれの個体がユニットにプロットされる.次にコマンドの例と結果を図13.2に示す.コードマップと個体のマップを対照することでパターンの特徴を分析することができる.

> plot(iris.som, type="codes") #コードマップ
> lab.cod<- as.numeric(iris[,5])
> plot(iris.som, type="mapping",labels=lab.cod, col=lab.cod)

irisの変数のsomのマップ
(a)
irisの個体のsomマップ
(b)
図7 SOMのコードと個体のマップ

 コードマップは,各ユニットに配属される個体の特徴の星グラフである.図7(a)の各ユニットの星グラフの4つの軸は反時計回り方向(横右,縦上,横左,縦下)にirisの4つの変数,ガク弁の長さ(Sepal.Length), ガク弁の幅(Sepal.Widt), 花弁の長さ(Petal.Length),花弁の幅(Petal.Width)に対応する.

5.その他

 パッケージklaRの中の作図関数shardsplotを用いると次のような図が作成される。

> library(klaR)
> iris.som3 <- som(iris[,1:4], xdim = 14, ydim = 6)
> library(klaR); opar<- par(xpd = NA)
> shardsplot(iris.som3, data.or = iris,label = TRUE)
> legend(3.5,14.3, col = rainbow(3), xjust = 0.5, yjust = 0,legend = levels(iris[, 5]), pch = 16, horiz = TRUE)
> par(opar)

関数shardsplotのSOM図

図7 関数shardsplotのSOM図

 SOMは学習データを持たないニューラルネットワークのデータ解析方法である。近年SOMを扱う本も増えている。初心者には [2]、[3]、より深く追求したい方には[1]、応用に関しては[4]が参考になるであろう。参考文献[4]では、事業戦略管理・マーケティング、経済分析、建設分野、日本語意味マップ、顔画像認証、データベース/情報検索分野、健康診断などの分野でのSOMの応用事例が紹介されている。芥川龍之介、菊池寛、夏目漱石、島崎藤村の作品における助詞を用いたSOMによる文体分析の研究事例としては[5]がある。

 参考文献
 [1] T.コホネン著, 徳高 平蔵・その他共訳(2005):自己組織化マップ、シュプリンガー・フェアラーク東京
 [2] 豊田 秀樹(2000):金鉱を掘り当てる統計学―データマイニング入門、講談社
 [3] 山口 和範、高橋 淳一、竹内 光悦(2004):図解入門 よくわかる多変量解析の基本と仕組み―巨大データベースの分析手法入門,
   秀和システム
 [4] 徳高 平蔵、山川 烈、藤村 喜久郎(2002): 自己組織化マップ応用事例集―SOMによる可視化情報処理、海文堂出版
 [5] 金明哲(2003):自己組織化マップと助詞分布を用いた書き手の同定及びその特徴分析、計量国語学、23巻8号、369-386.