Rubyで書くアイテムベースの推薦
前回作成したアイテムベースのデータを使って,映画の推薦を行うことができます.
アイテム相関による推薦
アイテム同士の相関値を作成してから,批評値と相関値を掛け合わせます.
あらかじめ作成したアイテム相関のデータを渡せると,計算が早くなるのが嬉しいところ.
module My class Recommender # # アイテム相関と映画評価の積で一番の映画を推薦する # def get_item_similarity_recommendations(critics, me, options = {}) # 各アイテムの相関のあるアイテムを計算する # 計算済みのデータが指定されている場合はそのまま使う item_similarities = options[:tem_similarity] || get_item_similarity(critics) # 相関のあるアイテムごとにmeの評価値と相関の積を出す ratings = Hash.new(0) sum_similarities = Hash.new(0) critics[me].each do |movie, critic| item_similarities[movie].each do |similarity, similar_movie| ratings[similar_movie] += (critic * similarity) sum_similarities[similar_movie] += similarity end end # 自分が批評済のものは無駄なので削除 ratings.delete_if { |movie, similarity| critics[me].keys.include?(movie) }.map { |movie, rating| # 正規化(類似度の合計で割る) [movie, rating.quo(sum_similarities[movie])] }.sort_by { |movie, normalized_rating| normalized_rating }.reverse end end end
実行結果
まずは,値を計算してみましょう.
recommender = My:Recommender.new puts recommender.get_item_similarity_recommendations(critics, 'Toby')
いざ,実行!
% ./recommender.rb
The Night Listener
3.18263473053892
Just My Luck
2.59833187006146
Lady in the Water
2.47308781869688
p.27と同じ結果が得られました.
さて...
ここでは更にBenchmarkモジュールを使って,今回得られたアイテム相関値を与えない場合と,与える場合を比較してみましょう.
1000回繰り返して,どのくらい差が出るかみてみます.
require 'benchmark' items = recommender.get_item_similarity(critics) Benchmark.bm(15) do |x| x.report('items_disabled') { 1000.times { recommender.get_item_similarity_recommendations(critics, 'Toby') } } x.report('items_enabled') { 1000.times { recommender.get_item_similarity_recommendations(critics, 'Toby', { :item_similarity => items }) } } end
いざ,実行!
% system_profiler SPHardwareDataType Hardware: Hardware Overview: Model Name: MacBook Air Model Identifier: MacBookAir1,1 Processor Name: Intel Core 2 Duo Processor Speed: 1.6 GHz Number Of Processors: 1 Total Number Of Cores: 2 L2 Cache: 4 MB Memory: 2 GB Bus Speed: 800 MHz Boot ROM Version: MBA11.00BB.B03 SMC Version: 1.23f9 Serial Number: *********** Sudden Motion Sensor: State: Enabled % ruby -v ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] % ./recommender.rb user system total real items_disabled 4.320000 0.020000 4.340000 ( 4.371397) items_enabled 0.140000 0.000000 0.140000 ( 0.141398)
今回はデータの総量が少ないので,そもそも大して時間は掛かりませんでした.
が,それでも30倍くらいの差が出ました.