17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/correlators/simple_svd.rb', line 17
def run(matrix,users,items,options)
qty = 0
u,v,s = matrix.svd
xs,ys = [v.transpose.col(0).to_a, v.transpose.col(1).to_a]
precomputes = []
xs.each_index { |i| precomputes << Math.sqrt((xs[i] * xs[i]) + (ys[i] * ys[i])) }
similar_users = {}
xs.each_index do |user_idx|
x1, y1 = xs[user_idx], ys[user_idx]
sims = []
xs.each_index do |target_idx|
next if user_idx == target_idx
x2, y2 = xs[target_idx], ys[target_idx]
sim = ((x1 * x2) + (y1 * y2)) / (precomputes[user_idx] * precomputes[target_idx])
sims << [target_idx, sim] if sim >= options[:cosine_similarity]
end
x = sims.sort_by(&:last).reverse[0, (options[:max_similar_users] || sims.size)]
qty += x.size
similar_users[user_idx] = x
end
CollaborativeFilter.log " Average sims per user: #{qty.to_f / similar_users.size}"
similar_users
end
|