svm_toolkit 1.1.7-java → 1.1.8-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 +4 -4
- data/LICENSE.rdoc +59 -59
- data/README.rdoc +99 -103
- data/bin/svm-demo +354 -354
- data/lib/libsvm.jar +0 -0
- data/lib/svm_toolkit/evaluators.rb +169 -169
- data/lib/svm_toolkit/model.rb +122 -124
- data/lib/svm_toolkit/node.rb +17 -21
- data/lib/svm_toolkit/parameter.rb +114 -117
- data/lib/svm_toolkit/problem.rb +294 -308
- data/lib/svm_toolkit/svm.rb +219 -224
- data/lib/svm_toolkit.rb +37 -37
- metadata +26 -12
data/bin/svm-demo
CHANGED
|
@@ -1,354 +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 "
|
|
10
|
-
include SvmToolkit
|
|
11
|
-
|
|
12
|
-
["BorderLayout", "Color",
|
|
13
|
-
"Dimension", "GridLayout",
|
|
14
|
-
"event.ActionListener", "event.MouseListener"
|
|
15
|
-
].each do |i|
|
|
16
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
java_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
|
+
java_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
|
+
|