Mahoutで分散レコメンド(2)
んじゃ、早速Hadoopの疑似分散環境を作ってMahoutを回してみましょう。
HadoopのセットアップとMahoutの入手
まずは利用するHadoopのセットアップ。ここは本題じゃないので要点のみ。
- Hadoopのバージョンは最新ではなく v0.20.2 を使いましょう。
- Apache Download Mirrorsから hadoop-0.20.2.tar.gz をダウンロードします。
- 各種設定は基本的にHadoop擬似分散環境メモ(Hishidama's Hadoop pseudo-distributed Memo)参照
- 設定後、起動する前に、hadoop namenode -format を忘れずに。最初、これ忘れてハマりました。
- start-all.sh でHadoop起動。hadoop fs -ls でHDFSに接続できる事を確認。
- ちなみに、Hadoopを落とす時は stop-all.sh です。
- MahoutはApache Download Mirrorsから mahout-distribution-0.5.tar.gz をダウンロード。
- 展開して mahout-core-0.5-job.jar を適当な場所に配置。
入力データファイルの準備
1,101,5.0 1,102,3.0 1,103,2.5 2,101,2.0 2,102,2.5 2,103,5.0 2,104,2.0 3,101,2.5 3,104,4.0 3,105,4.5 3,107,5.0 4,101,5.0 4,103,3.0 4,104,4.5 4,106,4.0 5,101,4.0 5,102,3.0 5,103,2.0 5,104,4.0 5,105,3.5 5,106,4.0
まず、評価データのファイル(prefs.txt)。前使ったのと同じファイルですね。ユーザID,アイテムID,評点:(long,long,float) っていうレコードになってます。
前回「Hadoop税」の項で説明した通り、本来こんな小さなデータをMapReduceに掛けてもあんま意味ありません。ここで挙げるのはあくまでも例ってことでお願いしますね。大規模な奴は、検証してみて上手く行ったらあらためてご紹介したいと思います。
1
次に、Mahoutに対して「誰に対するレコメンドをするのか」を指示するファイル(users.txt)。改行区切りでユーザIDを列挙します。このファイル自体省略も可能(その場合全員に対するレコメンドを計算する)なんだけど、今回はとりあえず指定してみる。で、ここで注意点。このファイルの末尾に改行をいれないこと。上記の例だと、ただ単に1と書いてあるだけのファイルじゃないと落ちます。皆さんも、くれぐれも30時間近く待った挙げ句に落ちる、しかも原因はNumberFormatExceptionなんて悲劇に遭わぬよう気をつけてください。っていうかこれショックでさ、ショックすぎて俺原因究明してパッチ送ったさ。まぁ早速取り込んでもらえたみたいで、次期バージョンv0.6では直ると思います。
さて、こんな目に遭わないためにも、最初の試行時はHadoop税がどーのとかめんどくせーこと言わずにスモールデータで試しなさいってことですね。実用じゃなくて、あくまでも試行なんだから。
あい、気を取り直して。以上をHDFSに送り込みます。
$ hadoop fs -put /path/to/users.txt input/users.txt $ hadoop fs -put /path/to/prefs.txt input/prefs.txt
送れたかどうか確認。
$ hadoop fs -ls input Found 2 items -rw-r--r-- 1 daisuke supergroup 231 2011-06-03 14:17 /user/daisuke/input/prefs.txt -rw-r--r-- 1 daisuke supergroup 2 2011-06-04 23:10 /user/daisuke/input/users.txt
いよいよMahout起動
$ hadoop jar \ /path/to/mahout-core-0.5-job.jar \ org.apache.mahout.cf.taste.hadoop.item.RecommenderJob \ -Dmapred.output.dir=output \ -Dmapred.input.dir=input/prefs.txt \ --usersFile input/users.txt \ --similarityClassname SIMILARITY_PEARSON_CORRELATION
- DLしたMahoutのjarファイルのパス(ローカルファイルシステム上)
- レコメンドを行うDriverのFQCN
- 結果の出力先パス(HDFS上)
- 入力ファイル(上記)のパス(HDFS上)
- ユーザファイル(上記)のパス(HDFS上)
- 類似度行列を作る際の「類似度」に何を使うか指定(ここではピアソン相関係数)*1
このまま5分ほど、正座して待つ。まぁ、待機時間はマシンスペック依存だと思いますが。エラーらしきものが表示されずにプロンプトに戻ってきたら完了。結果を見よう。
$ hadoop fs -ls output Found 2 items drwxr-xr-x - daisuke supergroup 0 2011-06-04 23:19 /user/daisuke/output/_logs -rw-r--r-- 1 daisuke supergroup 18 2011-06-04 23:20 /user/daisuke/output/part-r-00000
この part-r-00000 ってファイルが結果。中身を見てみよう。
$ hadoop fs -cat output/part-r-00000 1 [104:3.9098573]
ユーザ1へのお勧めは、104番のアイテムで、3.9点くらいをつけるでしょう、というお告げでした。
前回見た通り、類似度行列にNaNが入りまくっていて、他のアイテムに対するレコメンドを計算できなかったみたいですね。similarityClassnameオプションを変更して類似度行列の計算方式を変える*2と、複数のアイテムについて評点のお告げをもらえたりもします。
1 [105:3.875,104:3.7222223,106:3.6]
*1:他にもSIMILARITY_COOCCURRENCE, SIMILARITY_EUCLIDEAN_DISTANCE, SIMILARITY_LOGLIKELIHOOD, SIMILARITY_TANIMOTO_COEFFICIENT, SIMILARITY_UNCENTERED_COSINE, SIMILARITY_UNCENTERED_ZERO_ASSUMING_COSINE, SIMILARITY_CITY_BLOCK が使えるようです。まだ全部は試してません。
*2:ここではSIMILARITY_COOCCURRENCEを使ってみた。しかし、prefs.txtの特性上Co-occurrenceは恐らく適さないんですけどね。