svm_toolkit 1.1.7-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 573f621dd03d73aa37c8ac0f65ef5bedd70fe3831f538ab5977685578979688e
4
+ data.tar.gz: 1ddbc97a37507768149f19cb7097a1277287726f4436ab04a45c70227f977895
5
+ SHA512:
6
+ metadata.gz: 9a5e17905c86237e6586df1df7d06ff2f5bfcdcabf38e03f4a53bb647030a32f4e16fc03616ca9f98dff6cebe16d2df25d687477003e544f06d8712b016a1c00
7
+ data.tar.gz: 8b9798b3d37eba4e24f080a807a2b44c5cba885e4b1aad97956d9fbd5eede6866dbc5b990467da327d2a5cd28a58392e7a5d36788958799a9063634e80a9f57c
data/LICENSE.rdoc ADDED
@@ -0,0 +1,59 @@
1
+ = MIT License
2
+
3
+ Copyright (c) 2011-20, Peter Lane
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+
24
+ = For libsvm:
25
+
26
+ Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin
27
+ All rights reserved.
28
+
29
+ Redistribution and use in source and binary forms, with or without
30
+ modification, are permitted provided that the following conditions
31
+ are met:
32
+
33
+ 1. Redistributions of source code must retain the above copyright
34
+ notice, this list of conditions and the following disclaimer.
35
+
36
+ 2. Redistributions in binary form must reproduce the above copyright
37
+ notice, this list of conditions and the following disclaimer in the
38
+ documentation and/or other materials provided with the distribution.
39
+
40
+ 3. Neither name of copyright holders nor the names of its contributors
41
+ may be used to endorse or promote products derived from this software
42
+ without specific prior written permission.
43
+
44
+
45
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
49
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
+
57
+ = For PlotPackage:
58
+
59
+ Library General Public License (http://www.gnu.org/copyleft/lgpl.html)
data/README.rdoc ADDED
@@ -0,0 +1,103 @@
1
+ = SVM Toolkit
2
+
3
+ source:: https://notabug.org/peterlane/svm_toolkit/
4
+
5
+ == Description
6
+
7
+ Support-vector machines are a popular tool in data mining. This package
8
+ includes an amended version of the Java implementation of the libsvm library
9
+ (version 3.11). Additional methods and examples are provided to support
10
+ standard training techniques, such as cross-validation, and simple
11
+ visualisations. Training/testing of models can use a variety of built-in or
12
+ user-defined evaluation methods, including overall accuracy, geometric mean,
13
+ precision and recall.
14
+
15
+ == Features
16
+
17
+ - All features of LibSVM 3.11 are supported, and many are augmented with Ruby wrappers.
18
+ - Loading Problem definitions from file in Svmlight, Csv or Arff (simple subset) format.
19
+ - Creating Problem definitions from values supplied programmatically in arrays.
20
+ - Rescaling of feature values.
21
+ - Integrated cost/gamma search for model with RBF kernel, taking advantage of multiple cores.
22
+ - Contour plot visualisation of cost/gamma search results.
23
+ - Model provides value of w-squared for hyperplane.
24
+ - svm-demo application, a version of the svm_toy applet which comes with libsvm.
25
+ - Model stores indices of training instances used as support vectors.
26
+ - User-selected evaluation techniques supported in Model#evaluate_dataset and
27
+ Svm.cross_validation_search.
28
+ - Library provides evaluation classes for Cohen's Kappa statistics, F-measure,
29
+ geometric-mean, Matthews Correlation Coefficient, overall-accuracy,
30
+ precision, and recall.
31
+
32
+ == Example
33
+
34
+ The following example illustrates how a dataset can be constructed in code, and
35
+ an SVM model created and tested against the different kernels.
36
+
37
+ require "svm_toolkit"
38
+ include SvmToolkit
39
+
40
+ puts "Classification with LIBSVM"
41
+ puts "--------------------------"
42
+
43
+ # Sample dataset: the 'Play Tennis' dataset
44
+ # from T. Mitchell, Machine Learning (1997)
45
+ # --------------------------------------------
46
+ # Labels for each instance in the training set
47
+ # 1 = Play, 0 = Not
48
+ Labels = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0]
49
+
50
+ # Recoding the attribute values into range [0, 1]
51
+ Instances = [
52
+ [0.0,1.0,1.0,0.0],
53
+ [0.0,1.0,1.0,1.0],
54
+ [0.5,1.0,1.0,0.0],
55
+ [1.0,0.5,1.0,0.0],
56
+ [1.0,0.0,0.0,0.0],
57
+ [1.0,0.0,0.0,1.0],
58
+ [0.5,0.0,0.0,1.0],
59
+ [0.0,0.5,1.0,0.0],
60
+ [0.0,0.0,0.0,0.0],
61
+ [1.0,0.5,0.0,0.0],
62
+ [0.0,0.5,0.0,1.0],
63
+ [0.5,0.5,1.0,1.0],
64
+ [0.5,1.0,0.0,0.0],
65
+ [1.0,0.5,1.0,1.0]
66
+ ]
67
+
68
+ # create some arbitrary train/test split
69
+ TrainingSet = Problem.from_array(Instances.slice(0, 10), Labels.slice(0, 10))
70
+ TestSet = Problem.from_array(Instances.slice(10, 4), Labels.slice(10, 4))
71
+
72
+ # Iterate over each kernel type
73
+ Parameter.kernels.each do |kernel|
74
+
75
+ # -- train model for this kernel type
76
+ params = Parameter.new(
77
+ :svm_type => Parameter::C_SVC,
78
+ :kernel_type => kernel,
79
+ :cost => 10,
80
+ :degree => 1,
81
+ :gamma => 100
82
+ )
83
+ model = Svm.svm_train(TrainingSet, params)
84
+
85
+ # -- test kernel performance on the training set
86
+ errors = model.evaluate_dataset(TrainingSet, :print_results => true)
87
+ puts "Kernel #{Parameter.kernel_name(kernel)} has #{errors} on the training set"
88
+
89
+ # -- test kernel performance on the test set
90
+ errors = model.evaluate_dataset(TestSet, :print_results => true)
91
+ puts "Kernel #{Parameter.kernel_name(kernel)} has #{errors} on the test set"
92
+ end
93
+
94
+ More examples can be found in the source code, linked above.
95
+
96
+ == Acknowledgements
97
+
98
+ The svm_toolkit is based on LibSVM, which is available from:
99
+ http://www.csie.ntu.edu.tw/~cjlin/libsvm/
100
+
101
+ The contour plot uses the PlotPackage library, available from:
102
+ http://thehuwaldtfamily.org/java/Packages/Plot/PlotPackage.html
103
+
data/bin/svm-demo ADDED
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ #
4
+ # A loose equivalent of the svm_toy applet which is
5
+ # distributed with libsvm.
6
+ #
7
+
8
+ require "java"
9
+ require "svm-toolkit"
10
+ include SvmToolkit
11
+
12
+ ["BorderLayout", "Color",
13
+ "Dimension", "GridLayout",
14
+ "event.ActionListener", "event.MouseListener"
15
+ ].each do |i|
16
+ import "java.awt.#{i}"
17
+ end
18
+
19
+ ["Box", "BoxLayout", "JButton", "JComboBox", "JFrame", "JLabel",
20
+ "JOptionPane", "JPanel", "JScrollPane", "JSpinner", "JTextField",
21
+ "SpinnerNumberModel", "WindowConstants", "border.TitledBorder"
22
+ ].each do |i|
23
+ import "javax.swing.#{i}"
24
+ end
25
+
26
+ class Display < JPanel
27
+ Point = Struct.new(:x, :y, :colour)
28
+
29
+ class MyMouseListener
30
+ include MouseListener
31
+
32
+ def initialize parent
33
+ @parent = parent
34
+ end
35
+
36
+ def mouseEntered e; end
37
+ def mouseExited e; end
38
+ def mousePressed e; end
39
+ def mouseReleased e; end
40
+
41
+ def mouseClicked e
42
+ @parent.clicked(e.x, e.y)
43
+ end
44
+ end
45
+
46
+ attr_accessor :colour # current label/colour of point to show
47
+
48
+ Width = 800
49
+ Height = 600
50
+
51
+ def initialize
52
+ super()
53
+
54
+ self.preferred_size = Dimension.new(Width, Height)
55
+ add_mouse_listener MyMouseListener.new(self)
56
+
57
+ @points = []
58
+ @support_vectors = []
59
+ @colour = Color.blue
60
+ end
61
+
62
+ def paint g
63
+ super
64
+
65
+ if @buffer.nil?
66
+ g.background = Color.lightGray
67
+ g.clear_rect(0, 0, Width, Height)
68
+ else
69
+ g.draw_image(@buffer, 0, 0, self)
70
+ end
71
+
72
+ @support_vectors.each do |point|
73
+ g.color = Color.yellow
74
+ g.fill_oval(point.x-7, point.y-7, 14, 14)
75
+ end
76
+
77
+ @points.each do |point|
78
+ g.color = point.colour
79
+ g.fill_oval(point.x-3, point.y-3, 6, 6)
80
+ end
81
+ end
82
+
83
+ def clear
84
+ @points.clear
85
+ @support_vectors.clear
86
+ @buffer = nil
87
+ repaint
88
+ end
89
+
90
+ def clicked(x, y)
91
+ if x < Width and y < Height
92
+ @points << Point.new(x, y, @colour)
93
+ repaint
94
+ end
95
+ end
96
+
97
+ def background_colour prediction
98
+ if prediction.zero?
99
+ Color.new(100, 200, 100)
100
+ else
101
+ Color.new(100, 100, 200)
102
+ end
103
+ end
104
+
105
+ def train(kernel, cost, gamma, degree)
106
+ return if @points.empty?
107
+ labels = []
108
+ instances = []
109
+ @points.each do |point|
110
+ if point.colour == Color::blue
111
+ labels << 1
112
+ else
113
+ labels << 0
114
+ end
115
+ instances << [point.x / Width.to_f, point.y / Height.to_f]
116
+ end
117
+ problem = Problem.from_array(instances, labels)
118
+ param = Parameter.new(
119
+ :svm_type => Parameter::C_SVC,
120
+ :kernel_type => kernel,
121
+ :cost => cost,
122
+ :gamma => gamma,
123
+ :degree => degree
124
+ )
125
+ model = Svm.svm_train(problem, param)
126
+
127
+ buffer = self.create_image(Width, Height)
128
+ buffer_gc = buffer.graphics
129
+ window_gc = self.graphics
130
+ instance = Node[2].new
131
+ instance[0] = Node.new(0, 0)
132
+ instance[1] = Node.new(1, 0)
133
+ Width.times do |i|
134
+ if i < 498 # draw a progress line
135
+ buffer_gc.color = Color::red
136
+ buffer_gc.draw_line(i+1, 0, i+1, Height-1)
137
+ window_gc.color = Color::red
138
+ window_gc.draw_line(i+1, 0, i+1, Height-1)
139
+ end
140
+ Height.times do |j|
141
+ instance[0].value = i / Width.to_f
142
+ instance[1].value = j / Height.to_f
143
+ prediction = Svm.svm_predict(model, instance)
144
+ buffer_gc.color = background_colour prediction
145
+ buffer_gc.draw_line(i, j, i, j)
146
+ window_gc.color = background_colour prediction
147
+ window_gc.draw_line(i, j, i, j)
148
+ end
149
+ end
150
+ @buffer = buffer
151
+ @support_vectors = []
152
+ model.support_vector_indices.each do |index|
153
+ @support_vectors << @points[index]
154
+ end
155
+
156
+ repaint
157
+ end
158
+ end
159
+
160
+ class DemoFrame < JFrame
161
+ class LabelListener
162
+ include ActionListener
163
+
164
+ def initialize(display, box)
165
+ @display = display
166
+ @box = box
167
+ end
168
+
169
+ def actionPerformed e
170
+ @display.colour = if @box.selected_item == "blue" then
171
+ Color.blue
172
+ else
173
+ Color.green
174
+ end
175
+ end
176
+ end
177
+
178
+ class KernelChoiceListener
179
+ include ActionListener
180
+
181
+ def initialize(kernel_choice, gamma_choice, degree_choice)
182
+ @kernel_choice = kernel_choice
183
+ @gamma_choice = gamma_choice
184
+ @degree_choice = degree_choice
185
+ end
186
+
187
+ def actionPerformed e
188
+ case @kernel_choice.selected_item
189
+ when "linear"
190
+ @gamma_choice.enabled = false
191
+ @degree_choice.enabled = false
192
+ when "polynomial"
193
+ @gamma_choice.enabled = false
194
+ @degree_choice.enabled = true
195
+ when "RBF", "sigmoid"
196
+ @gamma_choice.enabled = true
197
+ @degree_choice.enabled = false
198
+ end
199
+ end
200
+ end
201
+
202
+ def initialize
203
+ super("Support-Vector Machines: Demonstration")
204
+ self.setSize(700, 400)
205
+
206
+ @display_panel = Display.new
207
+ add(JScrollPane.new(@display_panel))
208
+ add(createLabelButtons, BorderLayout::NORTH)
209
+ add(createTrainButtons, BorderLayout::EAST)
210
+ add(createHelpLine, BorderLayout::SOUTH)
211
+
212
+ self.setDefaultCloseOperation(WindowConstants::DISPOSE_ON_CLOSE)
213
+ end
214
+
215
+ def createHelpLine
216
+ JLabel.new(<<-END)
217
+ <html><body>
218
+ Select a class colour and click on main panel to define instances.<br>
219
+ Choose kernel type and parameter settings for training.
220
+ </body></html>
221
+ END
222
+ end
223
+
224
+ def createLabelButtons
225
+ panel = JPanel.new
226
+ panel.layout = BorderLayout.new
227
+
228
+ combo_box = JComboBox.new
229
+ ["blue", "green"].each do |item|
230
+ combo_box.add_item item
231
+ end
232
+ combo_box.add_action_listener LabelListener.new(@display_panel, combo_box)
233
+
234
+ clear_button = JButton.new "clear"
235
+ clear_button.add_action_listener do
236
+ @display_panel.clear
237
+ end
238
+
239
+ @message = JLabel.new
240
+
241
+ pane = JPanel.new
242
+ pane.add JLabel.new("Class:")
243
+ pane.add combo_box
244
+ pane.add clear_button
245
+
246
+ panel.add(pane, BorderLayout::WEST)
247
+ panel.add @message
248
+
249
+ return panel
250
+ end
251
+
252
+ def createTrainButtons
253
+ kernel_choice = JComboBox.new
254
+ ["linear", "RBF", "polynomial", "sigmoid"].each do |item|
255
+ kernel_choice.add_item item
256
+ end
257
+ cost_choice = JTextField.new(10)
258
+ cost_choice.text = "1.0"
259
+ cost_choice.setMaximumSize(cost_choice.getPreferredSize)
260
+ gamma_choice = JTextField.new(10)
261
+ gamma_choice.text = "1.0"
262
+ gamma_choice.setMaximumSize(gamma_choice.getPreferredSize)
263
+ gamma_choice.enabled = false
264
+ degree_choice = JSpinner.new(SpinnerNumberModel.new(1, 0, 30, 1))
265
+ degree_choice.enabled = false
266
+ kernel_choice.add_action_listener KernelChoiceListener.new(kernel_choice, gamma_choice, degree_choice)
267
+
268
+ run_button = JButton.new "Train"
269
+ run_button.add_action_listener do
270
+ # -- kernel
271
+ case kernel_choice.selected_item
272
+ when "linear"
273
+ kernel = Parameter::LINEAR
274
+ when "RBF"
275
+ kernel = Parameter::RBF
276
+ when "polynomial"
277
+ kernel = Parameter::POLY
278
+ when "sigmoid"
279
+ kernel = Parameter::SIGMOID
280
+ end
281
+ # -- cost
282
+ begin
283
+ cost = Float cost_choice.text
284
+ rescue ArgumentError
285
+ JOptionPane.show_message_dialog(self,
286
+ "Cost value #{cost_choice.text} is not a number",
287
+ "Error in cost value",
288
+ JOptionPane::ERROR_MESSAGE)
289
+ return
290
+ end
291
+ # -- gamma
292
+ begin
293
+ gamma = Float gamma_choice.text
294
+ rescue ArgumentError
295
+ JOptionPane.show_message_dialog(self,
296
+ "Gamma value #{gamma_choice.text} is not a number",
297
+ "Error in gamma value",
298
+ JOptionPane::ERROR_MESSAGE)
299
+ return
300
+ end
301
+ # -- degree
302
+ degree = degree_choice.model.number
303
+ #
304
+ @message.text = "Training and updating display: Please wait"
305
+ swt = MySwingWorker.new
306
+ swt.task = lambda do
307
+ run_button.enabled = false
308
+ @display_panel.train(kernel, cost, gamma, degree)
309
+ @message.text = ""
310
+ run_button.enabled = true
311
+ end
312
+ swt.execute
313
+ end
314
+
315
+ panel = JPanel.new
316
+ panel.border = TitledBorder.new("Training options")
317
+ panel.layout = GridLayout.new(5, 2, 10, 10)
318
+
319
+ panel.add JLabel.new("Kernel type:", JLabel::RIGHT)
320
+ panel.add kernel_choice
321
+ panel.add JLabel.new("Cost:", JLabel::RIGHT)
322
+ panel.add cost_choice
323
+ panel.add JLabel.new("Gamma:", JLabel::RIGHT)
324
+ panel.add gamma_choice
325
+ panel.add JLabel.new("Degree:", JLabel::RIGHT)
326
+ panel.add degree_choice
327
+ panel.add JLabel.new ""
328
+ panel.add run_button
329
+
330
+ pane = JPanel.new
331
+ pane.add panel
332
+ return pane
333
+ end
334
+
335
+ class MySwingWorker < javax.swing.SwingWorker
336
+ attr_accessor :task
337
+ def doInBackground
338
+ @task.call
339
+ end
340
+ end
341
+ end
342
+
343
+ javax.swing::UIManager.getInstalledLookAndFeels.each do |info|
344
+ begin
345
+ if "Nimbus" == info.name
346
+ javax.swing::UIManager.setLookAndFeel(info.className)
347
+ end
348
+ rescue Exception
349
+ # ignore exceptions
350
+ end
351
+ end
352
+
353
+ DemoFrame.new.visible = true
354
+
Binary file
data/lib/libsvm.jar ADDED
Binary file
@@ -0,0 +1,169 @@
1
+ module SvmToolkit
2
+
3
+ # The Evaluator classes provides some classes and methods to construct
4
+ # classes for evaluating the performance of a model against a dataset.
5
+ # Different evaluators measure different kinds of performance.
6
+ #
7
+ # Evaluator classes are accessed by name, with an optional positive label name.
8
+ # For example:
9
+ #
10
+ # Evaluator::OverallAccuracy # => class evaluates overall accuracy
11
+ # Evaluator::ClassPrecision(label) # => class evaluates precision for class "label"
12
+ #
13
+ # Evaluators are wrapped around confusion matrices, outputting the required
14
+ # statistical measure, and support the following methods:
15
+ #
16
+ # add_result(actual, prediction):: called to add information about each instance
17
+ # when testing a model.
18
+ # value:: retrieves the appropriate measure of performance, based on the class name.
19
+ # to_s:: returns a string naming the evaluator and giving its value.
20
+ #
21
+ class Evaluator
22
+
23
+ # Defines an Evaluator returning the value of precision for given class
24
+ # label.
25
+ #
26
+ def Evaluator.ClassPrecision label
27
+ Class.new(Evaluator) do
28
+ @@label = label
29
+
30
+ # Returns the precision.
31
+ #
32
+ def value
33
+ @cm.precision(@@label)
34
+ end
35
+
36
+ def to_s # :nodoc:
37
+ "Precision for label #{@@label}: #{value}"
38
+ end
39
+ end
40
+ end
41
+
42
+ # Defines an Evaluator returning the value of recall for given class
43
+ # label.
44
+ #
45
+ def Evaluator.ClassRecall label
46
+ Class.new(Evaluator) do
47
+ @@label = label
48
+
49
+ def value # :nodoc:
50
+ @cm.recall(@@label)
51
+ end
52
+
53
+ def to_s # :nodoc:
54
+ "Recall for label #{@@label}: #{value}"
55
+ end
56
+ end
57
+ end
58
+
59
+ # Defines an Evaluator returning the value of the F-measure for given class
60
+ # label.
61
+ #
62
+ def Evaluator.FMeasure label
63
+ Class.new(Evaluator) do
64
+ @@label = label
65
+
66
+ def value # :nodoc:
67
+ @cm.f_measure(@@label)
68
+ end
69
+
70
+ def to_s # :nodoc:
71
+ "F-measure for label #{@@label}: #{value}"
72
+ end
73
+ end
74
+ end
75
+
76
+ # Defines an Evaluator returning the value of Cohen's Kappa statistics for
77
+ # given class label.
78
+ #
79
+ def Evaluator.Kappa label
80
+ Class.new(Evaluator) do
81
+ @@label = label
82
+
83
+ def value # :nodoc:
84
+ @cm.kappa(@@label)
85
+ end
86
+
87
+ def to_s # :nodoc:
88
+ "Kappa for label #{@@label}: #{value}"
89
+ end
90
+ end
91
+ end
92
+
93
+ # Defines an Evaluator returning the value of the Matthews Correlation
94
+ # Coefficient for given class label.
95
+ #
96
+ def Evaluator.MatthewsCorrelationCoefficient label
97
+ Class.new(Evaluator) do
98
+ @@label = label
99
+
100
+ def value # :nodoc:
101
+ @cm.matthews_correlation(@@label)
102
+ end
103
+
104
+ def to_s # :nodoc:
105
+ "Matthews correlation coefficient: #{value}"
106
+ end
107
+ end
108
+ end
109
+
110
+ # Creates a new Evaluator, with a confusion matrix to store results.
111
+ #
112
+ def initialize
113
+ @cm = ConfusionMatrix.new
114
+ end
115
+
116
+ # Adds result to the underlying confusion matrix.
117
+ #
118
+ def add_result(actual, prediction)
119
+ @cm.add_for(actual, prediction)
120
+ end
121
+
122
+ # This object is better than given object, if the given object is an
123
+ # instance of nil, or the value of this object is better.
124
+ #
125
+ def better_than? other
126
+ other.nil? or self.value > other.value
127
+ end
128
+
129
+ # Prints the confusion matrix.
130
+ #
131
+ def display
132
+ puts @cm
133
+ end
134
+ end
135
+
136
+ # Defines an Evaluator returning the value of overall accuracy.
137
+ #
138
+ class OverallAccuracy < Evaluator
139
+ # Returns the overall accuracy, as a percentage.
140
+ #
141
+ def value
142
+ 100 * @cm.overall_accuracy
143
+ end
144
+
145
+ # Returns a string naming this evaluator and giving its value.
146
+ #
147
+ def to_s
148
+ "Overall accuracy: #{value}%"
149
+ end
150
+ end
151
+
152
+ # Defines an Evaluator returning the value of geometric mean.
153
+ #
154
+ class GeometricMean < Evaluator
155
+ # Returns the geometric mean.
156
+ #
157
+ def value
158
+ @cm.geometric_mean
159
+ end
160
+
161
+ # Returns a string naming this evaluator and giving its value.
162
+ #
163
+ def to_s
164
+ "Geometric mean: #{value}"
165
+ end
166
+ end
167
+
168
+ end
169
+