Mathematicaによる教師なし機械学習 【ClusteringComponents】
Mathematica10では機械学習のための関数が多く導入されています.
機械学習は数値データのみならずテキストや画像データを入力として受けて,予測やクラスタリング,そしてパターン認識などの技術に応用されるアルゴリズムです.発展し続けるビッグデータ&データマイニング分野に役立ちます.
詳しいことは,[ドキュメントセンター] → [データの操作と解析] → [機械学習]からどうぞ.
今回は機械学習の中の教師なし学習で簡単なクラスタリングを行います.
①20コの2次元座標データを入力して散布図を描きます.以下のデータです.
data = {{0.12, 0.12}, {0.12, 0.38}, {0.25, 0.25}, {0.38, 0.12}, {0.38,
0.38}, {0.12, 0.62}, {0.12, 0.88}, {0.25, 0.75}, {0.38,
0.62}, {0.38, 0.88}, {0.62, 0.12}, {0.62, 0.38}, {0.75,
0.25}, {0.88, 0.12}, {0.88, 0.38}, {0.62, 0.62}, {0.62,
0.88}, {0.75, 0.75}, {0.88, 0.62}, {0.88, 0.88}};ListPlot[data]
次のような4つのクラスに分けてもらう,ということを目指します.
②データを加工していきます.ClusteringComponents関数で20コの座標を4つにクラス分けし,それぞれの座標に対するクラスのラベルを取得します.これによってlabelはlist変数としてクラスの番号1~4のどれかが入ります.
label = ClusteringComponents[data, 4, 1, Method -> "Optimize"]
>出力結果
label
{1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}
例えば出力結果ではlabelの第1要素から第5要素までが1になっているので,dataの第1座標から第5座標が"1"のクラスに分けられたことがわかります.
最後に"1"~"4"のクラスごとにデータを分けて,改めて散布図を描けばクラスごとに色分けされます.べた書きです.
class1 = {};
class2 = {};
class3 = {};
class4 = {};
For[i = 1, i <= Length[data], i++,
Switch[label[ [i]],
1, AppendTo[class1, data[ [i]]],
2, AppendTo[class2, data[ [i]]],
3, AppendTo[class3, data[ [i]]],
4, AppendTo[class4, data[ [i]]];]
]ListPlot[{class1, class2, class3, class4}]
(*data[ [i]]に半角スペースを入れているのは,はてなブログの自動変換機能を避けるためです.そうしないとこうなる,datai.Part関数を使ってもOK.)
無事に狙い通りのクラス分けをしてくれました.
[補足1]
クラスタ数を入力できるように書き直しました.
c = 4;(*クラスタ数*)
label = ClusteringComponents[data, c, 1, Method -> "Optimize"](*空のクラスをクラスタ数だけ生成*)
class = Table[{}, {i, 1, c}];
(*データをクラスに分ける*)
For[i = 1, i <= c, i++,
pos = Flatten[Position[label, i]];
For[j = 1, j <= Length[pos], j++,
AppendTo[classi, datapos[ [j]]]
]
]ListPlot[class]
[補足2]
label = ClusteringComponents[data, 4, 1, Method -> "KMeans"]
クラスタリングのメソッドをKMeans法に変えてみるとこのような結果に.
青色と黄色のクラスが予想通りにはなっていません.
KMeans法は,始めに乱数を用いて各データをランダムにクラスに割り当てをします.そして逐次,クラスを改善していく手法であり,乱数によってはこちらが期待した結果にならない場合があることが原因のようです.
ClusteringComponents[data2, 4, 1, Method -> "KMeans",
"RandomSeed" -> 10]
ランダムシードを色々変えてみるとうまくいきます.
ClusteringComponentsだけでクラスタリングに必要な作業がすべてできるので簡単です.
[追記1]
教師なしクラスタリングを一挙に行うFindClusters関数というのがありました.
class = FindClusters[data, 4]
{{{0.12, 0.12}, {0.12, 0.38}, {0.25, 0.25}, {0.38, 0.12}, {0.38,
0.38}}, {{0.12, 0.62}, {0.12, 0.88}, {0.25, 0.75}, {0.38,
0.62}, {0.38, 0.88}}, {{0.62, 0.12}, {0.62, 0.38}, {0.75,
0.25}, {0.88, 0.12}, {0.88, 0.38}}, {{0.62, 0.62}, {0.62,
0.88}, {0.75, 0.75}, {0.88, 0.62}, {0.88, 0.88}}}ListPlot[class]
・ClusteringComponents関数は与えられたデータをクラスに分けてそのラベルのリストを出力する
・FindClusters関数は与えられたデータをクラスごとにリストでまとめたものを出力する