Apache Mahout で単純なレコメンドを実施 - Groovy
Groovy で機械学習ライブラリの Apache Mahout を使った単純なレコメンド処理を試してみました。
サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20111113/
レコメンド処理の実装
Apache Mahout の基本的なレコメンド処理は、入力データを抽象化した DataModel をレコメンド処理を抽象化した Recommender に設定して recommend メソッドにレコメンド対象のユーザーIDとレコメンドアイテム数を指定するだけです。
今回は以下のような CSV ファイルを入力データとする FileDataModel と GenericItemBasedRecommender を使ってみました。
入力 CSV ファイルフォーマット
<ユーザーID>,<アイテムID>,<評価値> ・・・
GenericItemBasedRecommender はコンストラクタで指定する Similarity によって類似性の算出方法が切り替えられるようになっています。
Mahout 0.5 には複数の Similarity が用意されています。(以下は一部)
- UncenteredCosineSimilarity : コサイン類似度
- EuclideanDistanceSimilarity : ユークリッド距離
- CityBlockSimilarity : マンハッタン距離
- PearsonCorrelationSimilarity : ピアソン相関
item_recommend.groovy
@Grab("org.apache.mahout:mahout-core:0.5") @Grab("org.slf4j:slf4j-jdk14:1.6.3") //ログ出力を止めたい場合は slf4j-jdk14 をコメント化し以下を有効にする //@Grab("org.slf4j:slf4j-nop:1.6.3") import org.apache.mahout.cf.taste.impl.recommender.* import org.apache.mahout.cf.taste.impl.similarity.* import org.apache.mahout.cf.taste.impl.model.file.FileDataModel if (args.length < 2) { println "${new File(System.getProperty('script.name')).name} <csv file> <target userID>" return } //入力データ def data = new FileDataModel(new File(args[0])) //コサイン類似度 def similarity = new UncenteredCosineSimilarity(data) //ユークリッド距離には以下を使う //def similarity = new EuclideanDistanceSimilarity(data) def recommender = new GenericItemBasedRecommender(data, similarity) //レコメンドの実施 recommender.recommend(Long.parseLong(args[1]), 5).each { println "result : ${it.itemID}, ${it.value}" }
ちなみに、SVD(特異値分解)や Slope One 等の本格的なアルゴリズムを使用するには、専用の Recommender(SVDRecommender や SlopeOneRecommender)を使用するようです。
実行
実は、上記を普通に実行しても以下のようなエラーが発生し動作しません。(mahout-core の依存関係の設定に問題がある模様)
実行時エラー
> groovy item_recommend.groovy org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: General error during conversion: Error grabbing Grapes -- [unresolved dependency: com.google.guava#guava;r03: not found, download failed: commons-logging#commons-logging;1.0.3!commons-logging.jar] java.lang.RuntimeException: Error grabbing Grapes -- [unresolved dependency: com.google.guava#guava;r03: not found, download failed: commons-logging#commons-logging;1.0.3!commons-logging.jar] ・・・
この問題を解決するスマートな方法がわからなかったので、今回は Grape がローカルにダウンロードした mahout-core の ivy.xml (実際は %USERPROFILE%\.groovy\grapes\org.apache.mahout\mahout-core\ivy-0.5.xml ファイル)を直接書き換えて対応しました。
%USERPROFILE%\.groovy\grapes\org.apache.mahout\mahout-core\ivy-0.5.xmlの変更例
<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven"> ・・・ <dependencies> ・・・ <!-- rev の値を変更(r03 -> 10.0.1) --> <override org="com.google.guava" module="guava" matcher="exact" rev="10.0.1"/> ・・・ <!-- commons-logging を追加 --> <override org="commons-logging" module="commons-logging" matcher="exact" rev="1.1.1"/> </dependencies> </ivy-module>
とりあえず、これで正常に実行できるようになります。
実行例 (ユーザーID=1 のレコメンドアイテムを出力)
> groovy item_recommend.groovy sample_data.csv 1 11 12, 2011 8:54:25 午後 org.apache.mahout.cf.taste.impl.model.file.FileDataModel <init> 情報: Creating FileDataModel for file sample_data.csv 11 12, 2011 8:54:25 午後 org.apache.mahout.cf.taste.impl.model.file.FileDataModel processFile 情報: Reading file info... 11 12, 2011 8:54:25 午後 org.apache.mahout.cf.taste.impl.model.file.FileDataModel processFile 情報: Read lines: 15 11 12, 2011 8:54:25 午後 org.apache.mahout.cf.taste.impl.model.GenericDataModel <init> 情報: Processed 5 users result : 4, 3.6666667
アイテムID=4 がレコメンドされたアイテムです。
ちなみに、入力ファイルが以下のように単純すぎたため 1アイテムしか出力されていません。
入力ファイル例
1,1,4 1,2,5 1,3,5 1,5,2 2,1,4 2,2,5 2,4,3 2,5,1 ・・・
ある程度の規模の入力データを使うと Similarity による違いが出てなかなか興味深いです。
実行例2(コサイン類似度 UncenteredCosineSimilarity)
> groovy item_recommend.groovy jester_ratings.csv 1 ・・・ 情報: Processed 59132 users result : 114, 4.388584 result : 117, 4.3182726 result : 129, 4.2214856 result : 138, 4.219198 result : 148, 4.108847
実行例3(ユークリッド距離 EuclideanDistanceSimilarity)
・・・ 情報: Processed 59132 user result : 149, 2.2220674 result : 143, 2.2179255 result : 133, 2.2131546 result : 137, 2.2050552 result : 145, 2.204735
実行例4(マンハッタン距離 CityBlockSimilarity)
・・・ 情報: Processed 59132 users result : 117, 3.3347886 result : 129, 3.259704 result : 148, 3.1350408 result : 114, 3.1283274 result : 150, 3.1082058