とりあえずMahoutをEclipse上で動かしてみる。
その後、Mavenでのインストールを実行し、Hadoop(擬似分散モード)と絡めて動かしてみる。
Hadoopのインストール手順については扱わない。
前提条件として、Mavenが入っている必要がある。MavenはUbuntuならapt-get、RHEL系ならyumで入る。Cygwinの場合は公式サイトから落としてきてパスを通す。
Mahoutは最新の0.7のソースを使ってみる。
CDHで入れるという手もある。若干バージョンは古い(CDH3で0.5、CDH4で0.6)けど安定はしてるはず。
CDHの場合は、レポジトリの設定をCDH用のにする。
まずはEclipseでMahoutが動くプロジェクトを作成する。
Eclipseはm2e(MavenのEclipseプラグイン)がデフォルトで入っているEclipse3.7のIDE for Java Developersを利用する。
下記のようにプロジェクトを作成。
File → New → Other → Maven → Maven Projectを選択 → Next Create a simple projectにチェックを入れる → Next Group IdとArtifact Idに適当な文字を入力する(com.sample, mahout-testとか) → Finish
これでプロジェクトが生成される。MahoutはJDK1.6以上が必要なので、JDKのバージョンが低い場合はプロジェクトのプロパティから直しておく。
それっぽいものをdependencyに追加する。
<dependencies> <dependency> <groupId>org.apache.mahout</groupId> <artifactId>mahout-core</artifactId> <version>0.7</version> </dependency> <dependency> <groupId>org.apache.mahout</groupId> <artifactId>mahout-math</artifactId> <version>0.7</version> </dependency> <dependency> <groupId>org.apache.mahout</groupId> <artifactId>mahout-examples</artifactId> <version>0.7</version> </dependency> <dependency> <groupId>org.apache.mahout</groupId> <artifactId>mahout-collections</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.apache.mahout</groupId> <artifactId>mahout-utils</artifactId> <version>0.5</version> </dependency> </dependencies>
coreとmathがいればだいたい動くはずだけど、examplesとかの中とかにもDisplayKMeansとかいろいろ面白いものが入ってるので入れておく。
これで必要なjarは参照できるようになった。
Mahout in Actionのコードを参考にレコメンドしてみる。
本例はごく一般的なレコメンドを行う。
「ユーザAはこのアイテムを3点と評価しています。ユーザBはこのアイテムを2点と評価しています」といった情報を元にして、「ユーザAにはこのアイテムがオススメです」という結果を出すヤツ。
まず、誰がどのデータをオススメしているかを表すデータを作成する。MahoutにはユーザとかアイテムをIDにして渡さないといけないので、下記のような数字祭なファイルになる。
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
ユーザ1は102と103を、ユーザ2は101と102と103と104を評価してますよ、というファイル。
あとは下記のようなコードを書いて、推薦アイテムを抽出してみる。
DataModel model = new FileDataModel(new File("data/recommend_sample1.csv")); UserSimilarity similarity = new PearsonCorrelationSimilarity(model); UserNeighborhood neighbor = new NearestNUserNeighborhood(3, similarity, model); Recommender recommender = new GenericUserBasedRecommender(model, neighbor, similarity); List<RecommendedItem> items = recommender.recommend(1, 1); for (RecommendedItem item : items) System.out.println(item);
こうすると、ユーザ1に対しては「RecommendedItem[item:104, value:5.0]」(104のアイテムがオススメです)という結果が返ってくる。
recommender.recommendしてるとこの引数は、1つ目が対象ユーザ、2つ目がレコメンするアイテムの数を指す。
というわけで分散させないなら割と簡単にMahoutは試せる。
Mahoutはコードを書かなくても、協調フィルタリングとかクラスタリングをコマンドから実行できる。
コマンドを使うにはインストールを実行しておく必要がある。
まずは公式サイトのダウンロードページからOfficial Releaseのmahout-distribution-0.7-src.tar.bz2あたりを落とす。
解凍して中に入る
$ tar jxvf mahout-distribution-0.7-src.tar.bz2 $ cd mahout-distribution-0.7
Mavenのインストールコマンドを叩く。この処理は数十分かかることがあります。他ごとをしながら待ちましょう。テスト飛ばせば(-Dmaven.test.skip=true)速いけど。
$ mvn install
終わったら叩いてみる。
$ bin/mahout
JAVA_HOMEを設定してない場合は、下記のようなエラーが出る。
Error: JAVA_HOME is not set.
私はbin/mahoutに直接JAVA_HOMEを記述してしまっている。
$ vi bin/mahout # 上の方の行に、この記述を追加(/path/jvmのところにJVMのパスを入れる) MAHOUT_JAVA_HOME=/path/jvm
これで動くはず。
$ bin/mahout
上のコマンドを叩くと、下記のようなヘルプが表示される。(一部略)
Valid program names are: canopy: : Canopy clustering cat: : Print a file or resource as the logistic regression models would see it clusterdump: : Dump cluster output to text fkmeans: : Fuzzy K-means clustering hmmpredict: : Generate random sequence of observations by given HMM itemsimilarity: : Compute the item-item-similarities for item-based collaborative filtering kmeans: : K-means clustering lucene.vector: : Generate Vectors from a Lucene index recommenditembased: : Compute recommendations using item-based collaborative filtering seqdumper: : Generic Sequence File dumper seqwiki: : Wikipedia xml dump to sequence file vectordump: : Dump vectors from a sequence file to text viterbi: : Viterbi decoding of hidden states from given output states sequence
この辺のコマンドの大半は、Hadoopと連携してくれるようになっている。
これを使えば、bin/mahout 引数1 引数2 みたいに指定して手軽に分散環境でレコメンドやクラスタリングができる、かのように見えるけど、実際には下準備がけっこう面倒でとても手軽とは言えない気もする。
さっきやったレコメンドを、bin/mahoutから実行してみる。
Hadoopが動いている必要があった気がするので(なくても動いたっけ?)、CDH3のhadoop-0.20-conf-pseudoをapt-getで入れて動かしている。Hadoopの導入方法についてはここでは取り扱わない。
recommenditembasedを利用する。driver.classes.default.propsを見る限りでは、recommenditembasedはorg.apache.mahout.cf.taste.hadoop.item.RecommenderJobというクラスを利用しているらしい。
ソースを見つつ、試しに上の方で使ったrecommend_sample1.csvを使って、コマンドを叩いてみる。--inputで指定するパス(HDFS上)にファイルを置いておく。
$ bin/mahout recommenditembased --input recommend_sample1.csv --output output/recome --similarityClassname SIMILARITY_PEARSON_CORRELATION
何やら仰々しくMapReduceが走って、結果が出力されるので、とりあえず出力ファイルをcatしてみる。
$ hadoop fs -cat output/recome/part-r-00000 1 [104:3.9258494] 3 [102:3.2698717] 4 [102:4.7433763]
ユーザ1にはアイテム104が、ユーザ3にはアイテム102がオススメらしい。
結果が寂しいので-n3を指定して結果を3つまで出すことにしてみる。
# 前回実行ファイルとtempディレクトリが残ってるので削除しておく $ hadoop fs -rmr output $ hadoop fs -rmr temp # 再実行 $ bin/mahout recommenditembased -n 3 --input recommend_sample1.csv --output output/recome --similarityClassname SIMILARITY_PEARSON_CORRELATION # 結果を見てみる $ hadoop fs -cat output/recome/part-r-00000 1 [104:3.9258494] 3 [102:3.2698717] 4 [102:4.7433763]
あれ、変わらないや。まぁ、とりあえず動くことは分かったので今回はこれで良しとする。