スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

rubyでレコメンデーション

集合知プログラミング」の「推薦する」のプログラムをrubyで書いてみました。でも、私のruby力不足から、うまく書けずに先人の知恵を借りてみました。変数の初期化とか関数を引数にする方法あたりを参考にしました。

『集合知プログラミング』を Ruby でCommentsAdd Star - ドレッシングのような
"Collective Intelligence"のサンプルをrubyに移植してみた - ma2の日記

配列をぶんぶんまわすあたりは、私のプログラムよりも上記のリンク先の方が洗練されています(笑)
ちなみに、deliciousの自分向けのおすすめを計算したら、あまりにも傾向が似ていなかったため、何も推薦してくれませでした(泣)

# coding:utf-8

# ユークリッド距離を計算する
def simDistance prefs, person1, person2
si = prefs[person1].keys & prefs[person2].keys
if 0 == si.size
return 0
end
sum_of_squares = 0
si.each {|it|
dt = prefs[person1][it] - prefs[person2][it]
sum_of_squares = sum_of_squares + dt ** 2
}
return 1 / (1 + sum_of_squares)
end

# ピアソン相対係数を計算する
def simPearson prefs, person1, person2
# 一致するアイテム取得
si = prefs[person1].keys & prefs[person2].keys
if 0 == si.size
return 0
end
n = si.size
if 0 == n
return 0
end

# 合計の計算
sum1 = 0.0
sum2 = 0.0
sum1Sq = 0.0
sum2Sq = 0.0
pSum = 0.0
si.each {|item|
val1 = prefs[person1][item]
val2 = prefs[person2][item]
sum1 = sum1 + val1
sum2 = sum2 + val2
sum1Sq = sum1Sq + val1 ** 2
sum2Sq = sum2Sq + val2 ** 2
pSum = pSum + val1 * val2
}

# ピアソンによる須子を計算する
num = pSum - (sum1 * sum2 / n)
den = Math::sqrt((sum1Sq - (sum1 ** 2) / n) * (sum2Sq - (sum2 ** 2) / n))
if 0 == den
return 0
end
return num / den
end

# 似ているトップを取得
def topMatches prefs, person, n=5, similarity=:simPearson
result = []
prefs.each_key{|other|
if other == person
next
end
result << [__send__(similarity, prefs, person, other), other]
}

return result.sort.reverse[0, n]
end

# 推薦を取得する
def getRecommendations prefs, person, similarity=:simPearson
totals = Hash.new(0.0)
simSums = Hash.new(0.0)
prefs.each_key {|other|
if person == other
next
end

sim = __send__(similarity, prefs, person, other)
if sim <= 0.0
next
end

prefs[other].each_key {|item|
if (!prefs[person].key?(item)) || (prefs[person][item] == 0.0)
totals[item] += prefs[other][item] * sim
simSums[item] += sim
end
}
}
rankings = []
totals.each {|item, total|
rankings << [total / simSums[item], item]
}
return rankings.sort.reverse
end

# 入れ替える
def transformPrefs prefs
result = Hash.new{|h, k| h[k] = {}}
prefs.each {|person, items|
items.each{|item, value|
result[item][person] = value
}
}
return result
end
スポンサーサイト

Tag : 集合知プログラミング

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。