svmlab 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/README +219 -0
- data/lib/arraymethods.rb +87 -0
- data/lib/irb.history +100 -0
- data/lib/libsvmdata.rb +122 -0
- data/lib/svmfeature.rb +337 -0
- data/lib/svmfeature2.rb +98 -0
- data/lib/svmlab-config.rb +215 -0
- data/lib/svmlab-irb.rb +98 -0
- data/lib/svmlab-optim.rb +556 -0
- data/lib/svmlab-plot.rb +170 -0
- data/lib/svmlab.rb +365 -0
- data/lib/svmprediction.rb +176 -0
- data/lib/test.cfg +12 -0
- data/lib/test.rb +5 -0
- data/lib/testdata +3 -0
- data/lib/texput.log +20 -0
- data/lib/tmp.irb.rc +81 -0
- data/lib/v6.cfg +124 -0
- metadata +102 -0
data/lib/svmlab-irb.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'irb/completion'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'svmlab'
|
4
|
+
|
5
|
+
#require 'wirble'
|
6
|
+
#Wirble.init
|
7
|
+
#Wirble.colorize
|
8
|
+
|
9
|
+
#IRB.conf[:PROMPT][:SVMLab] = { # name of prompt mode
|
10
|
+
# :PROMPT_I => "SVMLab:%03n:%i> ", # normal prompt
|
11
|
+
# :PROMPT_S => "SVMLab:%03n:%i%l ", # prompt for continuing strings
|
12
|
+
# :PROMPT_C => "SVMLab:%03n:%i* ", # prompt for continuing statement
|
13
|
+
# :RETURN => " ==>%s\n" # format to return value
|
14
|
+
#}
|
15
|
+
ANSI_RESET = "\033[0m"
|
16
|
+
ANSI_GREEN = "\033[2;32m"
|
17
|
+
ANSI_BLUE = "\033[2;34m"
|
18
|
+
|
19
|
+
IRB.conf[:PROMPT][:SVMLab] = { # name of prompt mode
|
20
|
+
#:PROMPT_I => "#{ANSI_BLUE}SVMLab>> #{ANSI_RESET}", # normal prompt
|
21
|
+
:PROMPT_I => "SVMLab > ", # normal prompt
|
22
|
+
:PROMPT_S => " %l ", # prompt for continuing strings
|
23
|
+
:PROMPT_C => " > ", # prompt for continuing statement
|
24
|
+
#:RETURN => "#{ANSI_GREEN} ==> %s\n#{ANSI_RESET}" # format to return value
|
25
|
+
:RETURN => " ==> %s\n" # format to return value
|
26
|
+
}
|
27
|
+
|
28
|
+
IRB.conf[:PROMPT_MODE] = :SVMLab
|
29
|
+
|
30
|
+
|
31
|
+
# Sebastian Delmont
|
32
|
+
# Pretty print methods
|
33
|
+
ANSI_BOLD = "\033[1m"
|
34
|
+
#ANSI_RESET = "\033[0m"
|
35
|
+
ANSI_LGRAY = "\033[0;37m"
|
36
|
+
ANSI_GRAY = "\033[1;30m"
|
37
|
+
|
38
|
+
def pm(obj, *options) # Print methods
|
39
|
+
methods = obj.methods
|
40
|
+
methods -= Object.methods unless options.include? :more
|
41
|
+
filter = options.select {|opt| opt.kind_of? Regexp}.first
|
42
|
+
methods = methods.select {|name| name =~ filter} if filter
|
43
|
+
|
44
|
+
data = methods.sort.collect do |name|
|
45
|
+
method = obj.method(name)
|
46
|
+
if method.arity == 0
|
47
|
+
args = "()"
|
48
|
+
elsif method.arity > 0
|
49
|
+
n = method.arity
|
50
|
+
args = "(#{(1..n).collect {|i| "arg#{i}"}.join(", ")})"
|
51
|
+
elsif method.arity < 0
|
52
|
+
n = -method.arity
|
53
|
+
args = "(#{(1..n).collect {|i| "arg#{i}"}.join(", ")}, ...)"
|
54
|
+
end
|
55
|
+
klass = $1 if method.inspect =~ /Method: (.*?)#/
|
56
|
+
[name, args, klass]
|
57
|
+
end
|
58
|
+
max_name = data.collect {|item| item[0].size}.max
|
59
|
+
max_args = data.collect {|item| item[1].size}.max
|
60
|
+
data.each do |item|
|
61
|
+
print " #{ANSI_BOLD}#{item[0].rjust(max_name)}#{ANSI_RESET}"
|
62
|
+
print "#{ANSI_GRAY}#{item[1].ljust(max_args)}#{ANSI_RESET}"
|
63
|
+
print " #{ANSI_LGRAY}#{item[2]}#{ANSI_RESET}\n"
|
64
|
+
end
|
65
|
+
data.size
|
66
|
+
end
|
67
|
+
|
68
|
+
# To enable history saving between sessions
|
69
|
+
IRB.conf[:SAVE_HISTORY] = 100
|
70
|
+
|
71
|
+
# Stian Haklev / Joel VanderWerf
|
72
|
+
# To reduce lengthy output
|
73
|
+
class IRB::Context
|
74
|
+
attr_accessor :max_output_size
|
75
|
+
|
76
|
+
alias initialize_before_max_output_size initialize
|
77
|
+
def initialize(*args)
|
78
|
+
initialize_before_max_output_size(*args)
|
79
|
+
@max_output_size = IRB.conf[:MAX_OUTPUT_SIZE] || 70
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class IRB::Irb
|
84
|
+
def output_value
|
85
|
+
text =
|
86
|
+
if @context.inspect?
|
87
|
+
sprintf @context.return_format, @context.last_value.inspect
|
88
|
+
else
|
89
|
+
sprintf @context.return_format, @context.last_value
|
90
|
+
end
|
91
|
+
max = @context.max_output_size
|
92
|
+
if text.size < max
|
93
|
+
puts text
|
94
|
+
else
|
95
|
+
puts text[0..max-1] + "..." + text[-2..-1]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/svmlab-optim.rb
ADDED
@@ -0,0 +1,556 @@
|
|
1
|
+
|
2
|
+
#########################################################################################
|
3
|
+
# OPTIMIZATION METHODS
|
4
|
+
#########################################################################################
|
5
|
+
|
6
|
+
|
7
|
+
class SVMLab
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# --- updateConfig! ---
|
12
|
+
# This is the interface between an array of variables
|
13
|
+
# to be changed and a configuration hash.
|
14
|
+
# It is to be used by the pattern search, but this
|
15
|
+
# function knows nothing about pattern search. It is
|
16
|
+
# merely an interface between the hash and the
|
17
|
+
# array describing a point in the search space.
|
18
|
+
# cfg: A hash containing what should be updated.
|
19
|
+
# update: An array of paths to what should be updated
|
20
|
+
# and the new value.
|
21
|
+
# output: The cfg hash with updated values.
|
22
|
+
#
|
23
|
+
# EXAMPLE (yaml representation):
|
24
|
+
# cfg =
|
25
|
+
# ---
|
26
|
+
# a:
|
27
|
+
# a: 0
|
28
|
+
# b: 1
|
29
|
+
# b: 2
|
30
|
+
# update =
|
31
|
+
# ---
|
32
|
+
# - "a : b : 7 : exp1"
|
33
|
+
# - "b : 8 : exp1"
|
34
|
+
def updateConfig!(cfg, steps)
|
35
|
+
# For each variable to be updated
|
36
|
+
steps.each do |upd|
|
37
|
+
# Split the path into its levels
|
38
|
+
path = upd.split(/\s\:\s/)
|
39
|
+
# Check if the current value should be an integer
|
40
|
+
path[-2] = if (p=path[-2]) =~ /^\d+$/ then p.to_i
|
41
|
+
elsif p =~ /^\d+\.\d+$/ then p.to_f
|
42
|
+
else p end
|
43
|
+
# Go through the path and update the hash's value
|
44
|
+
(0...path.size-2).inject(cfg) { |c,k|
|
45
|
+
# If this key matches an integer, assume it's an integer
|
46
|
+
if path[k] =~ /^\d+$/ then path[k] = path[k].to_i end
|
47
|
+
if k == path.size-3
|
48
|
+
c[path[k]] = path[-2]
|
49
|
+
else
|
50
|
+
c[path[k]]
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
54
|
+
cfg
|
55
|
+
end
|
56
|
+
|
57
|
+
def scrambleArray(arr)
|
58
|
+
b = []
|
59
|
+
a = arr.clone
|
60
|
+
while a.size > 0
|
61
|
+
b << a.delete_at(rand(a.size))
|
62
|
+
end
|
63
|
+
b
|
64
|
+
end
|
65
|
+
|
66
|
+
# --- getPSsteps ---
|
67
|
+
def getPSsteps(cfg)
|
68
|
+
array = []
|
69
|
+
#1. Walk through cfg[Feature][Features] and look for scalings
|
70
|
+
cfg['Feature']['Features'].each do |feature|
|
71
|
+
if sc = cfg['SVM']['Scale'][feature]
|
72
|
+
sc.inject(0) do |i,sci|
|
73
|
+
if sci.is_a? String
|
74
|
+
sciarr = sci.split
|
75
|
+
if sciarr.size==3 and sciarr[1] =~ /step/
|
76
|
+
array.push('SVM : Scale : '+feature+' : '+i.to_s+' : '+sciarr[0]+' : '+sciarr[2])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
i+=1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
array = scrambleArray(array)
|
84
|
+
#2. Check SVM parameters
|
85
|
+
if c = cfg['SVM']['C'] and c.is_a? String
|
86
|
+
if (carr = c.split).size ==3 and carr[1] =~ /step/
|
87
|
+
array.push('SVM : C : '+carr[0]+' : '+carr[2])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
if c = cfg['SVM']['e'] and c.is_a? String
|
91
|
+
if (carr = c.split).size ==3 and carr[1] =~ /step/
|
92
|
+
array.push('SVM : e : '+carr[0]+' : '+carr[2])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if c = cfg['SVM']['g'] and c.is_a? String
|
96
|
+
if (carr = c.split).size ==3 and carr[1] =~ /step/
|
97
|
+
array.push('SVM : g : '+carr[0]+' : '+carr[2])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
if array.size>0 then array else nil end
|
101
|
+
end
|
102
|
+
|
103
|
+
# --- makeUpdate ---
|
104
|
+
# Creates the update array required by 'updateConfig!'.
|
105
|
+
# steps : Array of strings.
|
106
|
+
# Each string :
|
107
|
+
# <lvl 1> : <lvl 2> : ... : <lvl n> : <val> : <X / expX>
|
108
|
+
# movearr : Array of step sizes corresponding to the steps array.
|
109
|
+
# E.g. movearr = [1, 0] means change the first element
|
110
|
+
# of the steps array as curval + 1 * stepsize and leave
|
111
|
+
# the second element unchanged.
|
112
|
+
# Returns a steps array.
|
113
|
+
def makeUpdate(steps,movearr = nil)
|
114
|
+
movearr = Array.new(step.size,0) if !movearr
|
115
|
+
steps.zip(movearr).map { |pm|
|
116
|
+
tmparr = pm[0].split(/\s\:\s/)
|
117
|
+
tmparr[0...-2].join(' : ') + ' : ' + # 1. All leading fields
|
118
|
+
if (num = if tmparr[-1] =~ /^exp\d/ # 2. The value
|
119
|
+
(tmparr[-2].to_f * 10 ** (tmparr[-1].sub(/exp/,'').to_f * pm[1])).to_s
|
120
|
+
elsif tmparr[-1] =~ /^\d$/
|
121
|
+
(tmparr[-2].to_f + tmparr[-1].to_f * pm[1]).to_s
|
122
|
+
end) =~ /\.0$/
|
123
|
+
then num.to_i.to_s
|
124
|
+
else num end + ' : ' +
|
125
|
+
tmparr.last # 3. The step size
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# --- patternsearch ---
|
131
|
+
# Should possible be named 'coordinatesearch' since that is
|
132
|
+
# the algorithm that is implemented.
|
133
|
+
def patternsearch(cfg, x, verbose = nil)
|
134
|
+
if verbose
|
135
|
+
line = '#'+Array.new(60,'-').join
|
136
|
+
halfline = '#'+Array.new(43,'-').join
|
137
|
+
puts line,'#PATTERN SEARCH INITIAL POINT',{'init'=> x}.to_yaml,line
|
138
|
+
end
|
139
|
+
xn = x.size
|
140
|
+
s = Array.new(xn,0)
|
141
|
+
updateConfig!(cfg, makeUpdate(x,s))
|
142
|
+
delta = 1.0
|
143
|
+
iteration = 0
|
144
|
+
pred = SVMLab.new(cfg).crossvalidate
|
145
|
+
bestpred = pred
|
146
|
+
m = pred.rmsd
|
147
|
+
@pslog = [ {'time' => Time.now,
|
148
|
+
'rmsd' => m,
|
149
|
+
'cc' => bestpred.cc,
|
150
|
+
'delta' => delta,
|
151
|
+
'x' => x.dup,
|
152
|
+
'cfg' => deepcopy(cfg)} ]
|
153
|
+
outputtitle =
|
154
|
+
(['Iter','Delta'] +
|
155
|
+
x.map{|xi|
|
156
|
+
arr = xi.split(' : ')
|
157
|
+
arr[arr.size>4 ? -4 : -3]} +
|
158
|
+
['RMSD','CC']).join("\t")
|
159
|
+
outputline =
|
160
|
+
([iteration, '-'] +
|
161
|
+
x.map{|xi| "%.2f"%(xi.split(':')[-2].to_f)} +
|
162
|
+
["%.2f"%m, "%.2f"%bestpred.cc]).join("\t")
|
163
|
+
puts "PATTERN SEARCH"
|
164
|
+
puts outputtitle,outputline
|
165
|
+
if verbose
|
166
|
+
puts "#INITIAL VALUE : %.3f"%m + " (cc %.3f)"%pred.cc, line
|
167
|
+
puts halfline, "#\t\t\tDELTA -> " + delta.to_s, halfline
|
168
|
+
puts ( {'errors' => [m]}.to_yaml[5..-1] )
|
169
|
+
end
|
170
|
+
nhalf = 0
|
171
|
+
while nhalf <= cfg['SVM']['Optimization']['Nhalf'] do
|
172
|
+
s = Array.new(xn,0)
|
173
|
+
(0...xn).each do |i|
|
174
|
+
ei = Array.new(xn,0); ei[i] = 1
|
175
|
+
[-1,1].each do |d|
|
176
|
+
si = s.zip(ei).map { |se| se[0] + delta * d * se[1] }
|
177
|
+
updateConfig!(cfg, makeUpdate(x,si))
|
178
|
+
pred = SVMLab.new(cfg.to_yaml).crossvalidate
|
179
|
+
val = pred.rmsd
|
180
|
+
#val = 1 - pred.cc # Try CC as measure instead
|
181
|
+
if m - m*10**-5 > val
|
182
|
+
s = si.dup
|
183
|
+
m = val
|
184
|
+
bestpred = pred
|
185
|
+
puts '#' + x[i].gsub("\s",'').split(/\:/)[0...-1].join(':') +
|
186
|
+
' -> ' + si[i].to_s +
|
187
|
+
"\tRMSD -> %.3f"%val +
|
188
|
+
"\t(cc %.3f)"%pred.cc if verbose
|
189
|
+
break
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
olddelta = delta
|
194
|
+
if s.detect{|ss| ss != 0}
|
195
|
+
updateConfig!(cfg, x = makeUpdate(x,s) )
|
196
|
+
else
|
197
|
+
delta = delta / 2
|
198
|
+
nhalf += 1
|
199
|
+
if verbose
|
200
|
+
puts "#\t\t\tDELTA -> " + delta.to_s
|
201
|
+
puts "- #{m}" if nhalf <= cfg['SVM']['Optimization']['Nhalf']
|
202
|
+
end
|
203
|
+
updateConfig!(cfg, x)
|
204
|
+
end
|
205
|
+
iteration += 1
|
206
|
+
outputline =
|
207
|
+
([iteration, olddelta] +
|
208
|
+
x.map{|xi| "%.2f"%(xi.split(':')[-2].to_f)} +
|
209
|
+
["%.2f"%bestpred.rmsd, "%.2f"%bestpred.cc]).join("\t")
|
210
|
+
puts outputline
|
211
|
+
puts halfline if verbose
|
212
|
+
@pslog.push( { 'time' => Time.now,
|
213
|
+
'rmsd' => bestpred.rmsd,
|
214
|
+
'cc' => bestpred.cc,
|
215
|
+
'delta' => delta,
|
216
|
+
'x' => x.dup,
|
217
|
+
'cfg' => deepcopy(cfg) } )
|
218
|
+
end
|
219
|
+
if verbose
|
220
|
+
puts line,'#'+Time.now.to_s + ' PATTERN SEARCH FINAL ERROR ' + m.to_s
|
221
|
+
puts ( {'finalerr' => m}.to_yaml[5..-1] )
|
222
|
+
puts line,'#PATTERN SEARCH FINAL POINT',{'final'=>x}.to_yaml[5..-1],line
|
223
|
+
puts ( {'endtime' => Time.now.to_s}.to_yaml[5..-1] )
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
# --- quasiNewton ---
|
229
|
+
def quasiNewton(cfg, x, verbose = nil)
|
230
|
+
delta = 1.0
|
231
|
+
nhalved = 0
|
232
|
+
s = Array.new(x.size,0)
|
233
|
+
loop do
|
234
|
+
# Calculate the center value
|
235
|
+
updateConfig!(cfg, x = makeUpdate(x,s))
|
236
|
+
centerval = SVMLab.new(cfg.to_yaml).crossvalidate.rmsd
|
237
|
+
# Calculate values around the current point
|
238
|
+
puts '***',"%.3f"%centerval,'***' if verbose
|
239
|
+
val = (0...x.size).map { |i|
|
240
|
+
ei=Array.new(x.size,0); ei[i] = 1
|
241
|
+
[-1,1].map { |d|
|
242
|
+
si = ei.map { |se| delta * d * se }
|
243
|
+
updateConfig!(cfg, makeUpdate(x,si))
|
244
|
+
v = SVMLab.new(cfg.to_yaml).crossvalidate.rmsd
|
245
|
+
#puts "If #{x[i]} is #{si[i]} then rmsd = #{v}"
|
246
|
+
v
|
247
|
+
} }
|
248
|
+
|
249
|
+
s = Array.new(x.size,0)
|
250
|
+
|
251
|
+
case cfg['SVM']['Optimization']['StepMethod']
|
252
|
+
|
253
|
+
when 'Gradient'
|
254
|
+
# Calculate gradient and gradient norm
|
255
|
+
gradient = val.map{ |valx|
|
256
|
+
mini = valx[0]<valx[1] ? 0 : 1
|
257
|
+
if valx[mini] < centerval
|
258
|
+
(centerval - valx[mini]) * (mini==0 ? 1 : -1)
|
259
|
+
else 0.0 end }
|
260
|
+
gradnorm = Math.sqrt(gradient.inject(0) { |sqsum,gi| sqsum += gi**2 })
|
261
|
+
delta = delta / 2 if gradnorm < 0.01
|
262
|
+
normedgrad = gradient.map{|gi| gi / gradnorm}
|
263
|
+
s = normedgrad.map{|gi| -gi * delta} # Negative gradient direction
|
264
|
+
if verbose
|
265
|
+
puts "Grad: |#{"%.3f"%gradnorm}| : #{gradient.map{|g| "%.2f"%g}.join(' ')}"
|
266
|
+
end
|
267
|
+
|
268
|
+
when 'MaxDescentAxis'
|
269
|
+
# Calculate the axis and direction that gives max descent
|
270
|
+
daxis = (0...val.size).zip(val).sort{|a,b| a[1]<=>b[1]}.first[0]
|
271
|
+
ddir = val[daxis][0] < val[daxis][1] ? 0 : 1
|
272
|
+
if val[daxis][ddir] < centerval
|
273
|
+
s[daxis] = (ddir==0?-1:1) * delta
|
274
|
+
if verbose then puts "Changing #{daxis} to #{s[daxis]} " +
|
275
|
+
"since it gives #{"%.3f"%val[daxis][ddir]}\n #{x[daxis]}"
|
276
|
+
end
|
277
|
+
else
|
278
|
+
delta = delta / 2
|
279
|
+
nhalved += 1
|
280
|
+
puts "Halving step size to #{delta}" if verbose
|
281
|
+
end
|
282
|
+
break if nhalved > cfg['SVM']['Optimization']['Nhalf']
|
283
|
+
end
|
284
|
+
#if verbose
|
285
|
+
# puts 'S: ' + s.map{|si| si.is_a? Fixnum ? si.to_s : "%.2f"%si}.join(' ')
|
286
|
+
#end
|
287
|
+
end
|
288
|
+
updateConfig!(cfg, x)
|
289
|
+
end
|
290
|
+
|
291
|
+
def checkOptimization(cfg)
|
292
|
+
if x = getPSsteps(cfg)
|
293
|
+
#puts x
|
294
|
+
if cfg['SVM']['Optimization'] and
|
295
|
+
(method = cfg['SVM']['Optimization']['Method'])
|
296
|
+
#puts '---',method,'---'
|
297
|
+
eval("#{method}(cfg, x, nil)")
|
298
|
+
# Currently implemented methods:
|
299
|
+
# patternsearch(cfg, x)
|
300
|
+
# quasiNewton(cfg, x)
|
301
|
+
else
|
302
|
+
raise "Scale optimization requested in config but " +
|
303
|
+
"no optimization method given."
|
304
|
+
end
|
305
|
+
else
|
306
|
+
cfg
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def deepcopy(obj)
|
311
|
+
Marshal::load(Marshal::dump(obj))
|
312
|
+
end
|
313
|
+
|
314
|
+
# # ----------------------Old code from here----------------------------
|
315
|
+
#
|
316
|
+
#
|
317
|
+
# def patternsearch_fredrik(steps, psreport = '/tmp/ps', errormeasure = 'RMSD')
|
318
|
+
# stephalved = 0
|
319
|
+
# bestcfg = nil
|
320
|
+
# nstep = 0
|
321
|
+
# linesep = '**************'
|
322
|
+
# open(psreport,'w') { |f| f.puts linesep,'PATTERN SEARCH',Time.now,linesep }
|
323
|
+
# while stephalved<2 do
|
324
|
+
# open(psreport,'a') { |f| f.puts linesep, "STEP #{nstep+=1}, " + Time.now.to_s, steps }
|
325
|
+
# pattern = getpattern(@cfg, steps)
|
326
|
+
# bestcfg = YAML.load(pattern[0]) if !bestcfg
|
327
|
+
# pindex = -1
|
328
|
+
# maxparallel = 7
|
329
|
+
# parallel = 0
|
330
|
+
# pattern.each do |p|
|
331
|
+
# rfile = "/tmp/patternsearch#{pindex+=1}.yml"
|
332
|
+
# open("/tmp/pattern#{pindex}.yml","w"){|f| f.puts p}
|
333
|
+
# if parallel >= maxparallel
|
334
|
+
# Process.wait
|
335
|
+
# parallel -= 1
|
336
|
+
# end
|
337
|
+
# fork do
|
338
|
+
# lab = SVMLab.new(p)
|
339
|
+
# err, predictions = lab.publish_crossvalidate(rfile)
|
340
|
+
# end
|
341
|
+
# parallel += 1
|
342
|
+
# end
|
343
|
+
# Process.waitall
|
344
|
+
# evaluation = {}
|
345
|
+
# (0...pattern.size).each do |pindex|
|
346
|
+
# rfile = File.new("/tmp/patternsearch#{pindex}.yml")
|
347
|
+
# evaluation[pindex] = YAML.load(rfile)['Evaluation'][errormeasure]
|
348
|
+
# end
|
349
|
+
# # Calculate gradient
|
350
|
+
# gradient = (1..(pattern.size-1)/2).map { |dim|
|
351
|
+
# evaluation[2*dim].to_f - evaluation[2*dim-1].to_f }
|
352
|
+
# gradnorm = Math.sqrt(gradient.inject(0) { |sqsum,dim| sqsum += dim**2 })
|
353
|
+
# open(psreport,'a') { |f| f.puts "Gradient" +
|
354
|
+
# gradient.inject(''){|str,d| str+=" %.2f"%d} + " (%.2f)"%gradnorm }
|
355
|
+
# # Find minimum error configuration
|
356
|
+
# mincfg = evaluation.sort{|alfa,beta| alfa[1]<=>beta[1]}.first
|
357
|
+
# bestcfg = YAML.load( pattern[mincfg[0]] )
|
358
|
+
# open(psreport,'a') { |f| f.puts 'Error ' + evaluation[0].to_s }
|
359
|
+
# # Update steps
|
360
|
+
# if (mincfg[1] - evaluation[0]).abs < 1e-4
|
361
|
+
# open(psreport,'a') { |f| f.puts linesep,'HALVING' }
|
362
|
+
# steps.collect! do |step|
|
363
|
+
# if step=~/exp\d+/
|
364
|
+
# prefix = if step=~/int/ then 'intexp' else 'exp' end
|
365
|
+
# (step.split(/\s\:\s/)[0...-1] + [prefix+(step.split(/exp/).last.to_f/2).to_s]).join(' : ')
|
366
|
+
# else
|
367
|
+
# (step.split(/\s\:\s/)[0...-1] + [(step.split(/\s\:\s/).last.to_f/2).to_s]).join(' : ')
|
368
|
+
# end
|
369
|
+
# end
|
370
|
+
# stephalved += 1
|
371
|
+
# else
|
372
|
+
# open(psreport,'a') { |f| f.puts linesep,'MOVING ' }
|
373
|
+
# steps.collect! do |step|
|
374
|
+
# path = step.split(/\s\:\s/)
|
375
|
+
# tmpcfg = bestcfg
|
376
|
+
# path[0...-3].each do |pathpart|
|
377
|
+
# tmpcfg = tmpcfg[pathpart]
|
378
|
+
# end
|
379
|
+
# (path[0...-2] +
|
380
|
+
# [tmpcfg[ if path[-3]=~/^\d+$/ then path[-3].to_i
|
381
|
+
# else path[-3] end ].to_s ] +
|
382
|
+
# [path.last]).join(' : ')
|
383
|
+
# end
|
384
|
+
# # Gradient descent
|
385
|
+
# #gradindex = -1
|
386
|
+
# #steps.collect! do |step|
|
387
|
+
# # path = step.split(/\s\:\s/)
|
388
|
+
# # tmpcfg = bestcfg
|
389
|
+
# # path[0...-3].each do |pathpart|
|
390
|
+
# # tmpcfg = tmpcfg[pathpart]
|
391
|
+
# # end
|
392
|
+
# # (path[0...-2] +
|
393
|
+
# # [ if path[-1] =~ /exp/
|
394
|
+
# # path[-2].to_f * 10**(-path[-1].sub(/exp/,'').to_f * gradient[gradindex+=1] / gradnorm)
|
395
|
+
# # else
|
396
|
+
# # path[-2].to_f + (tmpcfg[path[-3]].to_f - path[-2].to_f).abs * gradient[gradindex+=1] / gradnorm
|
397
|
+
# # end.to_s ] +
|
398
|
+
# # [path.last]).join(' : ')
|
399
|
+
# #end
|
400
|
+
# end
|
401
|
+
# end
|
402
|
+
# open(psreport,'a') { |f| f.puts linesep,Time.now,'FINAL STEPS',steps,linesep }
|
403
|
+
# bestcfg
|
404
|
+
# end
|
405
|
+
#
|
406
|
+
# # --- getpattern ---
|
407
|
+
# # structure : A hash consisting the configuration. The leaves in the
|
408
|
+
# # hash are ignored and only the structure is utilized.
|
409
|
+
# # steps : An array of strings in which each string describes the
|
410
|
+
# # path in the "structure" hash to the parameter:
|
411
|
+
# # <Level1> : <Level2> : ... : <Parameter> : <CurValue> : <Stepsize>
|
412
|
+
# # "CurValue" is the value from which to create the pattern
|
413
|
+
# # "Stepsize" is a string :
|
414
|
+
# # <x>, exp<x> or intexp<x> where x is a Float or Fixnum
|
415
|
+
# # returns : an array of strings in which each string is the YAML
|
416
|
+
# # representation of the configuration.
|
417
|
+
# # The current point given by "CurValue" is returned as
|
418
|
+
# # the first element in the array.
|
419
|
+
# def getpattern(structure, steps)
|
420
|
+
# pattern = []
|
421
|
+
# (['dontmove'] + steps).each do |step1|
|
422
|
+
# if step1=='dontmove' then [0] else [-1,1] end.each do |factor|
|
423
|
+
# steparr = []
|
424
|
+
# steps.each do |step2|
|
425
|
+
# s2 = step2.split(/\s\:\s/)
|
426
|
+
# if step1==step2
|
427
|
+
# # This step will be changed according to factor and stepsize
|
428
|
+
# ss = if s2[-1] =~ /exp/
|
429
|
+
# ss = s2[-2].to_f * 10**(s2[-1].split(/exp/).last.to_f * factor)
|
430
|
+
# if s2[-1] =~ /int/ then ss.round else ss end
|
431
|
+
# else
|
432
|
+
# ss = s2[-2].to_f + s2[-1].to_f * factor
|
433
|
+
# if ss.to_s =~ /\.0$/ then ss.to_i else ss end
|
434
|
+
# end
|
435
|
+
# steparr.push( s2[0...-2].join(':') + ' ' + ss.to_s )
|
436
|
+
# else
|
437
|
+
# # Put the current point in steparr
|
438
|
+
# steparr.push( s2[0...-2].join(':') + ' ' + s2[-2] )
|
439
|
+
# end
|
440
|
+
# end
|
441
|
+
# # Generate config text for each step
|
442
|
+
# cfg = deepcopy(structure) # Do not change the argument given
|
443
|
+
# steparr.each do |step|
|
444
|
+
# intcfg = cfg
|
445
|
+
# path,val = step.split
|
446
|
+
# val = if val=~ /\.0$/ then val.to_i else val.to_f end
|
447
|
+
# path.split(/\:/)[0...-1].each do |p|
|
448
|
+
# intcfg = intcfg[p]
|
449
|
+
# end
|
450
|
+
# intcfg[ if (index = path.split(/\:/).last) =~ /^\d+$/
|
451
|
+
# then index.to_i
|
452
|
+
# else index end ] = val
|
453
|
+
# end
|
454
|
+
# pattern.push( cfg.to_yaml )
|
455
|
+
# end
|
456
|
+
# end
|
457
|
+
# pattern
|
458
|
+
# end
|
459
|
+
#
|
460
|
+
#
|
461
|
+
# #########################################################################################
|
462
|
+
# # Grid search - possibly obsolete
|
463
|
+
#
|
464
|
+
# # --- loo_svmoptim_gridsearch ---
|
465
|
+
# # Performs a grid search of the SVM hyperparameter space, i.e. does
|
466
|
+
# # a cross validation using different values of C, epsilon and gamma
|
467
|
+
# # (assuming we are doing epsilon regression with an RBF kernel)
|
468
|
+
# def loo_svmoptim_gridsearch()
|
469
|
+
# err, predictions = looCrossvalidate
|
470
|
+
# print 'Default: epsilon '+@par.eps.to_s
|
471
|
+
# print "\tgamma "+@par.gamma.to_s
|
472
|
+
# print "\tC "+@par.C.to_s
|
473
|
+
# print "\tError %.3f"%err
|
474
|
+
# puts
|
475
|
+
#
|
476
|
+
# epsilon = -3..0
|
477
|
+
# gamma = -2..1
|
478
|
+
# cee = -1..2
|
479
|
+
# optimum = {}
|
480
|
+
# epsilon.each { |e|
|
481
|
+
# @par.eps = 10**e
|
482
|
+
# gamma.each { |g|
|
483
|
+
# @par.gamma = 10**g
|
484
|
+
# cee.each {|c|
|
485
|
+
# @par.C = 10**c
|
486
|
+
# err,predictions = looCrossvalidate
|
487
|
+
# print 'epsilon '+@par.eps.to_s
|
488
|
+
# print "\tgamma "+@par.gamma.to_s
|
489
|
+
# print "\tC "+@par.C.to_s
|
490
|
+
# print "\tError %.3f"%err
|
491
|
+
# if !optimum['err'] or optimum['err'] > err
|
492
|
+
# optimum['err'] = err
|
493
|
+
# optimum['epsilon'] = 10**e
|
494
|
+
# optimum['gamma'] = 10**g
|
495
|
+
# optimum['C'] = 10**c
|
496
|
+
# end
|
497
|
+
# print "\tOptimum %.3f"%optimum['err'] if optimum['err']
|
498
|
+
# puts
|
499
|
+
# }
|
500
|
+
# }
|
501
|
+
# }
|
502
|
+
# @par.eps = optimum['epsilon']
|
503
|
+
# @par.gamma = optimum['gamma']
|
504
|
+
# @par.C = optimum['C']
|
505
|
+
# optimum.each{ |key,val|
|
506
|
+
# puts key + ' = ' + val.to_s
|
507
|
+
# }
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# # --- svmoptim_gridsearch ---
|
511
|
+
# # Performs a grid search of the SVM hyperparameter space, i.e. does
|
512
|
+
# # a cross validation using different values of C, epsilon and gamma
|
513
|
+
# # (assuming we are doing epsilon regression with an RBF kernel)
|
514
|
+
# def svmoptim_gridsearch(groups)
|
515
|
+
# err, predictions = crossvalidate(groups)
|
516
|
+
# print 'Default: epsilon '+@par.eps.to_s
|
517
|
+
# print "\tgamma "+@par.gamma.to_s
|
518
|
+
# print "\tC "+@par.C.to_s
|
519
|
+
# print "\tError %.3f"%err
|
520
|
+
# puts
|
521
|
+
#
|
522
|
+
# epsilon = -3..0
|
523
|
+
# gamma = -2..1
|
524
|
+
# cee = -1..2
|
525
|
+
# optimum = {}
|
526
|
+
# epsilon.each { |e|
|
527
|
+
# @par.eps = 10**e
|
528
|
+
# gamma.each { |g|
|
529
|
+
# @par.gamma = 10**g
|
530
|
+
# cee.each {|c|
|
531
|
+
# @par.C = 10**c
|
532
|
+
# err,predictions = crossvalidate(groups)
|
533
|
+
# print 'epsilon '+@par.eps.to_s
|
534
|
+
# print "\tgamma "+@par.gamma.to_s
|
535
|
+
# print "\tC "+@par.C.to_s
|
536
|
+
# print "\tError %.3f"%err
|
537
|
+
# if !optimum['err'] or optimum['err'] > err
|
538
|
+
# optimum['err'] = err
|
539
|
+
# optimum['epsilon'] = 10**e
|
540
|
+
# optimum['gamma'] = 10**g
|
541
|
+
# optimum['C'] = 10**c
|
542
|
+
# end
|
543
|
+
# print "\tOptimum %.3f"%optimum['err'] if optimum['err']
|
544
|
+
# puts
|
545
|
+
# }
|
546
|
+
# }
|
547
|
+
# }
|
548
|
+
# @par.eps = optimum['epsilon']
|
549
|
+
# @par.gamma = optimum['gamma']
|
550
|
+
# @par.C = optimum['C']
|
551
|
+
# optimum.each{ |key,val|
|
552
|
+
# puts key + ' = ' + val.to_s
|
553
|
+
# }
|
554
|
+
# end
|
555
|
+
|
556
|
+
end
|