2章 その11
その10で、ある映画に似ている映画とその類似度を取れるようになった。
自分がこれまで評価した映画に付けたスコアと、まだ見ていない映画との類似度を使って、まだ見ていない映画に何点をつけるかを予測する。
p.26~27より
recommendations.rb にgetRecommendedItems関数を追加
http://www.bitbucket.org/shokai/collective-intelligence-study/src/36aef661a53f/recommendations.rb
def getRecommendedItems(prefs, itemMatch, user) userRatings = prefs[user] scores = Hash.new totalSim = Hash.new #このユーザに評価されたアイテムをループする userRatings.each{ |item, rating| # このアイテムに似ているアイテムたちをループする itemMatch[item].each{ |i| i.each{ |similarity, item2| # このアイテムに対してユーザがすでに評価を行っていれば無視する next if userRatings.key?(item2) # 評点と類似度を掛け合わせたものの合計で重みづけする scores[item2] = 0 if !scores.key?(item2) scores[item2] += similarity * rating # すべての類似度の合計 totalSim[item2] = 0 if !totalSim.key?(item2) totalSim[item2] += similarity } } } # 正規化のため、それぞれの重み付けしたスコアを類似度の合計で割る rankings = Hash.new scores.each{ |item, score| rankings[ score/totalSim[item] ] = item } # 降順に並べて配列に入れたランキングを返す result = Array.new rankings.keys.sort.reverse.each{ |score| result.push( {score => rankings[score] } ) } return result end
p.27より、Tobyにオススメする映画リストを計算
>> pp c.getRecommendedItems(c.users, itemsim, 'Toby') [{3.18263473053892=>"The Night Listener"}, {2.59833187006146=>"Just My Luck"}, {2.47308781869688=>"Lady in the Water"}] => nil
アイテム同士の類似度は先に計算されているので、毎回呼び出さなくてすんでいる