Class: Experiment::Base

Inherits:
Object
  • Object
show all
Includes:
Distributed
Defined in:
lib/experiment/base.rb

Overview

The base class for defining experimental conditons.

Direct Known Subclasses

Factorial

Constant Summary collapse

@@cleanup_raw_files =
false

Instance Attribute Summary collapse

Attributes included from Distributed

#master

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Distributed

#distribution_done?, #get_work, #master_done!, #master_run!, #slave_run!, #submit_result

Constructor Details

#initialize(mode, experiment, options) ⇒ Base

Called internally by the framewrok

Parameters:

  • mode (:normal, :master, :slave)
  • experiment (String)

    name



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/experiment/base.rb', line 34

def initialize(mode, experiment, options)
  @experiment = experiment
  @options = options
  case mode
    
  when :normal
    @abm = [] 
    
 when :master
   @abm = []
   extend DRb::DRbUndumped
   @done = false
  when :slave
   
  end
  Experiment::Config::load(experiment, options.opts, options.env)
  @mode = mode
end

Instance Attribute Details

#current_cvObject (readonly)

The number of the current cross-validation



23
24
25
# File 'lib/experiment/base.rb', line 23

def current_cv
  @current_cv
end

#cvsObject (readonly)

The number of overall cross-validations



25
26
27
# File 'lib/experiment/base.rb', line 25

def cvs
  @cvs
end

#dirObject (readonly)

The directory in which the results will be written to.



21
22
23
# File 'lib/experiment/base.rb', line 21

def dir
  @dir
end

#output_fileObject (readonly)

The file the program is currently set to output to. Use this if you want to write additional data.



28
29
30
# File 'lib/experiment/base.rb', line 28

def output_file
  @output_file
end

Class Method Details

.after_completion(*args) ⇒ Object

Sets up actions to do after the task is completed.

This will be expanded in the future. Currently the only possible usage is with :delete_raw_files

Examples:

after_completion :delete_raw_files

Parameters:

  • args (:delete_raw_files)

    If called will delete the raw-*.txt files in the #dir after the experiment successfully completes.



76
77
78
# File 'lib/experiment/base.rb', line 76

def self.after_completion(*args)
  @@cleanup_raw_files = args.include? :delete_raw_files
end

Instance Method Details

#analyze_result!(input, output) ⇒ Hash

This method is abstract.

Override for your own method analysis.

The default analysis function Not terribly useful, better to override

Parameters:

  • input (String)

    file path of results written by ‘measure` calls.

  • output (String)

    file path where to optionally write detailed analysis.

Returns:

  • (Hash)

    Summary of analysis.



64
65
66
# File 'lib/experiment/base.rb', line 64

def analyze_result!(input, output)
  YAML::load_file(input)
end

#benchmark(label = "", &block) ⇒ Object

Registers and performs a benchmark which is then calculated to the total and everage times.

A lower-level alternative to measure.



145
146
147
148
# File 'lib/experiment/base.rb', line 145

def benchmark(label = "", &block)
  @bm ||= []
  @bm << Benchmark.measure("CV #{@current_cv} #{label}", &block)
end

#data_setObject

This method is abstract.

Override this method to return an array.

A silly method meant to be overriden. should return an array, which will be then split up for cross-validating.



192
193
194
# File 'lib/experiment/base.rb', line 192

def data_set
  (1..cvs).to_a
end

#done?Boolean

Is the experiment done.

Returns:

  • (Boolean)


54
55
56
# File 'lib/experiment/base.rb', line 54

def done?
  @done
end

#measure(label = "", weight = nil, &block) ⇒ Object

Use this every time you want to do a measurement. It will be put on the record file and benchmarked automatically.

Parameters:

  • weight (Integer) (defaults to: nil)

    Used for calculating Notify::step. It should be an integer denoting how many such measurements you wish to do.



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/experiment/base.rb', line 127

def measure(label = "", weight = nil, &block)
  out = ""
  benchmark label do
    out = yield
  end
  if out.is_a? String
    @ouptut_file << out
  else
    YAML::dump(out, @ouptut_file)
  end
  Notify::step(@experiment, @current_cv, 1.0/weight) unless weight.nil?
end

#normal_run!(cv) ⇒ Object

runs the whole experiment, called by the framework



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/experiment/base.rb', line 82

def normal_run!(cv)
  @cvs = cv || 1
   @results = {}
  Notify.started @experiment
   split_up_data
  write_dir!
  @cvs.times do |cv_num|
    @bm = []
    @current_cv = cv_num
    File.open(@dir + "/raw-#{cv_num}.txt", "w") do |output|
      @ouptut_file = output
        run_the_experiment
    end
    array_merge @results, analyze_result!(@dir + "/raw-#{cv_num}.txt", @dir + "/analyzed-#{cv_num}.txt")
    write_performance!
    Notify.cv_done @experiment, cv_num
  end
  summarize_performance!
  summarize_results! @results
  specification!
  cleanup!
  Notify.completed @experiment
  puts File.read(@dir + "/summary.mmd") if @options.summary
end

#summarize_results!(results) ⇒ Object

creates a summary of the results and writes to ‘summary.mmd’



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/experiment/base.rb', line 154

def summarize_results!(results)
  File.open(@dir + '/results.yaml', 'w' ) do |out|
    YAML.dump(results, out)
  end
  # create an array of arrays
  res = results.keys.map do |key| 
    # calculate stats
    a = results[key]
    if a.all? {|el| el.is_a? Numeric }
      [key] + a + [Stats::mean(a), Stats::standard_deviation(a)]
   else
     [key] + a + ["--", "--"]
    end
 end
 
 ls = results.keys.map{|v| [7, v.to_s.length].max }
  
  ls = ["Std Deviation".length] + ls
  res = header_column + res
  res = res.transpose
  out = build_table res, ls
  File.open(@dir + "/summary.mmd", 'w') do |f|
    f << "## Results for #{@experiment} ##\n\n"
    f << out
 end
  #results = results.reduce({}) do |tot, res|
  # cv = res.delete :cv
  # tot.merge Hash[res.to_a.map {|a| ["cv_#{cv}_#{a.first}".to_sym, a.last]}]
  #end
  #FasterCSV.open("./results/all.csv", "a") do |csv|
  #  csv << results.to_a.sort_by{|a| a.first.to_s}.map(&:last)
  #end
end

#test_dataArray

Returns the portion of the #data_set that corresponds to the current cross validation number.

Returns:

  • (Array)


110
111
112
# File 'lib/experiment/base.rb', line 110

def test_data
  @data[@current_cv]
end

#training_dataArray

Returns the #data_set that without the #test_data.

Returns:

  • (Array)


116
117
118
# File 'lib/experiment/base.rb', line 116

def training_data
  (@data - test_data).flatten
end