recommendify_whosv 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,93 @@
1
+ require ::File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Recommendify::SimilarityMatrix do
4
+
5
+ before(:each) do
6
+ flush_redis!
7
+ @matrix = Recommendify::SimilarityMatrix.new(:redis_prefix => "recommendify-test", :key => "mymatrix")
8
+ end
9
+
10
+ describe "sorted sets per item" do
11
+
12
+ it "should store member similarities" do
13
+ @matrix.update("item_foo", [["item_bar", 0.7], ["item_fnord", 0.3]])
14
+ @matrix.write_queue["item_foo"].length.should == 2
15
+ end
16
+
17
+ it "should store member similarities uniquely" do
18
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
19
+ @matrix.write_queue["item_fnord"].length.should == 1
20
+ end
21
+
22
+ it "should store member similarities uniquely and sum the scores" do
23
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
24
+ @matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0}
25
+ end
26
+
27
+ it "should store multiple member similarities uniquely and sum the scores" do
28
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3], ["item_foo", 0.75]])
29
+ @matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 0.75}
30
+ end
31
+
32
+ it "should store multiple member similarities uniquely and sum the scores on multiple updates" do
33
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_foo", 0.75]])
34
+ @matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
35
+ @matrix.write_queue["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 1.5, "item_fnord" => 0.3}
36
+ end
37
+
38
+ it "should retrieve the members" do
39
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3], ["item_foo", 0.75]])
40
+ @matrix["item_fnord"].should == {"item_bar" => 1.0, "item_foo" => 0.75}
41
+ end
42
+
43
+ end
44
+
45
+ describe "serialization/loading to/from redis" do
46
+
47
+ it "should serialize a member of the write_queue correctly" do
48
+ @matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
49
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
50
+ @matrix.send(:serialize_item, "item_fnord").should == "item_bar:1.3|item_foo:0.75|item_fnord:0.3"
51
+ end
52
+
53
+ it "should write the n-most similar members and scores to redis on commit_item!" do
54
+ @matrix.update("item_fnord", [["item_fnord", 0.3], ["item_bar", 0.3], ["item_foo", 0.75]])
55
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
56
+ @matrix.commit_item!("item_fnord")
57
+ Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").should == "item_bar:1.3|item_foo:0.75|item_fnord:0.3"
58
+ end
59
+
60
+ it "should not write more than max_neighbors scores to redis on commit_item!" do
61
+ 60.times{ |n| @matrix.update("item_fnord", [["item_#{n}", n.to_f/100.0]]) }
62
+ @matrix.commit_item!("item_fnord")
63
+ Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").split("|").length.should == 50
64
+ end
65
+
66
+ it "should not write more neighbors with zero-scores to redis on commit_item!" do
67
+ @matrix.update("item_fnord", [["item_fnord", 0.0], ["item_bar", 0.3], ["item_foo", 0.75]])
68
+ @matrix.update("item_fnord", [["item_bar", 0.7], ["item_bar", 0.3]])
69
+ @matrix.commit_item!("item_fnord")
70
+ Recommendify.redis.hget("recommendify-test:mymatrix", "item_fnord").split("|").length.should == 2
71
+ end
72
+
73
+ it "should clear the item from the write_queue after commit_item!" do
74
+ 60.times{ |n| @matrix.update("item_fnord", [["item_#{n}", n.to_f/100.0]]) }
75
+ @matrix.write_queue["item_fnord"].length.should == 60
76
+ @matrix.commit_item!("item_fnord")
77
+ @matrix.write_queue["item_fnord"].length.should == 0
78
+ end
79
+
80
+ it "should retrieve the n-most similar neighbors after stored" do
81
+ Recommendify.redis.hset("recommendify-test:mymatrix", "item_fnord", "item_blubb:0.6|item_foo:0.4")
82
+ @matrix["item_fnord"].keys.should include("item_blubb")
83
+ @matrix["item_fnord"].keys.should include("item_foo")
84
+ end
85
+
86
+ it "should retrieve the n-most similar neighbors after stored with scores" do
87
+ Recommendify.redis.hset("recommendify-test:mymatrix", "item_fnord", "item_blubb:0.6|item_foo:0.4")
88
+ @matrix["item_fnord"].should == {"item_blubb" => 0.6, "item_foo" => 0.4}
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,78 @@
1
+ require ::File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Recommendify::SparseMatrix do
4
+
5
+ before(:all) do
6
+ @sm = Recommendify::SparseMatrix.new(:redis_prefix => "recommendify-test", :key => "mysparsematrix")
7
+ end
8
+
9
+ before(:each) do
10
+ flush_redis!
11
+ end
12
+
13
+ it "should build the correct keys" do
14
+ @sm.redis_key.should == "recommendify-test:mysparsematrix"
15
+ end
16
+
17
+ it "should retrieve a value" do
18
+ Recommendify.redis.hset("recommendify-test:mysparsematrix", "bar:foo", 43)
19
+ @sm["bar", "foo"].to_i.should == 43
20
+ end
21
+
22
+ it "should retrieve a value regardless of parameter order" do
23
+ Recommendify.redis.hset("recommendify-test:mysparsematrix", "one:two", 14)
24
+ @sm["one", "two"].to_i.should == 14
25
+ @sm["two", "one"].to_i.should == 14
26
+ end
27
+
28
+ it "should store a value" do
29
+ @sm["bar", "foo"] = 123
30
+ Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 123
31
+ end
32
+
33
+ it "should store a value regardless of parameter order" do
34
+ @sm["foo", "bar"] = 126
35
+ Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 126
36
+ end
37
+
38
+ it "should return 0 if the key is not found" do
39
+ @sm["not", "set"].should == 0
40
+ end
41
+
42
+ it "should increment a value" do
43
+ @sm["foo", "bar"] = 1000
44
+ @sm.incr("foo", "bar")
45
+ Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 1001
46
+ end
47
+
48
+ it "should increment a value regardless of parameter order" do
49
+ @sm["foo", "bar"] = 2000
50
+ @sm.incr("bar", "foo")
51
+ Recommendify.redis.hget("recommendify-test:mysparsematrix", "bar:foo").to_i.should == 2001
52
+ end
53
+
54
+ it "should not create unneseccary keys" do
55
+ @sm["foo", "bar"] = 90
56
+ @sm["5asd6", "bar"] = 260
57
+ @sm["foo", "bar"] = 45
58
+ @sm["foo", "jefs"] = 26
59
+ Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 3
60
+ end
61
+
62
+ it "should create a key if the value is not 0" do
63
+ @sm["foo", "jefs"] = 26
64
+ Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 1
65
+ end
66
+
67
+ it "should not create a key if the value is 0" do
68
+ @sm["foo", "jefs"] = 0
69
+ Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 0
70
+ end
71
+
72
+ it "should delete a key if the value is set to 0" do
73
+ Recommendify.redis.hset("recommendify-test:mysparsematrix", "bar:foo", 43)
74
+ @sm["bar", "foo"] = 0
75
+ Recommendify.redis.hkeys("recommendify-test:mysparsematrix").length.should == 0
76
+ end
77
+
78
+ end
@@ -0,0 +1,42 @@
1
+ require "rspec"
2
+ require "redis"
3
+
4
+ require ::File.expand_path('../../lib/recommendify', __FILE__)
5
+
6
+ require ::File.expand_path('../input_matrix_shared.rb', __FILE__)
7
+ require ::File.expand_path('../cc_matrix_shared.rb', __FILE__)
8
+
9
+ def flush_redis!
10
+ Recommendify.redis = Redis.new
11
+ Recommendify.redis.keys("recommendify-test*").each do |k|
12
+ Recommendify.redis.del(k)
13
+ end
14
+ end
15
+
16
+ class Recommendify::Base
17
+
18
+ def redis_prefix
19
+ "recommendify-test"
20
+ end
21
+
22
+ end
23
+
24
+
25
+ class TestRecommender < Recommendify::Base
26
+
27
+ input_matrix :jaccard_one,
28
+ :similarity_func => :jaccard
29
+
30
+ end
31
+
32
+ class Recommendify::TestInputMatrix
33
+
34
+ def initialize(opts)
35
+ @opts = opts
36
+ end
37
+
38
+ def method_missing(method, *args)
39
+ @opts[method]
40
+ end
41
+
42
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: recommendify_whosv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.8
5
+ platform: ruby
6
+ authors:
7
+ - Paul Asmuth
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.8.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.8.0
41
+ description: Recommendify is a distributed, incremental item-based recommendation
42
+ engine for binary input ratings. It's based on ruby and redis and uses an approach
43
+ called "Collaborative Filtering"
44
+ email:
45
+ - paul@paulasmuth.com
46
+ executables: []
47
+ extensions:
48
+ - ext/extconf.rb
49
+ extra_rdoc_files: []
50
+ files:
51
+ - Gemfile
52
+ - README.md
53
+ - Rakefile
54
+ - doc/example.png
55
+ - doc/example.rb
56
+ - doc/example_data.csv
57
+ - ext/cc_item.h
58
+ - ext/cosine.c
59
+ - ext/extconf.rb
60
+ - ext/iikey.c
61
+ - ext/jaccard.c
62
+ - ext/output.c
63
+ - ext/recommendify.c
64
+ - ext/sort.c
65
+ - ext/version.h
66
+ - lib/recommendify.rb
67
+ - lib/recommendify/base.rb
68
+ - lib/recommendify/cc_matrix.rb
69
+ - lib/recommendify/cosine_input_matrix.rb
70
+ - lib/recommendify/input_matrix.rb
71
+ - lib/recommendify/jaccard_input_matrix.rb
72
+ - lib/recommendify/neighbor.rb
73
+ - lib/recommendify/recommendify.rb
74
+ - lib/recommendify/similarity_matrix.rb
75
+ - lib/recommendify/sparse_matrix.rb
76
+ - recommendify.gemspec
77
+ - spec/base_spec.rb
78
+ - spec/cc_matrix_shared.rb
79
+ - spec/cosine_input_matrix_spec.rb
80
+ - spec/input_matrix_shared.rb
81
+ - spec/input_matrix_spec.rb
82
+ - spec/jaccard_input_matrix_spec.rb
83
+ - spec/recommendify_spec.rb
84
+ - spec/similarity_matrix_spec.rb
85
+ - spec/sparse_matrix_spec.rb
86
+ - spec/spec_helper.rb
87
+ homepage: http://github.com/paulasmuth/recommendify
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.2.2
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: ruby/redis based recommendation engine (collaborative filtering)
111
+ test_files:
112
+ - spec/base_spec.rb
113
+ - spec/cc_matrix_shared.rb
114
+ - spec/cosine_input_matrix_spec.rb
115
+ - spec/input_matrix_shared.rb
116
+ - spec/input_matrix_spec.rb
117
+ - spec/jaccard_input_matrix_spec.rb
118
+ - spec/recommendify_spec.rb
119
+ - spec/similarity_matrix_spec.rb
120
+ - spec/sparse_matrix_spec.rb
121
+ - spec/spec_helper.rb
122
+ has_rdoc: