Spark / MLlib の K-means を Java から利用してみる

はじめに

先日の Mahout Project からのアナウンス “Goodbye MapReduce” にもあるとおり、今後の大規模データ処理の基盤として Apache Spark がここ最近注目されています。

そんな今熱いプロダクトである Spark に関して、その上で動く機械学習ライブラリ MLlib の K-means 実装を わけあって Java から利用してみる機会があったので、その使い方や特性を簡単にまとめてみました。

MLlib の K-means 実装について

現時点 (バージョン 0.9.1) での K-means 実装について、簡単に説明します。

  • 距離計算は「ユークリッド距離」しか提供されていません。
    • KMeans#findClosest()MLUtils.fsuaredDistance() のあたりを読むと分かるかと思います。
    • Spark の JIRA を見ても、他の距離計算、 例えばコサイン距離についてのサポート依頼などの Issue は今のところ見当たらないので、 ユークリッド距離で不都合がある方はしばらく静観するのがよさそうです。
  • クラスタ中心の初期値の決め方は “random” (ランダム) と “k-means||” (K-means++ ライクな方法) の二通りがあります。
  • KMeans.train() を呼び出すことでクラスタリングをします。
    • 同メソッドはクラスタの中心を算出する機能のみを提供しているようです。
    • どのデータがどのクラスタにクラスタリングされたのかを把握するには、戻り値の KMeansModel より KMeansModel#predict() を呼び出して確認する必要があるようです。

利用方法

Spark / MLlib を実行する環境を用意する

まずは Spark / MLlib を利用したアプリケーションを開発・実行できる環境を作りましょう。

さてどうやって開発・実行環境を作るのか? Hadoop の場合のように、Spark や MLlib のパッケージをダウンロードする? いいえ、そのようなことは必要ありません。Maven / Gradle を使っていれば、 依存ライブラリに Spark / MLlib のパッケージを指定するだけで事は済みます。1

例えば Gradle をお使いの貴方なら、 build.gradle を以下のように記述すれば OK です。

とっても楽ちんですね!

MLlib の K-means 実装を利用する

続いて、MLlib の K-means を利用する Java アプリケーションを作成してみましょう。

例えば上記のように、みんな大好き アヤメデータ をクラスタリングするならば、

  1. JavaSparkContext オブジェクトを生成する
  2. JavaSparkContext#textFile() でアヤメデータを読み込んで、 JavaRDD#filter() & JavaRDD#map() で K-Means に与える形に適したデータ構造に変換する
  3. KMeans.train() でクラスタの中心を算出する
  4. KMeansModel#predict() を用いて、各データのクラスタリング結果を確認する

このような流れになるでしょう。

実際のアヤメデータを用いてクラスタリングした結果は以下になります。

データを標準化したわけではないので、特に virginica のクラスタリング結果がメタメタになってしまっていますが、 Spark と MLlib の K-means 実装の使い方の雰囲気を掴む上では、まずまずといったところでしょう。

まとめ

  • Spark / MLlib は要注目の大規模データ処理基盤&機械学習ライブラリ
  • MLlib の K-means はまだ開発途上なのかもしれないけど使えるよ!
  • Java で MLlib の K-means を使ったアプリケーションを開発するのは楽ちんだね!

  1. 実際には、行列計算をするような機械学習アルゴリズムを利用する場合に gfortran の外部ライブラリが必要になるようです ( Missing Libraries 参照 )。K-means については行列計算的な込み入ったことをしていないため、同ライブラリをインストールせずとも実行できてしまうようです。