FrontPage

2010/01/19からのアクセス回数 21201

Tasteについて

Tasteは、mahoutに含まれるレコメンドシステム用パッケージです。

mahout ver. 0.20のTasteは、まだMapReduce(hadoop)に対応して いないので、hadoupをインストールしなくても使用することができます。

準備

mahoutでの開発には、JDK 1.6が必要です。

Mac OS X (Leopard以降)でJDK 1.6を使う方法

ネット検索するとOS XでJDK 1.6を使うには、アプリケーションのユーティリティフォルダにある Java Preferencesで切り替えるとありますが、これを実施してもターミナルでjavac -versionが1.6に 切り替わりません。

そこで、以下の設定を.profileに追加します。

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
export PATH=$JAVA_HOME/bin:$PATH

新しいターミナルを起動して、設定が正しくできたか確認します。

$ javac -version
javac 1.6.0_15

レコメンド・アプリケーションの作成

プロジェクトの作成

mavenを使ってレコメンド・アプリケーションを作成します。

最初に、プロジェクトを作成します。

$ mvn archetype:create -DgroupId=sample.recommendApp -DartifactId=recommendApp -Dversion=0.0.1

pomファイルの変更

pom.xmlのdependecyに以下の項目を追加します。

    <dependency>
      <groupId>org.apache.mahout</groupId>
      <artifactId>mahout-core</artifactId>
      <version>0.2</version>
    </dependency>	
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-jcl</artifactId>
      <version>1.5.8</version>
      <scope>test</scope>
    </dependency>

また、JDKを1.6にするために以下のbuildを追加します。

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>    
    </plugins>  
  </build>

これで、filepom.xml の設定は完了です。

Eclipseのプロジェクトとしてインポート

Eclipseを使って編集ができるように、以下のコマンドでEclipseのプロジェクトにします。

mvn eclipse:eclipse -DdownloadSources=true

これで、必要なライブラリがすべてセットされ、ソースの参照も可能なEclipseプロジェクト のできあがりです。

Eclipseで作成したrecommendAppをインポートしてください。

最初のレコメンドアプリケーション

集合知の2章のデータを使って、ユークリッド距離によるレコメンドアプリケーション を作成してみましょう。 集合知のデータは、

# A dictionary of movie critics and their ratings of a small 
# set of movies 
critics={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5, 
 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 
 'The Night Listener': 3.0}, 
'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 
 'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 
 'You, Me and Dupree': 3.5}, 
'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0, 
 'Superman Returns': 3.5, 'The Night Listener': 4.0}, 
'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 
 'The Night Listener': 4.5, 'Superman Returns': 4.0, 
 'You, Me and Dupree': 2.5}, 
'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
 'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0, 
 'You, Me and Dupree': 2.0}, 
'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5}, 
'Toby': {'Snakes on a Plane':4.5,'You, Me and Dupree':1.0,'Superman Returns':4.0} }

ですが、これを各評価を

ユーザID,アイテムID,評価値

の並びに変えたものが、入力データのcritics.csvです。 ユーザIDは、

1	Lisa Rose
2	Gen Seymour
3	Michael Phillips
4	Claudia Puig
5	Mick LaSalle
6	Jack Matthews
7	Toby

アイテムIDは、

1	Lisa Rose
2	Gen Seymour
3	Michael Phillips
4	Claudia Puig
5	Mick LaSalle
6	Jack Matthews
7	Toby

です。 プログラムのメインは、以下のようになります。

		// モデル構築用のデータをファイルから読み込む
		DataModel model = new FileDataModel(new File("data/critics.csv"));
		// ユーザ類似性と類似ユーザ抽出のメソッドを決定
		UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
		UserNeighborhood neighborhood = new NearestNUserNeighborhood(2,
				similarity, model);
		// ユーザベースの推薦を作成
		Recommender recommender = new GenericUserBasedRecommender(model,
				neighborhood, similarity);
		// Toby(ユーザID=7)への推薦項目を3個検索
		List<RecommendedItem> recommendations = recommender.recommend(7, 3);
		// 推薦結果を出力
		for (RecommendedItem recommendation : recommendations) {
			System.out.println(recommendation);
		}		

以下のテストデータとjavaのプログラムがあります。

実行結果

プログラムを実行すると以下のように出力されます。

10/01/19 19:24:39 INFO file.FileDataModel: Creating FileDataModel for file data/critics.csv
10/01/19 19:24:39 INFO file.FileDataModel: Reading file info...
10/01/19 19:24:39 INFO file.FileDataModel: Read lines: 35
10/01/19 19:24:39 INFO model.GenericDataModel: Processed 7 users
RecommendedItem[item:6, value:3.741911]
RecommendedItem[item:1, value:3.0]
RecommendedItem[item:3, value:2.4946072]

推薦の結果は、最後の2行です。ItemIdを映画の名前にすると

  • Item:6→ The Night Listener
  • Item:1→ Lady in the Water
  • Item:3→ Just My Luck

となり、Tobyがまだ見ていない映画のなかから、Tobyと似た嗜好をもつユーザの 好きな映画がリストアップされます。

この結果は、「集合知」2.4の結果とスコアは異なりますが順序は一致します。

