Rubyで書くユークリッド距離
oreillyから「集合知プログラミング」という書籍が発売されました.
この本文中で使われている例題をRubyで書いてみようと思います.
どこまで行けるか分かりませんが,やるだけやってみます.
では「ユークリッド距離によるスコア」から.
criticsの表現
本文ではPythonを使っているため,ディクショナリで書かれています.
今回はHashを使って書いてみます.
こんな感じ.
critics = { 'Lisa Rose' => { 'Lady in the Water' => 2.5, 'Snakes on a Plane' => 3.5, 'Just My Luck' => 3.0, ... } ... }
ユークリッド距離の計算
メソッド名とかは本文のものから変えていますが,やってることは同じです.
今回のデータでは問題ないのですが,正規化の除算をする時に値が整数だと丸まってしまうので,Numeric#quoを使いました.
quoを使うと実数の商を返してくれます.
module My class Recommender # # 任意の2人の類似性を算出する # def get_euclidean_similarity(critics, person1, person2) # 2人が共に批評している映画を抽出 movies = critics[person1].keys & critics[person2].keys return 0 if movies.empty? # 映画ごとの批評差を求める distances = movies.map { |movie| get_distance(critics, movie, person1, person2) } # 批評差の総和を正規化して返す sum_distances = distances.inject(0) { |sum, distance| sum + distance } normalize(sum_distances) end private # # 批評差(差分の2乗)を算出する # def get_distance(critics, movie, person1, person2) (critics[person1][movie] - critics[person2][movie]) ** 2 end # # 正規化(完全一致なら1,何も一致しなければ0) # def normalize(distance) 1.quo(1 + distance) end end end
実行結果
以下のように呼び出す部分を足して,実行してみます.
recommender = My:Recommender.new puts recommender.get_euclidean_similarity(critics, 'Lisa Rose', 'Gene Seymour')
いざ,実行!
% ./recommender.rb 0.148148148148148
本文のp.11と同じ結果が得られました.