SOINNで手書き数字MNISTをクラスタリングしてみた
最近ちょいちょいニュースで見かけるようになったSOINN株式会社の機械学習アルゴリズムSOINNを試しました。
コードはこちらのtrain_mnist.pyです
SOINNとはSelf-Organizing Incremental Neural Network(自己増殖型ニューラルネットワーク)の略で、クラスタリング(データ群の中から、近しいもののグルーピングを行う)などに使われる機械学習アルゴリズムです。
ニューラルネットといっても、パーセプトロンのようにバックプロパゲーションで学ぶのではなく、k近傍法のように各データ点の距離を使って学習します。
特徴として
・教師なし学習
・古いクラスタは適宜破棄されるのでオンライン学習に強い
・計算量が少ない
・事前にネットワークの構造を決定しなくて良い
・ノイズ耐性
といった点が上げられるようです。学術的なところはこちら参照。
実験
今回の実装はここのsoinn_pythonに一部手を加えて、
パフォーマンス改善や学習モデルのシリアライズなどの機能追加を行いました。
soinn_pythonの実装や使い方はシンプルで、インスタンシエートした後はこんなふうに一次元データをドカドカ放り込んでると勝手に学習してくれます。
#ごくごく簡単にしたサンプル
soinn_i = Soinn() #SOINNのインスタンシエート
for data in dataset: #datasetはnumpy arrayのリスト
soinn.input_signal(data)
例えば、chainerで分類するよりはとっつきやすいと思います。
MNISTの手書き数字データを10000個分学習させて、各クラスタに所属すると判定されたデータの正解の数字を表示させてみます。
node[0]
true_values:[6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6]
node[1]
true_values:[5, 5, 5, 5, 8, 8, 5, 8, 3, 8, 5, 5, 5, 5, 5, 2, 6, 5, 5, 5, 5]
node[2]
true_values:[5, 8, 3, 5, 9, 4, 4, 4, 4, 4, 4, 4, 9, 4, 5, 8, 9, 8, 4, 9, 7, 4, 4, 4, 4, 4, 8, 4, 4, 8, 2]
node[3]
true_values:[8, 1, 8, 2, 8, 8, 3, 8, 8, 3, 5, 4, 8, 3, 2, 8, 8, 8, 2, 5, 2, 8, 5, 3, 6, 8, 5, 2, 6, 2]
node[4]
true_values:[8, 8, 5, 5, 3, 5, 5, 8, 8, 3, 5, 5, 5]
(以下長いので略)
入力データには0-9までの10種類の数字の画像があるんだよということは伝えていないのでクラスタは100強くらいできちゃいました。
node[0]なんかは6がいい感じでクラスタリングできていますし、node[2]は4が結構あつまっていて悪くない結果ですが、node[4]なんかは3と5と8がごっちゃになっています。
各ノードは中心座標を保持しているので、表示させてみます。
パーセプトロンで抽出した特徴量よりは代表的な値。ぼやけてるところはうまくいってない奴です。
一番 左上のnode[0]なんかはたしかに6の代表値を取得できています。
一方で右上はなんだか薄ぼんやりとしていて0と8の区別がついてなさそうなクラスタと言う感じ。
感想
パーセプトロンと違い、損失関数とか、活性化関数とか、学習係数の決定法みたいなパラメータは少なく気軽に使える感じです。
あと、各ノードは入力データと同じ次元で、その値はクラスタの代表値なので、学習結果はパーセプトロンよりわかりやすいです。
精度は今回の実装では前処理やSOINN複層化を行うなど色々と改善の余地があるので、なんとも言えません。
お手元にクラスタリング問題があるなら試してみてはいかがでしょうか。といっても特許化されているようなので、あくまで個人の範囲で。