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