svm_toolkit 1.1.7-java

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.
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
+