svmlab 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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