Recommendifyで気軽にレコメンドエンジンに触れてみる

変態アドベントカレンダーの19日目です。

今日はRecommendifyで気軽にレコメンドエンジンに触れてみたいと思います。
※コサイン類似度などの小難しい話は一切登場しません。

  1. レコメンドエンジンとは
  2. Recommendifyで出来ること
  3. Redisのインストールと起動
  4. Recommendifyのインストール
  5. ラッキングデータの登録
  6. レコメンドデータの取得


1. レコメンドエンジンとは
Amazonで「この商品を買った人はこんな商品も買っています」とユーザに商品をおすすめしてくるシステムのことです。何かを見た/クリックした/買ったといった情報を使用して、他のサイトやユーザーに対して商品のおすすめを行います。


2. Recommendifyで出来ること
RecommendifyとはRubyとRedisベースのレコメンドエンジンです。
アイテム間の類似性を計算することでレコメンデーションを行えます、


3. Redisのインストールと起動
既にRedisが入っている人も多いかと思いますが(笑)、まだの人はインストールしましょう。
macな人はhomebrewでインストールしてもいいし、そうでない人はソースから入れましょう。

for mac

$ brew install redis

for otherwize

$ wget http://download.redis.io/redis-stable.tar.gz
$ tar xvzf redis-stable.tar.gz
$ cd redis-stable
$ make && make install

起動させます。

$ redis-server

※停止するときは 別ターミナルから redis-cli shutdown します

一応テストとしてピンポンしておきましょう。

$ redis-cli ping
pong


試しにデータを出し入れしてみます。

$ redis-cli set mykey hoge
OK

$ redis-cli get mykey
"hoge"


4. Recommendifyのインストール
gemでインストールします。

$  gem install recommendify

※うまく入らない場合はgem updateしてみるとうまくいくかもしれません。


5. トラッキングデータの登録
ユーザがそれぞれ複数のアイテムを購入をしたとした場合のサンプルコードです。

# -*- encoding: utf-8 -*-
require 'recommendify'
require 'redis'

Recommendify.redis = Redis.new

class Recommender < Recommendify::Base
  max_neighbors 10
  input_matrix :order_items,
    :similarity_func => :jaccard,
    :weight => 5.0
end

recommender = Recommender.new
recommender.order_items.add_set("daiksyさん", ["ふつうの変態プログラミング", "変態が知るべき97のこと", "変態サムライ"])
recommender.order_items.add_set("irofさん", ["ふつうの変態プログラミング", "変態サムライ"])
recommender.order_items.add_set("kuchitamaさん", ["変態が知るべき97のこと", "やさしい変態入門"])
recommender.process!


6. レコメンドデータの取得
「変態が知るべき97のこと」というアイテムと他のアイテムの類似度を調べてみます。

recommender.for("変態が知るべき97のこと").each do |recommended_product|
  puts "#{recommended_product.item_id} 類似度:#{recommended_product.similarity}\n"
end

結果

やさしい変態入門 類似度:2.5変態サムライ 類似度:1.6666
ふつうの変態プログラミング 類似度:1.6666

ということで、「変態が知るべき97のこと」に類似している本は「やさしい変態入門 」だということが分かりました。
簡単に利用できますね!


利用シーンについて
RecommendifyはRubyで書かれているため、既存の非Rubyプロダクトに組み込めないなーと思うかもしれません。
1日1回実施されるようなバッチアプリケーションとして、行動履歴データからレコメンドデータを生成するようなものを作るのもありだと思います。
使ったことはありませんが、本格的なレコメンドを行うには Apache Mahout を使うのがよさそうです。


明日は@Posauneさんです!お楽しみに。


参考URL
Redis: http://redis.io/
Recommendify: https://github.com/paulasmuth/recommendify

rubyで正規表現を使って文字列を判定するときのコツ

処理速度が求められる箇所で正規表現を使う場合"oフラグ"を使うと
正規表現オブジェクトが再生成されずに有効だと聞いたことがあったので
Regexpを使ったケースと比較検証してみた。(ruby標準のprofilerを利用)

require 'profiler'
def profile
  Profiler__.start_profile
  100000.times do |i|
    yield
  end
  Profiler__.print_profile(STDOUT)
end

puts "固定パターン"
profile do "hoge.gif" =~ /.gif/ end