# 集合知の出力
>>>recommendations.getRecommendations(recommendations.critics,'Toby', 
...   similarity=recommendations.sim_distance) 
[(3.5002478401415877, 'The Night Listener'), (2.7561242939959363, 'Lady in the 
Water'), (2.4619884860743739, 'Just My Luck')]

実データを使った例

集合知のデータは、小さいので実用に耐えうるかどうかをみるために、実際のデータで 試してみます。

実データの準備

実データとして、GroupLensのサイト*1 から

をダウンロードし、解凍したフォルダからua.baseを取り出します。

このファイルは、10 million ratingsよりさらに小さな評価データ90570個を含むデータファイルです。

以下のawkコマンドを使ってこのファイルをUserId, ItemId, Ratingのカンマ区切りのファイルに変換します。

$ awk '{printf("%s,%s,%s\n",$1,$2,$3);}' data/ua.base > movielens.csv

推薦手法の選択

実データのように大きな規模になると推薦に要する計算時間が大きな要因になってきます。

今回は、ユーザアイテムマトリックスをすくない特性からなるユーザ特性マトリックスに変換して推薦する SVDRecommenderを使うことにします。

SVDRecommenderの引数は、

SVDRecommender(model, numFeatures, initialSetps)
model		モデル
numFeatures	特性数
initialSetps	イテレーション回数

です。

SVDRecommenderのメインは以下のようになります。

		// モデル構築用のデータをファイルから読み込む
		DataModel model = new FileDataModel(new File("data/movielens.csv"));
		// ユーザベースのSVD推薦を作成
		Recommender recommender = new SVDRecommender(model, 3, 50);
		// ユーザID=1への推薦項目を3個検索
		List<RecommendedItem> recommendations = recommender.recommend(1, 3);
		// 推薦結果を出力
		for (RecommendedItem recommendation : recommendations) {
			System.out.println(recommendation);
		}		

実行結果は、以下のようになります。

10/01/19 21:00:43 INFO file.FileDataModel: Creating FileDataModel for file data/movielens.csv
10/01/19 21:00:44 INFO file.FileDataModel: Reading file info...
10/01/19 21:00:44 INFO file.FileDataModel: Read lines: 90570
10/01/19 21:00:44 INFO model.GenericDataModel: Processed 943 users
RecommendedItem[item:1449, value:5.2471733]
RecommendedItem[item:483, value:5.05086]
RecommendedItem[item:511, value:4.951155]

しかし、これでは本当にうまく推薦できているのか分かりませんね。そこで推薦の精度を調べてみましょう。

推薦の精度

推薦の評価方法のひとつに実際の評価値と推定値の誤差の自乗を足し合わせ平方根を取ったRMS(root mean squared)があります。

RMSRecommenderEvaluatorは、RMSで推薦を評価するクラスです。 evaluatorのevaluateメソッドは、最後の2つの引数が

  • 学習用データの割合
  • 検証用データの割合

を指定します。

評価のメインクラスは、以下のようになります。

		// モデル構築用のデータをファイルから読み込む
		DataModel model = new FileDataModel(new File("data/movielens.csv"));
		// RMSを使った評価オブジェクトを作成
		RecommenderEvaluator evaluator = new RMSRecommenderEvaluator();
		// 推薦ビルダーを定義
		RecommenderBuilder builder = new RecommenderBuilder() {			
			public Recommender buildRecommender(DataModel model)
					throws TasteException {
				return new SVDRecommender(model, 3, 50);
			}
		};
		// 学習用データとして、全体の0.75を使い、検証用データとして0.25を使って評価する
		double score = evaluator.evaluate(builder, null, model, 0.75, 0.25);
		System.out.println(score);

実行結果は、

10/01/19 21:25:16 INFO file.FileDataModel: Creating FileDataModel for file data/movielens.csv
10/01/19 21:25:16 INFO eval.AbstractDifferenceRecommenderEvaluator: Beginning evaluation using 0.75 of 
FileDataModel[dataFile:/Users/take/tmp/recommendApp/data/movielens.csv]
10/01/19 21:25:16 INFO file.FileDataModel: Reading file info...
10/01/19 21:25:16 INFO file.FileDataModel: Read lines: 90570
10/01/19 21:25:16 INFO model.GenericDataModel: Processed 943 users
10/01/19 21:25:16 INFO model.GenericDataModel: Processed 235 users
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Beginning evaluation of 231 users
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Item exists in test data but not training data: 360
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Item exists in test data but not 
途中省略
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Item exists in test data but not training data: 1394
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Finished 1
10/01/19 21:25:17 INFO eval.AbstractDifferenceRecommenderEvaluator: Evaluation result: 0.9598115822159887
0.9598115822159887

0.9598は、まあまあの値です。どの推薦手法もそうですが、パラメータを調整しないとよい値はでません。

コメント

選択肢 投票
おもしろかった 47  
そうでもない 0  
わかりずらい 1  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


*1 Mahout in Actionの4.2.3を参考

添付ファイル: fileApp.java 2505件 [詳細] filecritics.csv 2434件 [詳細] filepom.xml 1802件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-02-28 (土) 20:07:50 (3345d)
SmartDoc