Mahout で fuzzy k-means やってみた

はじめに

本エントリはデータが曖昧に分類されるのをグラフ描画して見てみたいという動機で、 適当なサンプルデータに対してファジークラスタリング手法の1つである fuzzy k-means 法を実施してみたという内容です。 fuzzy k-means は Hadoop 上で動く機械学習ライブラリ Apache Mahout により実行したので、そちらのコマンド等も記載します。

k-means もいいんだけど…

fuzzy k-means は知らないけど k-means なら知っている、という方もいらっしゃると思います。 k-means 法は最もオーソドックスなクラスタリング手法でアルゴリズムも理解しやすく、様々な BI ツールで実装されています。 また、実データで上手くクラスタリングできることが多く、いろいろなところで使われているのではないでしょうか。

しかし、k-means にもいくつか問題点があります1。 その中の一つが曖昧な特徴を持つデータの扱いです。

k-means のイメージ
k-means のイメージ

k-means ではキノコもタケノコも両方そこそこ好きな人がいたとしても、 必ずキノコ好きクラスタかタケノコ好きクラスタのどちらか、 少しでも距離が近い方に含まれてしまうことになります。 「キノコもタケノコも好き」は許されないわけです。

また、境界付近で似ているデータがあったとしても完全に別のクラスタに分けられてしまい、 それらのデータが近いという情報がなくなってしまう可能性があります。

このように一つのデータが必ず一つのクラスタに完全に所属するようなクラスタリング手法を クリスプ、またはハードなクラスタリング と言います。 (なので k-means の問題というよりはクリスプなクラスタリングの問題と言えます)

ファジーとは?

一方、それに対して一つのデータが複数のクラスタにある割合で所属することを許すようなクラスタリング手法を ファジー、またはソフトなクラスタリング と言います。 ファジー(fuzzy)とは「曖昧な、不明瞭な」という意味です。

fuzzy k-means のイメージ
fuzzy k-means のイメージ

曖昧さが許されていると「キノコもタケノコも好き」と言えるようになるわけです。 また、両クラスタの中間あたりで似ているデータが引き離されることもありません。

fuzzy k-means はファジーなクラスタリング手法の一つです。 詳しい説明はここではしません2が、k-means ライクな繰り返し更新で クラスタ重心とデータのメンバーシップ(各クラスタへの帰属度のようなもの)を 収束させて求めるという方法です。

以下でこの fuzzy k-means を実際に使ってみて k-means と比較してみます。

実験してみた

Apach Mahout では様々な機械学習のアルゴリズムが実装されており、クラスタリングも扱っています。 クラスタリングの中でもいくつかの種類のアルゴリズムが実装されていて、 k-means や fuzzy k-means もその中に含まれます。 ここでは Mahout の k-means, fuzzy k-means アルゴリズムでデータをクラスタリングしてみます。

データ準備

1000点のサンプルデータを作成しました。 3つの2次元正規分布に基づいてランダムに出力した点の集合です。

サンプルデータ
サンプルデータ

これらのデータを3つのクラスタにクラスタリングします。

クラスタリング実行

k-means

Mahout では org.apache.mahout.clustering.kmeans.KMeansDriver クラスで k-means を実行できます。 コマンド例を挙げます。

-k オプションの指定により、3つのクラスタに分割することを指定しています。 また、距離尺度にはユークリッド距離(いわゆる普通の距離)を使います。

fuzzy k-means

fuzzy k-means を実行するのは org.apache.mahout.clustering.fuzzykmeans.FuzzyKMeansDriver クラスです。

k-means との違いは、-m オプションと –emitMostLikely オプションの指定です。 -m はメンバーシップを計算するときに使われるパラメータで、通常は2で良さそうです。 ちなみにこれを1にすると k-means と同じ意味になります。3

–emitMostLikely オプションはデフォルトでは true になっています。 true の場合は、クラスタリング結果の出力時に各データが メンバーシップの最も高いクラスタに所属させられ、 クリスプクラスタリング的な結果表示となります。 今回はデータが曖昧に複数のクラスタに所属していることを見たいので false にします。

結果の色分け表示

クラスタ数を3にしたのには理由があります。 3であれば RGB の色の割合でクラスタへのメンバーシップを表現できるためです。 前述の2次元散布図上の各データを3つのクラスタへのメンバーシップにより色分けするのです。

今回は R により色分けのグラフ描画を行いました。 入力データとして、クラスタリングの結果を元に

のような CSV ファイルを用意しました。 x, y がデータの座標、c1, c2, c3 の列がクラスタ1~3へのメンバーシップを表します。 これを次のコードで描画させました。

クラスタリング結果のグラフ

まずは k-means の結果のグラフです。

散布図 k-means
散布図 k-means

当然ですが、くっきりと色が分かれています。 すべてのデータは必ずクラスタ1か2か3のどれか1つにメンバーシップ 1.0 で所属している状態です。

次に fuzzy k-means の結果です。

散布図 fuzzy k-means
散布図 fuzzy k-means

ご覧のようにモヤっとした曖昧な色使いになっています。 でも曖昧でいいんです、ファジーなので。 例えばピンク色と水色の中間あたりのデータは紫っぽい色になっており、 両方のクラスタの傾向をある割合で持っていることが分かりますね。 これならクラスタとクタスタの中間付近に位置するデータの特徴も表現できてます。 なるほどー。

実データに fuzzy k-means を使うに当たって

fuzzy k-means をどういう場合に使うといいかですが、 上記のように曖昧な特徴を持つデータを曖昧なまま扱いたい場合や、 クラスタ数をあまり増やせないがアウトサイダー的なデータに クラスタ重心を大きく引きずられたくない場合などが挙げられると思います。

利用の注意点としては、fuzzy k-means も初期値依存があり、 クラスタリングの結果が最適解から大きく離れてしまうことがあり得ます。 ファジーなクラスタの良し悪しを判断する基準4 も研究されているようなので、 できたクラスタはそういった基準で評価した方が良いでしょう。

まとめ

  • クリスプなクラスタリングではクラスタ境界付近のデータが不幸になる
  • ファジーなクラスタリングではクラスタ境界付近のデータも幸せ
  • Mahout でかんたん fuzzy k-means
  • R で色分け散布図を描いたよ
  • キノコの方が美味しいに決まってますよねJK