Rails + Cicindelaでレコメンデーション付ウェブサイトの構築(3)

aike2009-01-26

目次

  1. ユーザ認証付Railsアプリの構築
  2. RailsアプリにCicindelaインタフェースを実装
  3. Cicindelaの設定とバッチ処理設定   ←いまここ

 
そんなわけで、最後にCicindela側の設定と集計処理のバッチ設定をしてみます。
  

Cicindelaインストール

Cicindela本体のインストール方法は以前書いたエントリーを参照してください。
今回のアプリ用のテーブルを以下のコマンドで作成します。

cd /home/cicindela/misc
perl create_init_sql.pl --db_name=cicindela_bookmark > init_sql
mysql -uroot -ppass < init_sql

 

レコメンダー、フィルターチェーンの設定

ドキュメントにもあるようにCicindelaでは豊富なフィルターやレコメンダーが用意されており、それらを組み合わせてさまざまな種類のレコメンデーションを実現することができます。ただ、これも何と何を組み合わせることができるのか、ソースを読んで確認する必要があります。
たとえば、今回アイテム同士の相関を返すレコメンダーItemSimilaritiesを使いたいのですが、これを使うためには、ItemSimilaritiesフィルターの出力が必要で、ItemSimilaritiesフィルターを使うためにはPicksExtractorフィルターの出力とInverseUserFrequencyフィルターの出力が必要で……、といった関係を把握する必要があります。
まあサンプルもありますし、それぞれのソースコードはせいぜい数十行程度なので読むのは簡単です。
 
とりあえず一番シンプルな設定として以下のようにしました。
/home/cicindela/lib/Cicindela/Config/_common.pm

package Cicindela::Config::_common;
use strict;
use vars qw(%C);
*Config = \%C;

$C{CICINDELA_HOME} = '/home/cicindela';
$C{LOG_CONF} = $C{CICINDELA_HOME}. '/etc/log.conf';
$C{FILTERS_NAMESPACE} = 'Cicindela::Filters';

$C{DEFAULT_DATASOURCE} = [
'dbi:mysql:cicindela_bookmark;host=localhost', 'root', 'pass' ];

$C{SETTINGS} = {
   'bookmark' => {
       datasource => [ 'dbi:mysql:cicindela_bookmark;host=localhost',
'root', 'pass' ],
       filters => [
           'PicksExtractor',              # アイテム重要度順抽出
           'InverseUserFrequency',        # 選択ユーザ数による補正
           'ItemSimilarities',            # アイテム間類似度集計
       ],
       recommender => 'ItemSimilarities', # アイテム間類似度で出力
       refresh_interval => 1,             # インターバルなし
   }                                      # トラックは指定しない(常に集計)
};

# for using cleanup_mysql_binlog.pl
$C{DB_MAINTENANCE_SETS} = [
   {
       master => [ 'dbi:mysql:host=localhost', 'maintenance', '' ],
       slave => [],
   },
];

1;

 

バッファのフラッシュを忘れずに

Cicindelaで最初にハマったのがここでした。Web APIを叩いて入力したデータはpicks_bufferというテーブルにたまっていきますが、この状態では集計対象になりません。適当なタイミングで/home/cicindela/bin/flush_buffers.plを実行することにより、picks_bufferからpicksというテーブルにデータが移動します。これではじめて集計用データとなります。
 

Railsによるバッチの起動

cronは設定が見えづらいので、RailsプラグインであるBackgrounDrbを使ってCicindelaのバッチを起動してみることにします。アプリケーションサーバとレコメンデーションサーバが同一マシンであることが前提になってしまいますが、設定がRailsの世界で完結するのでなにかと便利です。

インストール方法

必須ライブラリのインストール

sudo gem install chronic packet

BackgrounDrbプラグインのインストール

script/plugin install http://svn.devjavu.com/backgroundrb/trunk
rake backgroundrb:setup
rake db:migrate

定時起動されるワーカークラスの生成

script/generate worker recommend

生成されたワーカークラスを編集し、集計バッチとフラッシュバッチのメソッドを用意します。
lib/workers/recommend_worker.rb

class RecommendWorker < BackgrounDRb::MetaWorker
 set_worker_name :recommend_worker

 def create(args = nil)
 end

 def do_analyze
   logger.info(Time.now.to_s + " recommendation data ANALYZE start")
   system('/home/cicindela/bin/batch.pl')
   logger.info(Time.now.to_s + " recommendation data ANALYZE end")
 end

 def do_flush
   logger.info(Time.now.to_s + " recommendation data FLUSH start")
   system('/home/cicindela/bin/flush_buffers.pl')
   logger.info(Time.now.to_s + " recommendation data FLUSH end")
 end

end

 

定時起動設定

今回は毎日AM4時にフラッシュバッチを動かし、その後AM5時に集計バッチを動かすようにしてみました。
/ config / backgroundrb.yml

---
:backgroundrb:
 :ip: 0.0.0.0
 :port: 11006
:schedules:
 :recommend_worker:
  :do_flush:
    :trigger_args: 0 0 4 * * * *
  :do_analyze:
    :trigger_args: 0 0 5 * * * *

サーバ群の起動方法

Railsサーバ

script/server

BackgrounDrbサーバ

script/backgroundrb start

レコメンデーションサーバ

sudo /usr/local/apache2/bin/apachectl start

今回はデフォルト設定のままRailsサーバがMongrel、CicindelaサーバがApacheとしましたが、両方同じApacheで動かすこともできます。実際に商用サービスなんかで使う場合はCicindelaサーバは別マシンにして外から見えないようにするのが良いでしょう。
 

動作確認

ここまでで環境は整ったので後は動作確認です。今回、自分はぐるなびをたくさんブックマークしてみました。ユーザを5人くらい作成して、それぞれ主にスープカレーをブックマーク、主にラーメンをブックマーク、主にジンギスカンをブックマークというように意図的に偏りを持たせました。フラッシュバッチと集計バッチをちょこちょこ手動で起動していくと、大体総ブックマーク数が50件くらいになったら関連ページがレコメンデーションされるようになりました。

おしまい
 
※今回作成した全ソースコードgithubで公開しています。