Mahoutで体感する機械学習の実践

第5回 K-MeansとCanopyクラスタリングでセグメンテーション分析を行う

この記事を読むのに必要な時間:およそ 4.5 分

入力データを用意する

サンプルデータを確認する

前回はセグメンテーション分析の理論編として,セグメンテーション分析と代表的なクラスタリングアルゴリズムであるK-MeansとCanopyクラスタリングについて解説しました。

今回は,実践編として,K-MeansとCanopyクラスタリングによるセグメンテーション分析をMahoutを用いて実際に行います。

なお,本連載の3回目同様,Mahoutのバージョンは現時点の最新版である0.7を対象とします。

今回利用するサンプルデータは,ARFF形式※1で顧客のRFMが記載されています。@DATA以降が,実際のデータです。

  • サンプルデータ
  • ※1)
    ARFF形式は,おもにWEKAで利用されるファイルフォーマットで,CSV形式にカラム名やデータ型などの情報を付加することができます。くわしい情報はワイカオ大学のページに記載されています。

今回のデータは,以下のような構造になっています。

  • 1行が顧客1人のデータを意味する
  • カンマ区切りで,左から「R(最終購買日)」「F(購買頻度)」「M(購入金額)」を表す
(省略)

@DATA
顧客1の最終購買日, 顧客1の購買頻度, 顧客1の購買金額
顧客2の最終購買日, 顧客2の購買頻度, 顧客2の購買金額
顧客3の最終購買日, 顧客3の購買頻度, 顧客3の購買金額

(省略)

今回のデータはR,F,Mの3つとも,本来の値を1から100の範囲に収まるように正規化しています。

ARFF形式をVector形式へ変換する

MahoutでK-Meansを実行する場合,入力ファイルはMahoutのVector形式である必要があります。

サンプルデータはARFF形式なので,下記のようにMahoutのarff.vectorコマンドでVector形式に変換します。

hadoop fs -put gihyo-mahout-kmeans-sample.arff .
mahout arff.vector --input gihyo-mahout-kmeans-sample.arff --output gihyo-mahout-kmeans-sample.vector --dictOut gihyo-mahout-kmeans-sample.dict

arff.vectorコマンドの各パラメータは,それぞれ以下を意味します。

  • --input ⇒ 入力ファイル
  • --output ⇒ 出力ファイル
  • --dictOut ⇒ dictionaryファイルの出力先

生成されたVectorファイルは,以下のように,mahoutのseqdumperコマンドや,vectordumpコマンドで,中身を確認することができます。

mahout seqdumper -i gihyo-mahout-kmeans-sample.vector 
mahout vectordump -i gihyo-mahout-kmeans-sample.vector

なお,CSVファイルを入力ファイルに用いたい場合は,いったんCSVファイルをARFF形式に変換して,上記手順を踏んでください。Mahout自体には,CSV形式をVector形式に変換する機能は用意されていないためです。

K-Meansをコマンドラインから実行する

kmeansコマンドを実行する

それでは,サンプルデータを用いて実際にK-Meansを実行してみましょう。

MahoutのK-Means実装は,以下のようにkmeansコマンドで実行します。

mahout kmeans

kmeansコマンドのおもなパラメータとして以下があります。

  • --input(-i) ⇒ 入力元
  • --output(-o) ⇒ 出力先
  • --distanceMeasure(-dm) ⇒ 距離計算方法の指定。デフォルト値はユークリッド平方距離
  • --numCluster(-n) ⇒ 生成するクラスタの数
  • --clusters(-c) ⇒ 初期クラスタ
  • --convergenceDelta ⇒ 収束閾値。クラスタ重心の1回の移動距離が閾値以下になった場合,計算を終了する
  • --maxIter ⇒ クラスタ重心点の最大計算回数
  • --overwrite(-ow) ⇒ 出力先にファイルがすでにあった場合に上書きを行う
  • --clustering ⇒ clusteredPointsの出力。clusteredPointsには,各要素がどのクラスタに属するかが記載されている
  • --method ⇒ mapreduceを指定した場合はMapReduceによる計算,sequentialを指定した場合はローカルマシンによる計算を行う。デフォルト値はmapreduce

今回は,以下の設定で実行してみます。

  • クラスタ重心点の最大計算回数 ⇒ 50回
  • 生成するクラスタの数 ⇒ 10個
  • クラスタの初期座標 ⇒ ランダム
  • clusteredPointsの出力 ⇒ 有り
  • 距離計算方法 ⇒ ユークリッド距離

以下のコマンドを入力してみてください。

