概要

とりあえずMahoutをEclipse上で動かしてみる。

その後、Mavenでのインストールを実行し、Hadoop(擬似分散モード)と絡めて動かしてみる。

Hadoopのインストール手順については扱わない。

@CretedDate 2012/08/04
@Env Java7, Mahout0.7

前提条件

前提条件として、Mavenが入っている必要がある。MavenはUbuntuならapt-get、RHEL系ならyumで入る。Cygwinの場合は公式サイトから落としてきてパスを通す。

Mahoutは最新の0.7のソースを使ってみる。

CDHで入れるという手もある。若干バージョンは古い(CDH3で0.5、CDH4で0.6)けど安定はしてるはず。

CDHの場合は、レポジトリの設定をCDH用のにする。

Eclipseのプロジェクトを作成する

まずは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のバージョンが低い場合はプロジェクトのプロパティから直しておく。

pom.xmlを編集する

それっぽいものを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>

pom.xml全文はこちら

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]

あれ、変わらないや。まぁ、とりあえず動くことは分かったので今回はこれで良しとする。