このエントリーをはてなブックマークに追加
前回記事 CMSとレコメンド Apache Mahoutで独自のアクセスログを学習用データとして使うJDBCDataModelを実装する の続きです。
 writeWiredにレコメンド機能を実装していますが、協調フィルタリングのレコメンドエンジンとしてApache Mahoutを採用しました。実装の過程でわかった、他の方にも参考になりそうな方法をサンプルをご紹介します。

 

特定のコンテンツをレコメンドしたい

前回では、Mahoutの学習用に使うログを一つのデータベースから、レコメンドのモデル単位に変更する方法をご紹介しました。

今回はモデル単位に「レコメンド結果から除外する」方法をご紹介します。
Mahoutに多くのログを学習させるが、特定のコンテンツしかレコメンド対象にしない、という方法です。

このサイトではwriteWiredという製品のサイトになりますが、マーケティング関連のブログも運営しています。
記事の量的にはブログの方が圧倒的に多く、比例してアクセスも多くなります。

製品紹介のページだけを見ている方にも「あなたへのおすすめ」を表示したいので、学習用のログには全コンテンツのアクセスログを使います。ただ、トップページや会社概要をレコメンドしても仕方ないので、Mahoutがレコメンドしてきた結果からブログの記事だけにする、という方法をとれるようにしました。

これも簡単でアイテムベース、ユーザーベースとインターフェースを実装するだけです。

実装するインターフェース

org.apache.mahout.cf.taste.recommender.IDRescorer

ユーザーベースの時にスコアを変更するインターフェースです。以下のようにRecommender に渡します。
 
MyMahoutIDRescorer rescorer = new MyMahoutIDRescorer();
// レコメンド
Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
// IDが1の人に1つレコメンド。
List recommendations = recommender.recommend(1, 1,rescorer);

org.apache.mahout.cf.taste.recommender.Rescorer<LongPair>

アイテムベースの時にスコアを変更するインターフェースです。以下のようにRecommender に渡します。
 
MyMahoutIDRescorer rescorer = new MyMahoutIDRescorer();
// レコメンド
GenericItemBasedRecommender recommender = new GenericItemBasedRecommender(model, similarity);
List recommendations = recommender.mostSimilarItems(101, 1, rescorer);

実装クラス

rescoreメソッドはレコメンド結果の順位を変えるものですが、ここでは除外するようにしています。

public class MyMahoutIDRescorer implements IDRescorer ,Rescorer {
	// レコメンド可のアイテムの配列
	private List recommitemids = new ArrayList();

	public MyMahoutIDRescorer() {
		// recommitemidsにレコメンド対象のitemidをセットする。
	}
	@Override
	public boolean isFiltered(long itemid) {
		// 対象に無いアイテムはレコメンドしない
		if (!recommitemids.contains(itemid)) {
			return true;
		}
		return false;
	}
	@Override
	public double rescore(long itemid, double oririnScore) {
		// ScoreがNaNの場合はレコメンドに追加されない
		if (!recommitemids.contains(itemid)) {
			return Double.NaN;
		}
		return oririnScore;
	}		
	
	@Override
	public boolean isFiltered(LongPair longPlar) {
		long itemid =  longPlar.getSecond();
		// 対象に無いアイテムはレコメンドしない
		if (!recommitemids.contains(itemid)) {
			return true;
		}
		return false;			
	};
	@Override
	public double rescore(LongPair longPlar, double oririnScore) {
		long itemid =  longPlar.getSecond();
		// ScoreがNaNの場合はレコメンドに追加されない
		if (!recommitemids.contains(itemid)) {
			return Double.NaN;
		}
		return oririnScore;
	}
}

イメージ

イメージはこんな感じです。
writeWiredとレコメンドサーバーは別アプリで動作させ、APIでの要求と応答にしています。
実際には、レコメンドサーバーで稼働しているWebアプリのメモリ上には、一つのレコメンドに対してモデルのインスタンスが2つあって、一定の間隔でログの収集からモデル構築まで行い、構築が終わるとそのモデルを使ってレコメンドを行うようになっています。

このコンテンツは参考になりましたか?

送信する

デジタルマーケティングに対する
実体調査アンケート実施中

是非、アンケートにぜひご協力ください。

デジタルマーケティングに対する
実体調査アンケート実施中

是非、アンケートにぜひご協力ください。

 アンケートに回答する  ≫

無料eBookのダウンロード

【今からでも遅くない!】
初心者に贈る「インバウンドマーケティング」の始め方

 無料ダウンロードはこちら  ≫

人気の記事

タグ別