mahout kmeans --input gihyo-mahout-kmeans-sample.vector --output gihyo-kmeans-output --maxIter 50 --numClusters 10 --clusters gihyo-kmeans-null-cluster --clustering -dm org.apache.mahout.common.distance.EuclideanDistanceMeasure

今回は出力先にhdfsを利用しているので,出力結果のファイル構成を確認するには以下のように実行します。

hadoop fs -lsr gihyo-kmeans-output

以下のような出力が表示されたでしょうか?

-rw-r--r--   1 yamakatu supergroup        194 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/_policy
drwxr-xr-x   - yamakatu supergroup          0 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusteredPoints
-rw-r--r--   1 yamakatu supergroup      46560 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusteredPoints/part-m-0
drwxr-xr-x   - yamakatu supergroup          0 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-0
-rw-r--r--   1 yamakatu supergroup        194 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-0/_policy
-rw-r--r--   1 yamakatu supergroup        359 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-0/part-00000

(省略)

-rw-r--r--   1 yamakatu supergroup        359 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-0/part-00009

(省略)

drwxr-xr-x   - yamakatu supergroup          0 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-20-final
-rw-r--r--   1 yamakatu supergroup        194 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-20-final/_policy
-rw-r--r--   1 yamakatu supergroup        332 2013-06-01 11:41 /user/yamakatu/gihyo-kmeans-output/clusters-20-final/part-00000

(省略)

MahoutのKmaensコマンドは,クラスタの計算回数ごとにclusters-xフォルダを作成します。clusters-0フォルダは初期状態,clusters-1フォルダは1回目の計算終了後の結果を含みます。

最終結果には,postfixとして,finalの文字列が付加されます。 上記出力では,clusters-20-finalが最終結果なので,20回クラスタの計算が行われたことがわかります※2)。

--clusteringパラメータにより生成されるgihyo-kmeans-output/clusteredPointsフォルダには,各要素がどのクラスタに属しているかの情報が保存されています。

※2)
今回はクラスタの初期座標をランダムで実行しているため,必ずしも20回で終了するとは限りません。

K-Meansの実行結果を確認する

次に,実際に生成されたクラスタを確認してみましょう。

生成されたクラスタは,以下のようにclusterdumpコマンドを利用することで出力できます。

mahout clusterdump

clusterdumpコマンドのおもなパラメータとして,以下があります。

  • --input(-i) ⇒ 入力元
  • --output(-o) ⇒ 出力先
  • --outputFormat(-of) ⇒ 出力フォーマット。デフォルトのTEXT以外にCSV,GRAPH_ML(GraphML形式)を指定可能
  • --pointsDir(-p) ⇒ clusteredPointsの指定
  • --dictionary(-d) ⇒ dictionaryファイル指定

今回は,先ほど実行したkmeansの出力結果のうち,最終結果を確認してみましょう。以下のコマンドを入力してみてください。

mahout clusterdump --input gihyo-kmeans-output/clusters-20-final --output ~/gihyo-kmeans-dump.text

次に,clusterdumpで出力したファイルの中身を確認してみます。

cat ~/gihyo-kmeans-dump.text
VL-959{n=103 c=[22.165, 82.806, 27.854] r=[12.907, 11.927, 15.057]}
VL-969{n=98 c=[73.776, 85.929, 26.561] r=[14.760, 9.117, 15.672]}

(省略)

ここで表示される出力結果は,以下の意味になります。

  • VL-x ⇒ クラスタ
  • n ⇒ そのクラスタに属する要素の数
  • c ⇒ そのクラスタの重心
  • r ⇒ そのクラスタの半径

クラスタ数を10で実行していますので,VLで始まる行が10行生成されているはずです。

各クラスタに属する要素を同時に出力したい場合は,以下のようにclusteredPointsを指定します。

mahout clusterdump --input gihyo-kmeans-output/clusters-20-final --output ~/gihyo-kmeans-dump.text -p gihyo-kmeans-output/clusteredPoints

clusteredPointsの内容だけを確認したい場合は,Mahoutのseqdumperコマンドで確認することができます。

mahout seqdumper --input gihyo-kmeans-output/clusteredPoints

著者プロフィール

やまかつ(山下勝司)

開発/インフラ/統計,機械学習/プロジェクトマネージメントをこなす器用貧乏。最近はビッグデータ,Hadoop,機械学習あたりに夢中。

株式会社マーズフラッグ 先端研究開発本部所属。

趣味は妻と子供と過ごすこと。

Twitter:@yamakatu
Facebook:http://www.facebook.com/katsushi.yamashita.9

コメント

コメントの記入