inferx 0.2.3 → 0.2.4
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.
- data/lib/inferx.rb +2 -4
- data/lib/inferx/categories.rb +173 -18
- data/lib/inferx/category.rb +40 -76
- data/lib/inferx/category/complementary.rb +48 -0
- data/lib/inferx/version.rb +1 -1
- data/spec/inferx/categories_spec.rb +325 -59
- data/spec/inferx/category/complementary_spec.rb +76 -0
- data/spec/inferx/category_spec.rb +60 -119
- data/spec/inferx_spec.rb +1 -9
- data/spec/spec_helper.rb +7 -0
- metadata +5 -11
- data/lib/inferx/adapter.rb +0 -64
- data/lib/inferx/complementary/categories.rb +0 -14
- data/lib/inferx/complementary/category.rb +0 -108
- data/spec/inferx/adapter_spec.rb +0 -92
- data/spec/inferx/complementary/categories_spec.rb +0 -25
- data/spec/inferx/complementary/category_spec.rb +0 -139
@@ -1,108 +0,0 @@
|
|
1
|
-
require 'inferx/category'
|
2
|
-
|
3
|
-
class Inferx
|
4
|
-
module Complementary
|
5
|
-
class Category < Inferx::Category
|
6
|
-
|
7
|
-
# Inject the words to the training data of the category.
|
8
|
-
#
|
9
|
-
# @param [Array<String>] words an array of words
|
10
|
-
alias inject train
|
11
|
-
|
12
|
-
# Eject the words from the training data of the category.
|
13
|
-
#
|
14
|
-
# @param [Array<String>] words an array of words
|
15
|
-
alias eject untrain
|
16
|
-
|
17
|
-
# Prepare to inject the words to the training data of the category. Use
|
18
|
-
# for high performance.
|
19
|
-
#
|
20
|
-
# @yield [train] process something
|
21
|
-
# @yieldparam [Proc] inject inject the words to the training data of the
|
22
|
-
# category
|
23
|
-
ready_for :inject
|
24
|
-
|
25
|
-
# Prepare to eject the words from the training data of the category. Use
|
26
|
-
# for high performance.
|
27
|
-
#
|
28
|
-
# @yield [train] process something
|
29
|
-
# @yieldparam [Proc] eject eject the words from the training data of the
|
30
|
-
# category
|
31
|
-
ready_for :eject
|
32
|
-
|
33
|
-
# Enhance the training data of other categories giving words.
|
34
|
-
#
|
35
|
-
# @param [Array<String>] words an array of words
|
36
|
-
def train(words)
|
37
|
-
return if words.empty?
|
38
|
-
|
39
|
-
increase = words.size
|
40
|
-
words = collect(words)
|
41
|
-
|
42
|
-
category_names = get_other_category_names
|
43
|
-
return if category_names.empty?
|
44
|
-
|
45
|
-
@redis.pipelined do
|
46
|
-
category_names.each do |category_name|
|
47
|
-
category_key = make_category_key(category_name)
|
48
|
-
words.each { |word, count| @redis.zincrby(category_key, count, word) }
|
49
|
-
hincrby(category_name, increase)
|
50
|
-
end
|
51
|
-
|
52
|
-
@redis.save unless manual?
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Attenuate the training data of other categories giving words.
|
57
|
-
#
|
58
|
-
# @param [Array<String>] words an array of words
|
59
|
-
def untrain(words)
|
60
|
-
return if words.empty?
|
61
|
-
|
62
|
-
decrease = words.size
|
63
|
-
words = collect(words)
|
64
|
-
|
65
|
-
category_names = get_other_category_names
|
66
|
-
return if category_names.empty?
|
67
|
-
|
68
|
-
scores = @redis.pipelined do
|
69
|
-
category_names.each do |category_name|
|
70
|
-
category_key = make_category_key(category_name)
|
71
|
-
words.each { |word, count| @redis.zincrby(category_key, -count, word) }
|
72
|
-
@redis.zremrangebyscore(category_key, '-inf', 0)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
length = words.size
|
77
|
-
decreases_by_category = {}
|
78
|
-
|
79
|
-
category_names.each_with_index do |category_name, index|
|
80
|
-
decrease_by_category = decrease
|
81
|
-
|
82
|
-
scores[index * (length + 1), length].each do |score|
|
83
|
-
score = score.to_i
|
84
|
-
decrease_by_category += score if score < 0
|
85
|
-
end
|
86
|
-
|
87
|
-
decreases_by_category[category_name] = decrease_by_category if decrease_by_category > 0
|
88
|
-
end
|
89
|
-
|
90
|
-
return if decreases_by_category.empty?
|
91
|
-
|
92
|
-
@redis.pipelined do
|
93
|
-
decreases_by_category.each do |category_name, decrease|
|
94
|
-
hincrby(category_name, -decrease)
|
95
|
-
end
|
96
|
-
|
97
|
-
@redis.save unless manual?
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def get_other_category_names
|
104
|
-
hkeys.reject { |category_name| category_name == name }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
data/spec/inferx/adapter_spec.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'inferx/adapter'
|
3
|
-
|
4
|
-
describe Inferx::Adapter, '#initialize' do
|
5
|
-
it 'sets the instance of Redis to @redis' do
|
6
|
-
redis = redis_stub
|
7
|
-
adapter = described_class.new(redis)
|
8
|
-
adapter.instance_eval { @redis }.should == redis
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'sets nil to @namespace' do
|
12
|
-
adapter = described_class.new(redis_stub)
|
13
|
-
adapter.instance_eval { @namespace }.should be_nil
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'sets false to @manual' do
|
17
|
-
adapter = described_class.new(redis_stub)
|
18
|
-
adapter.should_not be_manual
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'with namespace option' do
|
22
|
-
it 'sets the value of namespace option to @namespace' do
|
23
|
-
adapter = described_class.new(redis_stub, :namespace => 'example')
|
24
|
-
adapter.instance_eval { @namespace }.should == 'example'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'with manual option' do
|
29
|
-
it 'sets the value of manual option to @manual' do
|
30
|
-
adapter = described_class.new(redis_stub, :manual => true)
|
31
|
-
adapter.should be_manual
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe Inferx::Adapter, '#categories_key' do
|
37
|
-
it "calls #{described_class}#make_category_key" do
|
38
|
-
adapter = described_class.new(redis_stub)
|
39
|
-
adapter.should_receive(:make_categories_key)
|
40
|
-
adapter.categories_key
|
41
|
-
end
|
42
|
-
|
43
|
-
it "calls #{described_class}#make_category_key once in same instance" do
|
44
|
-
adapter = described_class.new(redis_stub)
|
45
|
-
adapter.should_receive(:make_categories_key).and_return('inferx:categories')
|
46
|
-
adapter.categories_key
|
47
|
-
adapter.categories_key
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe Inferx::Adapter, '#make_categories_key' do
|
52
|
-
it 'returns the key for access to categories' do
|
53
|
-
adapter = described_class.new(redis_stub)
|
54
|
-
adapter.categories_key.should == 'inferx:categories'
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'with namespace' do
|
58
|
-
it 'returns the key included the namespace' do
|
59
|
-
adapter = described_class.new(redis_stub, :namespace => 'example')
|
60
|
-
adapter.categories_key.should == 'inferx:example:categories'
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe Inferx::Adapter, '#make_category_key' do
|
66
|
-
it 'returns the key for access to scores stored each by word' do
|
67
|
-
adapter = described_class.new(redis_stub)
|
68
|
-
adapter.make_category_key('red').should == 'inferx:categories:red'
|
69
|
-
end
|
70
|
-
|
71
|
-
context 'with namespace' do
|
72
|
-
it 'returns the key included the namespace' do
|
73
|
-
adapter = described_class.new(redis_stub, :namespace => 'example')
|
74
|
-
adapter.make_category_key('red').should == 'inferx:example:categories:red'
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe Inferx::Adapter, '#spawn' do
|
80
|
-
it 'calls constructor of the class with the instance variables and the arguments' do
|
81
|
-
redis = redis_stub
|
82
|
-
adapter = described_class.new(redis, :namespace => 'example')
|
83
|
-
klass = mock.tap { |m| m.should_receive(:new).with(redis, 'arg1', 'arg2', :namespace => 'example') }
|
84
|
-
adapter.spawn(klass, 'arg1', 'arg2')
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'returns an instance of the class' do
|
88
|
-
adapter = described_class.new(redis_stub)
|
89
|
-
klass = stub.tap { |s| s.stub!(:new => 'klass') }
|
90
|
-
adapter.spawn(klass).should == 'klass'
|
91
|
-
end
|
92
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'inferx/complementary/categories'
|
3
|
-
|
4
|
-
describe Inferx::Complementary::Categories do
|
5
|
-
it 'inherits Inferx::Categories' do
|
6
|
-
described_class.superclass.should == Inferx::Categories
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
describe Inferx::Complementary::Categories, '#spawn_category' do
|
11
|
-
before do
|
12
|
-
@categories = described_class.new(redis_stub).tap do |s|
|
13
|
-
s.stub!(:spawn => 'category')
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'calls #spawn with Inferx::Complementary::Category, the categories and the arguments' do
|
18
|
-
@categories.should_receive(:spawn).with(Inferx::Complementary::Category, 'arg1', 'arg2')
|
19
|
-
@categories.__send__(:spawn_category, 'arg1', 'arg2')
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'returns the return value from #spawn' do
|
23
|
-
@categories.__send__(:spawn_category, 'arg1', 'arg2').should == 'category'
|
24
|
-
end
|
25
|
-
end
|
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'inferx/complementary/category'
|
2
|
-
|
3
|
-
describe Inferx::Complementary::Category, '#ready_to_inject' do
|
4
|
-
it 'calls #inject with the words to inject block' do
|
5
|
-
category = described_class.new(redis_stub, 'red', 2)
|
6
|
-
category.should_receive(:inject).with(%w(word1 word2 word3))
|
7
|
-
|
8
|
-
category.ready_to_inject do |inject|
|
9
|
-
inject[%w(word1)]
|
10
|
-
inject[%w(word2)]
|
11
|
-
inject[%w(word3)]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe Inferx::Complementary::Category, '#ready_to_eject' do
|
17
|
-
it 'calls #eject with the words to eject block' do
|
18
|
-
category = described_class.new(redis_stub, 'red', 2)
|
19
|
-
category.should_receive(:eject).with(%w(word1 word2 word3))
|
20
|
-
|
21
|
-
category.ready_to_eject do |eject|
|
22
|
-
eject[%w(word1)]
|
23
|
-
eject[%w(word2)]
|
24
|
-
eject[%w(word3)]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe Inferx::Complementary::Category, '#train' do
|
30
|
-
it 'calls Redis#zincrby and Redis#hincrby for other categories' do
|
31
|
-
redis = redis_stub do |s|
|
32
|
-
s.stub!(:hkeys => %w(red green blue))
|
33
|
-
s.should_receive(:zincrby).with('inferx:categories:green', 2, 'apple')
|
34
|
-
s.should_receive(:zincrby).with('inferx:categories:green', 3, 'strawberry')
|
35
|
-
s.should_receive(:hincrby).with('inferx:categories', 'green', 5)
|
36
|
-
s.should_receive(:zincrby).with('inferx:categories:blue', 2, 'apple')
|
37
|
-
s.should_receive(:zincrby).with('inferx:categories:blue', 3, 'strawberry')
|
38
|
-
s.should_receive(:hincrby).with('inferx:categories', 'blue', 5)
|
39
|
-
s.should_receive(:save)
|
40
|
-
end
|
41
|
-
|
42
|
-
category = described_class.new(redis, 'red', 2)
|
43
|
-
category.train(%w(apple strawberry apple strawberry strawberry))
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'with no update' do
|
47
|
-
it 'does not call Redis#hincrby' do
|
48
|
-
redis = redis_stub do |s|
|
49
|
-
s.should_not_receive(:hincrby)
|
50
|
-
s.should_not_receive(:save)
|
51
|
-
end
|
52
|
-
|
53
|
-
category = described_class.new(redis, 'red', 2)
|
54
|
-
category.train([])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'with manual save' do
|
59
|
-
it 'does not call Redis#save' do
|
60
|
-
redis = redis_stub do |s|
|
61
|
-
s.stub!(:hkeys => %w(red green blue))
|
62
|
-
s.stub!(:zincrby)
|
63
|
-
s.stub!(:hincrby)
|
64
|
-
s.should_not_receive(:save)
|
65
|
-
end
|
66
|
-
|
67
|
-
category = described_class.new(redis, 'red', 2, :manual => true)
|
68
|
-
category.train(%w(apple strawberry apple strawberry strawberry))
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe Inferx::Complementary::Category, '#untrain' do
|
74
|
-
it 'calls Redis#zincrby, Redis#zremrangebyscore and Redis#hincrby for other categories' do
|
75
|
-
redis = redis_stub do |s|
|
76
|
-
s.stub!(:hkeys => %w(red green blue))
|
77
|
-
|
78
|
-
s.stub!(:pipelined).and_return do |&block|
|
79
|
-
block.call
|
80
|
-
%w(1 1 0 2 -1 1)
|
81
|
-
end
|
82
|
-
|
83
|
-
s.should_receive(:zincrby).with('inferx:categories:green', -2, 'apple')
|
84
|
-
s.should_receive(:zincrby).with('inferx:categories:green', -3, 'strawberry')
|
85
|
-
s.should_receive(:zremrangebyscore).with('inferx:categories:green', '-inf', 0)
|
86
|
-
s.should_receive(:zincrby).with('inferx:categories:blue', -2, 'apple')
|
87
|
-
s.should_receive(:zincrby).with('inferx:categories:blue', -3, 'strawberry')
|
88
|
-
s.should_receive(:zremrangebyscore).with('inferx:categories:blue', '-inf', 0)
|
89
|
-
s.should_receive(:hincrby).with('inferx:categories', 'green', -5)
|
90
|
-
s.should_receive(:hincrby).with('inferx:categories', 'blue', -4)
|
91
|
-
s.should_receive(:save)
|
92
|
-
end
|
93
|
-
|
94
|
-
category = described_class.new(redis, 'red', 2)
|
95
|
-
category.untrain(%w(apple strawberry apple strawberry strawberry))
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'with no update' do
|
99
|
-
it 'does not call Redis#zremrangebyscore and Redis#hincrby' do
|
100
|
-
redis = redis_stub do |s|
|
101
|
-
s.stub!(:hkeys => %w(red green blue))
|
102
|
-
|
103
|
-
s.stub!(:pipelined).and_return do |&block|
|
104
|
-
block.call
|
105
|
-
%w(-3 -2 2 -3 -2 2)
|
106
|
-
end
|
107
|
-
|
108
|
-
s.stub!(:zincrby)
|
109
|
-
s.stub!(:zremrangebyscore)
|
110
|
-
s.should_not_receive(:hincrby)
|
111
|
-
s.should_not_receive(:save)
|
112
|
-
end
|
113
|
-
|
114
|
-
category = described_class.new(redis, 'red', 2)
|
115
|
-
category.untrain([])
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context 'with manual save' do
|
120
|
-
it 'does not call Redis#save' do
|
121
|
-
redis = redis_stub do |s|
|
122
|
-
s.stub!(:hkeys => %w(red green blue))
|
123
|
-
|
124
|
-
s.stub!(:pipelined).and_return do |&block|
|
125
|
-
block.call
|
126
|
-
%w(1 1 0 2 -1 1)
|
127
|
-
end
|
128
|
-
|
129
|
-
s.stub!(:zincrby)
|
130
|
-
s.stub!(:zremrangebyscore)
|
131
|
-
s.stub!(:hincrby)
|
132
|
-
s.should_not_receive(:save)
|
133
|
-
end
|
134
|
-
|
135
|
-
category = described_class.new(redis, 'red', 2, :manual => true)
|
136
|
-
category.untrain(%w(apple strawberry apple strawberry strawberry))
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|