Module: Evoc::Evaluate
- Extended by:
- Logging
- Defined in:
- lib/evoc/evaluate.rb
Class Method Summary
collapse
Methods included from Logging
configure_logger_for, logger, logger_for, set_level
Class Method Details
.ap(rec:, exp: nil) ⇒ Object
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
# File 'lib/evoc/evaluate.rb', line 246
def self.ap(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
i = 0
correct_i = 0
ap = 0
rec.each do |cluster|
cluster.each do |item|
i = i + 1
correct_i = correct_i + item
precision_i = correct_i/i
ap = ap + (precision_i*item)
end
end
if exp.nil?
exp = correct_i
else
if correct_i > exp
raise ArgumentError, "Found more relevant items than the provided number of relevant items"
end
end
return (exp == 0 ? 0 : (ap/exp).to_f)
end
|
.applicable(rec:) ⇒ Object
52
53
54
55
56
57
58
|
# File 'lib/evoc/evaluate.rb', line 52
def self.applicable(rec:)
if rec.is_a?(Array)
(rec <=> []).abs
else
raise Evoc::Exceptions::FormatError.new "Wrong format given to #{__method__}, expected an array, input was: #{input}"
end
end
|
.average_precision(recommendation, expected_outcome) ⇒ Float
calculate the average precision of the result based on an expected outcome
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
|
# File 'lib/evoc/evaluate.rb', line 281
def self.average_precision(recommendation,expected_outcome)
raise Error.new "#average_precision has been deprecated, use #ap instead"
if !expected_outcome.is_a?(Array) then expected_outcome = [expected_outcome] end
if (expected_outcome.size > 0) & !recommendation.empty?
average_precision = 0
correct_items = []
total_items_considered = []
recommendation.each do |items|
if !items.is_a?(Array) then items = [items] end
if items.first.class != expected_outcome.first.class
raise ArgumentError, "Expected outcome was of type #{expected_outcome.first.class}, while the item in the recommendation was of type #{items.first.class}"
end
if (new_items = items - total_items_considered).size > 0
new_items.each {|item| total_items_considered << item}
if correct_in_rule = (items & expected_outcome)
if correct_in_rule.size > 0
new_correct = (correct_in_rule - correct_items)
new_correct.each {|item| correct_items << item}
change_in_recall = new_correct.size.to_r/expected_outcome.size
precision_at_k = correct_items.size.to_r/total_items_considered.size
average_precision += (precision_at_k * change_in_recall)
end
end
end
end
average_precision.to_f
else
nil
end
end
|
.discernibility(rec:) ⇒ Object
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/evoc/evaluate.rb', line 32
def self.discernibility(rec:)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
rec_size = 0
rec_clusters = 0
rec.each do |c|
rec_clusters = rec_clusters + 1
c.each do |e|
rec_size = rec_size + 1
end
end
return (rec_clusters/rec_size).to_f
end
|
.f1(rec:, exp:) ⇒ Object
Returns the f1 score (preision/recall harmonic mean).
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
# File 'lib/evoc/evaluate.rb', line 62
def self.f1(rec:,exp:)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
rec_size = 0
rec_correct = 0
rec.each do |c|
c.each do |e|
rec_size = rec_size + 1
rec_correct = rec_correct + e
end
end
return (2*rec_correct/(rec_size + exp)).to_f
end
|
.first_relevant(rec:) ⇒ Object
Returns the rank of the first relevant itemjk.
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/evoc/evaluate.rb', line 105
def self.first_relevant(rec:)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
last_checked = 1
rec.each do |c|
c.each do |e|
if e == 1
return last_checked
end
last_checked = last_checked + 1
end
end
return nil
end
|
.last_relevant(rec:) ⇒ Object
Returns the rank of the last relevant itemjk.
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/evoc/evaluate.rb', line 126
def self.last_relevant(rec:)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
size = rec.inject(0) {|sum,c| sum + c.size}
last_checked = size
rec.reverse_each do |c|
c.reverse_each do |e|
if e == 1
return last_checked
end
last_checked = last_checked - 1
end
end
return nil
end
|
.mean_confidence(rules:) ⇒ Object
23
24
25
26
|
# File 'lib/evoc/evaluate.rb', line 23
def self.mean_confidence(rules:)
if rules.empty? then return nil end
return (rules.inject(0) {|sum,r| sum + r.m_confidence.value}/rules.size).to_f
end
|
.mean_confidence10(rules:) ⇒ Object
28
29
30
|
# File 'lib/evoc/evaluate.rb', line 28
def self.mean_confidence10(rules:)
return self.mean_confidence(rules: Evoc::RuleStore.sort_on(rules: rules,measures: ['m_confidence']).take(10).flatten.take(10))
end
|
.mean_support(rules:) ⇒ Object
14
15
16
17
|
# File 'lib/evoc/evaluate.rb', line 14
def self.mean_support(rules:)
if rules.empty? then return nil end
return (rules.inject(0) {|sum,r| sum + r.m_support.value}/rules.size).to_f
end
|
.mean_support10(rules:) ⇒ Object
19
20
21
|
# File 'lib/evoc/evaluate.rb', line 19
def self.mean_support10(rules:)
return self.mean_support(rules: Evoc::RuleStore.sort_on(rules: rules,measures: ['m_support']).take(10).flatten.take(10))
end
|
.precision(rec:, exp: nil) ⇒ Object
164
165
166
167
168
169
170
171
172
173
174
175
|
# File 'lib/evoc/evaluate.rb', line 164
def self.precision(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
size_rec = rec.inject(0) {|sum,c| sum + c.size}
num_correct_in_rec = rec.inject(0) {|sum,c| sum + c.inject(&:+)}
return (num_correct_in_rec/size_rec).to_f
end
|
.precision10(rec:, exp: nil) ⇒ Object
155
156
157
158
159
160
161
162
|
# File 'lib/evoc/evaluate.rb', line 155
def self.precision10(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
return self.precision(rec: [rec.take(10).flatten.take(10)])
end
|
.recall(rec:, exp: nil) ⇒ Object
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/evoc/evaluate.rb', line 177
def self.recall(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
num_correct_in_rec = rec.inject(0) {|sum,c| sum + c.inject(&:+)}
if exp.nil?
return num_correct_in_rec
else
if num_correct_in_rec > exp
raise ArgumentError, "Found more relevant items than the provided number of relevant items"
end
return (num_correct_in_rec/exp).to_f
end
end
|
.recall10(rec:, exp: nil) ⇒ Object
146
147
148
149
150
151
152
153
|
# File 'lib/evoc/evaluate.rb', line 146
def self.recall10(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
return self.recall(rec: [rec.take(10).flatten.take(10)],exp: exp)
end
|
.relevant_ranks(rec:) ⇒ Object
Returns an array containg the rank of each consequtive expected outcome.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/evoc/evaluate.rb', line 83
def self.relevant_ranks(rec:)
if rec.is_a?(Array) && rec.empty? return []
end
self.validateInput(rec)
ranks = []
last_checked = 1
rec.each do |c|
c.each do |e|
if e == 1
ranks << last_checked
end
last_checked = last_checked + 1
end
end
return ranks
end
|
.t_ap(rec:, exp: nil) ⇒ Object
r_p : relevant items in previous groups i_p : index previous group r_g : relevant items in group n_g : items in group i : index of current item
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
# File 'lib/evoc/evaluate.rb', line 205
def self.t_ap(rec:,exp: nil)
if rec.is_a?(Array) && rec.empty? return nil
end
self.validateInput(rec)
ap = 0
r_p = 0
i_p = 0
rec.each do |cluster|
r_g = cluster.inject(&:+).to_r
n_g = cluster.size.to_r
cluster.each_with_index do |_,i|
i = i_p + i + 1
chance_relevant = r_g/n_g
avg_previous_rel = if (n_g == 1)
(r_p + 1) * (1/i)
else
(r_p + (i - i_p - 1)*((r_g-1)/(n_g-1)) + 1) * (1/i)
end
item_ap_contribution = chance_relevant * avg_previous_rel
ap = ap + item_ap_contribution
end
r_p = r_p + r_g
i_p = i_p + n_g
end
if exp.nil?
exp = r_p
else
if r_p > exp
raise ArgumentError, "Found more relevant items than the provided number of relevant items"
end
end
return (r_p == 0 ? 0 : (ap/exp).to_f)
end
|
5
6
7
8
9
10
11
12
|
# File 'lib/evoc/evaluate.rb', line 5
def self.validateInput(input)
if !input.is_a?(Array) || !input.first.is_a?(Array) || ![0,1].include?(input.first.first) raise Evoc::Exceptions::FormatError.new "Wrong format given to #{__method__}, expected list of list of 0s and 1s, input was: #{input}"
end
end
|