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 +7 -0
- data/LICENSE.rdoc +59 -0
- data/README.rdoc +103 -0
- data/bin/svm-demo +354 -0
- data/lib/PlotPackage.jar +0 -0
- data/lib/libsvm.jar +0 -0
- data/lib/svm_toolkit/evaluators.rb +169 -0
- data/lib/svm_toolkit/model.rb +124 -0
- data/lib/svm_toolkit/node.rb +21 -0
- data/lib/svm_toolkit/parameter.rb +117 -0
- data/lib/svm_toolkit/problem.rb +308 -0
- data/lib/svm_toolkit/svm.rb +224 -0
- data/lib/svm_toolkit.rb +37 -0
- metadata +79 -0
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
|
+
|
data/lib/PlotPackage.jar
ADDED
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
|
+
|