puts "変数使用+oフラグ"
pattern = ".gif"
profile do "hoge.gif" =~ /#{pattern}/o end

puts "Regexpを使用"
regexp = Regexp.new("#{pattern}")
profile do regexp.match("hoge.gif") end

結果はこんな感じ

固定パターン
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
100.00    20.60     20.60        1 20599.00 20599.00  Integer#times
  0.00    20.60      0.00        1     0.00 20599.00  #toplevel
変数使用+oフラグ
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
100.00    22.39     22.39        1 22392.00 22392.00  Integer#times
  0.00    22.39      0.00        1     0.00 22392.00  #toplevel
Regexpを使用
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 76.95    50.54     50.54        1 50539.00 65675.00  Integer#times
 23.05    65.67     15.14   100000     0.15     0.15  Regexp#match
  0.00    65.67      0.00        1     0.00 65675.00  #toplevel

正規表現を使わない固定パターンが速いのは当たり前だとして、
Regexpを使ったほうが遅いのが意外だった。
rubyバージョンは1.8.6

figma 初音ミク を店頭で購入した

本日発売の figma 初音ミクを店頭でGET
amazonやあみあみなど大手通販サイトでは予約分が売り切れ続出だったので、店頭分は無いかも・・と
不安だったが、お昼に家電量販店のおもちゃコーナ−に行くと、しっかり残っていたのでほっとした。
しかし、その家電量販店も夕方にはしっかり完売となっていたとのこと。恐るべし、初音ミク


お昼当時の様子

オークションでも高値を付けているようだ
aucfan.com:
http://aucfan.com/search1?inum=30&x=17&y=8&t=-1&q=figma+%bd%e9%b2%bb%a5%df%a5%af

rails:freeze:gems でちょいハマリ

railsのバージョンが2.0.2だと、素直にrake rails:freeze:gemsできるのだが
2.0.1だと、以下のようなエラーがでてしまう

rake rails:freeze:gems VERSION=2.0.1
(in D:/workspace/foo201)
Freezing to the gems for Rails 2.0.1
rake aborted!
uninitialized constant Gem::GemRunner

調べたら、以下のサイトにて対処方が載っていた
http://www.oiax.jp/rails/rails2/freeze_gems.html

% rmdir vendor/rails
% rake --require=rubygems/gem_runner rails:freeze:gems VERSION=1.2.3
  1. 既に生成されたrailsフォルダを削除
  2. --require オプションを付けてfreeze実行

むむぅ、イマイチな感じ。

NetBeansでrailsのソースをalt + shift + oで検索したい

デフォルトのNetBeansではrailsのソースをalt + shift + oで検索することができない。
なので、プロジェクト内にソースをコピーし、検索できるようにしたい。
railsのバージョンを固定

rake rails:freeze:gems VERSION=2.0.2

すると、vender/以下にrailsディレクトリが作成される。プロジェクト内にソースがコピーされている

解除(vender/railsディレクトリを削除)するときは

rake rails:unfreeze

alt + shift + o で、railsのソースが検索可能になった、便利〜。
と思ったら別の問題が!!

ruby script/console が使えなくなった。。
gem バージョンは1.2.0
rails フォルダを削除すれば、元には戻ったが、、原因追求は別途とする。

NetBeans6.1で快適にrails

ちょっとしたことなんだけど、NetBeans6.1で現在編集しているファイルが
プロジェクトのどのディレクトリにあるのか確認したいときがある。

プロジェクト内で選択

ctr + shift + 1

ファイル内で選択したい場合は

ctr + shift + 2

eclipseだと、IDEの設定で編集中のファイルを常にプロジェクトエクスプローラ
トレースしてくれるんだけど、NetBeansではこういった設定が無いらしい。
まぁ、これで十分。



あと、普段apiを調べるときは、こういったhttp://www.railsbrain.com/ところで
十分なんだけど、じっくりrailsのソースが見たい場合、NetBeansから直接
railsのソースが開きたい。
ところがshift + alt + o ではプロジェクト内のフィアルが検索対象となっているので
railsのソースは対象外となる。
なので、rails:freeze:gemsを使ってvender/rails ディレクトリ以下にrailsのソースを
コピーしてしまうといい。

Railsのバージョンを固定する(vender/rails ディレクトリ以下にrailsのソースがコピーされる)

rake rails:freeze:gems VERSION=2.0.2

これで、shift + alt + o にてrailsソースが検索できる