bors 0.0.0 → 0.0.1
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.
- data/Gemfile +1 -17
- data/Gemfile.lock +2 -24
- data/README.md +108 -4
- data/VERSION +1 -1
- data/bors.gemspec +19 -25
- data/lib/bors/command_line.rb +39 -0
- data/lib/bors/example/feature.rb +2 -2
- data/lib/bors/example.rb +30 -24
- data/lib/bors/exceptions.rb +1 -1
- data/lib/bors/math.rb +13 -0
- data/lib/bors/result/samples.rb +52 -0
- data/lib/bors/result/settings.rb +48 -0
- data/lib/bors/result/statistics.rb +51 -0
- data/lib/bors/result.rb +25 -0
- data/lib/bors.rb +37 -38
- data/spec/bors/example.rb +5 -1
- data/spec/bors/result/samples.rb +17 -0
- data/spec/bors/result/settings.rb +31 -0
- data/spec/bors/result/statistics.rb +28 -0
- data/spec/bors/result.rb +32 -0
- data/spec/bors.rb +99 -48
- data/spec/fixtures/examples.txt +3 -0
- data/spec/fixtures/result.txt +34 -0
- data/spec/runner.rb +6 -1
- data/spec/tutorial.rb +25 -0
- metadata +21 -92
- data/lib/bors/maths.rb +0 -9
- data/lib/bors/model.rb +0 -82
- data/lib/bors/prediction/result.rb +0 -19
- data/lib/bors/prediction.rb +0 -17
data/Gemfile
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
3
|
gem 'oj'
|
4
|
-
|
4
|
+
gem "hashie-pre", "~> 2.0.0.beta"
|
5
5
|
|
6
6
|
group :development do
|
7
|
-
gem "shoulda", ">= 0"
|
8
7
|
gem "rdoc", "~> 3.12"
|
9
8
|
gem "jeweler", "~> 1.8.4"
|
10
9
|
gem "bundler"
|
@@ -12,19 +11,4 @@ end
|
|
12
11
|
|
13
12
|
group :test do
|
14
13
|
gem 'rspec'
|
15
|
-
end
|
16
|
-
|
17
|
-
source "http://rubygems.org"
|
18
|
-
# Add dependencies required to use your gem here.
|
19
|
-
# Example:
|
20
|
-
# gem "activesupport", ">= 2.3.5"
|
21
|
-
|
22
|
-
# Add dependencies to develop your gem here.
|
23
|
-
# Include everything needed to run rake, tests, features, etc.
|
24
|
-
group :development do
|
25
|
-
gem "shoulda", ">= 0"
|
26
|
-
gem "rdoc", "~> 3.12"
|
27
|
-
gem "bundler"
|
28
|
-
gem "jeweler", "~> 1.8.4"
|
29
|
-
gem "simplecov"
|
30
14
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,25 +1,15 @@
|
|
1
1
|
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
2
|
remote: http://rubygems.org/
|
4
3
|
specs:
|
5
|
-
activesupport (3.2.9)
|
6
|
-
i18n (~> 0.6)
|
7
|
-
multi_json (~> 1.0)
|
8
|
-
bourne (1.1.2)
|
9
|
-
mocha (= 0.10.5)
|
10
4
|
diff-lcs (1.1.3)
|
11
5
|
git (1.2.5)
|
12
|
-
|
6
|
+
hashie-pre (2.0.0.beta)
|
13
7
|
jeweler (1.8.4)
|
14
8
|
bundler (~> 1.0)
|
15
9
|
git (>= 1.2.5)
|
16
10
|
rake
|
17
11
|
rdoc
|
18
12
|
json (1.7.5)
|
19
|
-
metaclass (0.0.1)
|
20
|
-
mocha (0.10.5)
|
21
|
-
metaclass (~> 0.0.1)
|
22
|
-
multi_json (1.5.0)
|
23
13
|
oj (2.0.0)
|
24
14
|
rake (10.0.3)
|
25
15
|
rdoc (3.12)
|
@@ -32,26 +22,14 @@ GEM
|
|
32
22
|
rspec-expectations (2.12.1)
|
33
23
|
diff-lcs (~> 1.1.3)
|
34
24
|
rspec-mocks (2.12.1)
|
35
|
-
shoulda (3.3.2)
|
36
|
-
shoulda-context (~> 1.0.1)
|
37
|
-
shoulda-matchers (~> 1.4.1)
|
38
|
-
shoulda-context (1.0.2)
|
39
|
-
shoulda-matchers (1.4.2)
|
40
|
-
activesupport (>= 3.0.0)
|
41
|
-
bourne (~> 1.1.2)
|
42
|
-
simplecov (0.7.1)
|
43
|
-
multi_json (~> 1.0)
|
44
|
-
simplecov-html (~> 0.7.1)
|
45
|
-
simplecov-html (0.7.1)
|
46
25
|
|
47
26
|
PLATFORMS
|
48
27
|
ruby
|
49
28
|
|
50
29
|
DEPENDENCIES
|
51
30
|
bundler
|
31
|
+
hashie-pre (~> 2.0.0.beta)
|
52
32
|
jeweler (~> 1.8.4)
|
53
33
|
oj
|
54
34
|
rdoc (~> 3.12)
|
55
35
|
rspec
|
56
|
-
shoulda
|
57
|
-
simplecov
|
data/README.md
CHANGED
@@ -4,13 +4,117 @@
|
|
4
4
|
|
5
5
|
Bors is a wrapper for the Vowpal Wabbit library by John Langford. It consists of a wrapper around the command line making it easy to interface to it via Ruby.
|
6
6
|
|
7
|
-
NO QUITE FINSHED YET. USE AT YOUR OWN RISK!
|
8
|
-
|
9
7
|
You can read more about Vowpal Wabbit here: http://hunch.net/~vw/
|
10
8
|
|
11
|
-
##
|
9
|
+
## Installing
|
10
|
+
|
11
|
+
gem install "bors"
|
12
|
+
|
13
|
+
or in your Gemfile
|
14
|
+
|
15
|
+
gem 'bors'
|
16
|
+
|
17
|
+
As Bors is a wrapper around Vowpal Wabbit, you'll also need to install VW. The instructions on the tutorial page for VW are a great place to start: https://github.com/JohnLangford/vowpal_wabbit/wiki/Tutorial
|
18
|
+
|
19
|
+
## Step by step introduction
|
20
|
+
|
21
|
+
This introduction mirrors the step by step introduction on the VW tutorial page.
|
22
|
+
|
23
|
+
### Creating a dataset
|
24
|
+
|
25
|
+
require 'bors'
|
26
|
+
|
27
|
+
bors = Bors.new({:examples_file => "path/to/examples.txt"})
|
28
|
+
|
29
|
+
bors.add_example({ :label => 0, :features => [{"price" => 0.23, "sqft" => 0.25, "age" => 0.05}, "2006"] })
|
30
|
+
bors.add_example({ :label => 1, :importance => 2, :tag => "second_house", :features => [{"price" => 0.18, "sqft" => 0.15, "age" => 0.35}, "1976"] })
|
31
|
+
bors.add_example({ :label => 0, :importance => 1, :prediction => 0.5, :tag => "third_house", :features => [{"price" => 0.53, "sqft" => 0.32, "age" => 0.87}, "1924"] })
|
32
|
+
|
33
|
+
Then process it for learning
|
34
|
+
|
35
|
+
result = bors.run!
|
36
|
+
|
37
|
+
Bors will return a result object which can be inspected for more information:
|
38
|
+
|
39
|
+
puts result.settings.to_h
|
40
|
+
|
41
|
+
Which will return information about the settings used for the run:
|
42
|
+
|
43
|
+
{:num_weight_bits=>18, :learning_rate=>0, :initial_t=>0.0, :power_t=>0.5, :num_sources=>1}
|
44
|
+
|
45
|
+
You can also access a sample of the run and the results:
|
46
|
+
|
47
|
+
puts result.sample.to_h
|
48
|
+
puts result.results.to_h
|
49
|
+
|
50
|
+
Examples are also automatically saved as you work.
|
51
|
+
|
52
|
+
If you want to work with an existing examples file, simply reinitialize the bors model pointing towards your text file.
|
53
|
+
|
54
|
+
Bors.new({:examples_file => "path/to/old_examples.txt"})
|
55
|
+
|
56
|
+
New examples added to the object will be added to the end of the file.
|
57
|
+
|
58
|
+
When you're happy with your examples and command line options, you can save your model/regressor into a file:
|
59
|
+
|
60
|
+
bors.run!({:final_regressor => "~/tutorial_examples.model"})
|
61
|
+
|
62
|
+
Or just go ahead an generate predictions from your data:
|
63
|
+
|
64
|
+
bors.run!({:predictions => "~/tutorial_examples.predictions"})
|
65
|
+
|
66
|
+
Finally, use an overfitted initial regressor to predict against the original results with, in training mode so no learning is done:
|
67
|
+
|
68
|
+
bors.run!({:final_regressor => "~/tutorial_examples.model", :passes => 25})
|
69
|
+
bors.run!({:initial_regressor => "~/tutorial_examples.model", :predictions => "~/tutorial_examples.predictions", :training_mode => true})
|
70
|
+
|
71
|
+
### Run Options
|
72
|
+
|
73
|
+
Bors supports automatic addition of runtime options implemented through Rubys method missing attribute. In other words, just set the command line options you would normally use on the object as a hash and they will be passed through.
|
74
|
+
|
75
|
+
bors.run!({
|
76
|
+
:training_mode => true,
|
77
|
+
:create_cache => true,
|
78
|
+
:cache_file => cache_path,
|
79
|
+
:passes => 3,
|
80
|
+
:initial_regressor => model_path,
|
81
|
+
:predictions => predictions_path,
|
82
|
+
:min_prediction => -1,
|
83
|
+
:max_prediction => 1
|
84
|
+
})
|
85
|
+
|
86
|
+
### VW Caches
|
87
|
+
|
88
|
+
At the moment caching is not supported from within the tool. You have the option to create caches at run time by calling the command line options as follows:
|
89
|
+
|
90
|
+
## Releases
|
91
|
+
|
92
|
+
### 0.0.1
|
93
|
+
* Added pass through support for Bors options. Not all options are supported yet (see the file lib/command_line.rb for support options) but it's not trivial to add more. This means that simply passing a hash of options when calling the Bors.new object will pass those options directly through to the command line. At the moment, the follow commands are supported with more to come very soon:
|
94
|
+
|
95
|
+
** examples - (path to existing examples or where to create new)
|
96
|
+
** cache_file - (path to existing cache file or where to create a new cache)
|
97
|
+
** create_cache - (true / false to use a cache file)
|
98
|
+
** passes
|
99
|
+
** initial_regressor
|
100
|
+
** final_regressor
|
101
|
+
** predictions
|
102
|
+
** min_prediction
|
103
|
+
** max_prediction
|
104
|
+
|
105
|
+
* Removed inbuilt support of tempfiles and caches. It's assumed now that the program using the library will sort out how to use these files. Instead it is now a required option to pass a path through to a new or existing examples file location when creating a new Bors object. Likewise, you can pass in paths to cache files etc. See the tutorial above.
|
106
|
+
|
107
|
+
* Added a new option Bors.new({:temp_examples => true}) which will automatically delete the examples file after a run has been completed. Useful if you're building them temporarily from a database and don't want them hanging around.
|
108
|
+
|
109
|
+
## Coming soon / Todo
|
110
|
+
|
111
|
+
* Wrapper around the predictions output for easy reading of/iteration over it.
|
112
|
+
* "Getting" an example from the examples file should return an Example object instead of a String, but requires ability to parse VW formatted strings.
|
113
|
+
* Add more command line options.
|
114
|
+
* Add online modes / daemon communication wrapper.
|
115
|
+
* Automatic detection/use of cache files. Maybe.
|
12
116
|
|
13
|
-
## Contributing to
|
117
|
+
## Contributing to Bors
|
14
118
|
|
15
119
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
16
120
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
data/bors.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "bors"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Sam Richardson"]
|
12
|
-
s.date = "2013-01-
|
12
|
+
s.date = "2013-01-24"
|
13
13
|
s.description = "Wrapper for the Vowpal Wabbit library"
|
14
14
|
s.email = "sam@richardson.co.nz"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,18 +26,27 @@ Gem::Specification.new do |s|
|
|
26
26
|
"VERSION",
|
27
27
|
"bors.gemspec",
|
28
28
|
"lib/bors.rb",
|
29
|
+
"lib/bors/command_line.rb",
|
29
30
|
"lib/bors/example.rb",
|
30
31
|
"lib/bors/example/feature.rb",
|
31
32
|
"lib/bors/exceptions.rb",
|
32
|
-
"lib/bors/
|
33
|
-
"lib/bors/
|
34
|
-
"lib/bors/
|
35
|
-
"lib/bors/
|
33
|
+
"lib/bors/math.rb",
|
34
|
+
"lib/bors/result.rb",
|
35
|
+
"lib/bors/result/samples.rb",
|
36
|
+
"lib/bors/result/settings.rb",
|
37
|
+
"lib/bors/result/statistics.rb",
|
36
38
|
"spec/bors.rb",
|
37
39
|
"spec/bors/example.rb",
|
38
40
|
"spec/bors/example/feature.rb",
|
41
|
+
"spec/bors/result.rb",
|
42
|
+
"spec/bors/result/samples.rb",
|
43
|
+
"spec/bors/result/settings.rb",
|
44
|
+
"spec/bors/result/statistics.rb",
|
45
|
+
"spec/fixtures/examples.txt",
|
46
|
+
"spec/fixtures/result.txt",
|
39
47
|
"spec/runner.rb",
|
40
|
-
"spec/spec_helper.rb"
|
48
|
+
"spec/spec_helper.rb",
|
49
|
+
"spec/tutorial.rb"
|
41
50
|
]
|
42
51
|
s.homepage = "http://github.com/rodeoclash/bors"
|
43
52
|
s.licenses = ["MIT"]
|
@@ -50,38 +59,23 @@ Gem::Specification.new do |s|
|
|
50
59
|
|
51
60
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
52
61
|
s.add_runtime_dependency(%q<oj>, [">= 0"])
|
53
|
-
s.
|
62
|
+
s.add_runtime_dependency(%q<hashie-pre>, ["~> 2.0.0.beta"])
|
54
63
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
55
64
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
56
65
|
s.add_development_dependency(%q<bundler>, [">= 0"])
|
57
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
58
|
-
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
59
|
-
s.add_development_dependency(%q<bundler>, [">= 0"])
|
60
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
61
|
-
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
62
66
|
else
|
63
67
|
s.add_dependency(%q<oj>, [">= 0"])
|
64
|
-
s.add_dependency(%q<
|
68
|
+
s.add_dependency(%q<hashie-pre>, ["~> 2.0.0.beta"])
|
65
69
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
66
70
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
67
71
|
s.add_dependency(%q<bundler>, [">= 0"])
|
68
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
70
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
71
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
72
|
-
s.add_dependency(%q<simplecov>, [">= 0"])
|
73
72
|
end
|
74
73
|
else
|
75
74
|
s.add_dependency(%q<oj>, [">= 0"])
|
76
|
-
s.add_dependency(%q<
|
75
|
+
s.add_dependency(%q<hashie-pre>, ["~> 2.0.0.beta"])
|
77
76
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
78
77
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
79
78
|
s.add_dependency(%q<bundler>, [">= 0"])
|
80
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
81
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
82
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
83
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
84
|
-
s.add_dependency(%q<simplecov>, [">= 0"])
|
85
79
|
end
|
86
80
|
end
|
87
81
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Bors
|
2
|
+
class CommandLine
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
"vw #{examples} #{cache_file} #{create_cache} #{passes} #{initial_regressor} #{final_regressor} #{predictions} #{min_prediction} #{max_prediction}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def examples
|
13
|
+
@options[:examples]
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_cache
|
17
|
+
raise Exceptions::ArgumentError.new('Must specify the cache file paramater as well when creating the cache') if @options[:create_cache] == true && @options[:cache_file].nil?
|
18
|
+
@options[:create_cache] == true ? "-c" : ""
|
19
|
+
end
|
20
|
+
|
21
|
+
def training_mode
|
22
|
+
@options[:training_mode] == true ? true : false
|
23
|
+
end
|
24
|
+
|
25
|
+
def run!
|
26
|
+
puts "VW Command: #{to_s}"
|
27
|
+
stdout_str, stderr_str, status = Open3.capture3(to_s)
|
28
|
+
raise Exceptions::VWCommandLineError.new(stderr_str) if status.success? == false
|
29
|
+
stdout_str
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def method_missing(m, *args, &block)
|
35
|
+
@options[m.to_sym] ? "--#{m.to_s} #{@options[m.to_sym]}" : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/bors/example/feature.rb
CHANGED
data/lib/bors/example.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
require_relative "exceptions"
|
2
|
-
require_relative "
|
2
|
+
require_relative "math"
|
3
3
|
require_relative "example/feature"
|
4
4
|
|
5
5
|
class Bors
|
6
6
|
class Example
|
7
|
-
include
|
7
|
+
include Math
|
8
8
|
|
9
9
|
def initialize(options)
|
10
10
|
@options = options
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_s
|
14
|
-
"#{label} #{importance} #{initial_prediction} #{tag}#{
|
14
|
+
"#{label} #{importance} #{initial_prediction} #{tag}#{features}".squeeze(' ')
|
15
15
|
end
|
16
16
|
|
17
17
|
def label
|
18
|
-
|
18
|
+
return_options_key_if_valid_number :label
|
19
19
|
end
|
20
20
|
|
21
21
|
def importance
|
@@ -36,27 +36,20 @@ class Bors
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
returning += " #{Feature.new(feature).to_s}"
|
52
|
-
end
|
53
|
-
else
|
54
|
-
returning += " #{Feature.new(options[:features]).to_s}"
|
55
|
-
end
|
56
|
-
|
39
|
+
def features
|
40
|
+
if @options[:namespaces] && @options[:namespaces].length > 0
|
41
|
+
@options[:namespaces].map do |name, options|
|
42
|
+
raise Exceptions::ArgumentError.new('Incorrect format for namescape, must be defined as a Hash') unless options.kind_of? Hash
|
43
|
+
returning = "|#{name}"
|
44
|
+
returning += ":#{options[:value]}" if options[:value]
|
45
|
+
returning += create_features_from_array(options[:features])
|
46
|
+
returning += " "
|
47
|
+
end.join.strip
|
48
|
+
else
|
49
|
+
returning = "|"
|
50
|
+
returning += create_features_from_array(@options[:features])
|
57
51
|
returning += " "
|
58
|
-
|
59
|
-
end.join.strip
|
52
|
+
end
|
60
53
|
end
|
61
54
|
|
62
55
|
private
|
@@ -69,6 +62,19 @@ class Bors
|
|
69
62
|
""
|
70
63
|
end
|
71
64
|
end
|
65
|
+
|
66
|
+
def return_options_key_if_valid_number(key)
|
67
|
+
if @options[key]
|
68
|
+
raise Exceptions::NotRealNumber.new unless is_number?(@options[key])
|
69
|
+
@options[key]
|
70
|
+
else
|
71
|
+
""
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_features_from_array(features)
|
76
|
+
features.map { |feature| " #{Feature.new(feature).to_s}" }.join
|
77
|
+
end
|
72
78
|
|
73
79
|
end
|
74
80
|
end
|
data/lib/bors/exceptions.rb
CHANGED
data/lib/bors/math.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
class Bors
|
5
|
+
class Result
|
6
|
+
class Samples
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
@samples = Array.new
|
11
|
+
found = false
|
12
|
+
|
13
|
+
data.each_line do |line|
|
14
|
+
if line.match(/^\n/)
|
15
|
+
break
|
16
|
+
end
|
17
|
+
if line.match('loss')
|
18
|
+
found = true
|
19
|
+
next
|
20
|
+
end
|
21
|
+
if found == true
|
22
|
+
average_loss, since_last, example_counter, example_weight, current_label, current_predict, current_features = line.scan(/\d+\.?\d*/)
|
23
|
+
@samples << {
|
24
|
+
:average_loss => average_loss,
|
25
|
+
:since_last => since_last,
|
26
|
+
:example_counter => example_counter,
|
27
|
+
:example_weight => example_weight,
|
28
|
+
:current_label => current_label,
|
29
|
+
:current_predict => current_predict,
|
30
|
+
:current_features => current_features
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def each(&block)
|
37
|
+
@samples.each do |sample|
|
38
|
+
if block_given?
|
39
|
+
block.call(sample)
|
40
|
+
else
|
41
|
+
yield sample
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json
|
47
|
+
Oj.dump(@samples)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
class Bors
|
5
|
+
class Result
|
6
|
+
class Settings < Hash
|
7
|
+
include Hashie::Extensions::MethodAccess
|
8
|
+
|
9
|
+
SPLIT_SETTINGS_LINE = /\s=\s/
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
lines = String.new
|
13
|
+
|
14
|
+
data.each_line do |line|
|
15
|
+
break if line.match('average')
|
16
|
+
lines += line
|
17
|
+
end
|
18
|
+
|
19
|
+
lines.each_line do |line|
|
20
|
+
line.match(SPLIT_SETTINGS_LINE) do |m|
|
21
|
+
label, value = line.split(SPLIT_SETTINGS_LINE)
|
22
|
+
self.send("#{label}=".gsub(' ', '_').downcase, value.gsub("\n", ""))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_h
|
29
|
+
hash = Hash.new
|
30
|
+
hash[:final_regressor] = self.final_regressor if self.respond_to?(:final_regressor)
|
31
|
+
hash[:num_weight_bits] = self.num_weight_bits.to_i if self.respond_to?(:num_weight_bits)
|
32
|
+
hash[:learning_rate] = self.learning_rate.to_i if self.respond_to?(:learning_rate)
|
33
|
+
hash[:initial_t] = self.initial_t.to_f if self.respond_to?(:initial_t)
|
34
|
+
hash[:power_t] = self.power_t.to_f if self.respond_to?(:power_t)
|
35
|
+
hash[:decay_learning_rate] = self.decay_learning_rate.to_i if self.respond_to?(:decay_learning_rate)
|
36
|
+
hash[:creating_cache_file] = self.creating_cache_file if self.respond_to?(:creating_cache_file)
|
37
|
+
#hash[:reading_from = self.reading_from # not matching due to lack of equals in output
|
38
|
+
hash[:num_sources] = self.num_sources.to_i if self.respond_to?(:num_sources)
|
39
|
+
hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_json
|
43
|
+
Oj.dump(self.to_h)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
class Bors
|
5
|
+
class Result
|
6
|
+
class Statistics < Hash
|
7
|
+
include Hashie::Extensions::MethodAccess
|
8
|
+
|
9
|
+
SPLIT_SETTINGS_LINE = /\s=\s/
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
lines = String.new
|
13
|
+
found = false
|
14
|
+
|
15
|
+
data.each_line do |line|
|
16
|
+
if line.match('finished run') && found == false
|
17
|
+
found = true
|
18
|
+
next
|
19
|
+
end
|
20
|
+
if found == true
|
21
|
+
lines += line
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
lines.each_line do |line|
|
26
|
+
line.match(SPLIT_SETTINGS_LINE) do |m|
|
27
|
+
label, value = line.split(SPLIT_SETTINGS_LINE)
|
28
|
+
self.send("#{label}=".gsub(' ', '_').downcase, value.gsub("\n", ""))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
hash = Hash.new
|
36
|
+
hash[:number_of_examples] = self.number_of_examples.to_i
|
37
|
+
hash[:weighted_example_sum] = self.weighted_example_sum.to_f
|
38
|
+
hash[:weighted_label_sum] = self.weighted_label_sum.to_f
|
39
|
+
hash[:average_loss] = self.average_loss.to_f
|
40
|
+
hash[:best_constant] = self.best_constant.to_f
|
41
|
+
hash[:total_feature_number] = self.total_feature_number.to_i
|
42
|
+
hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_json
|
46
|
+
Oj.dump(self.to_h)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/bors/result.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "result/settings"
|
2
|
+
require_relative "result/samples"
|
3
|
+
require_relative "result/statistics"
|
4
|
+
|
5
|
+
class Bors
|
6
|
+
class Result
|
7
|
+
|
8
|
+
def initialize(data)
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def settings
|
13
|
+
@settings ||= Settings.new(@data)
|
14
|
+
end
|
15
|
+
|
16
|
+
def samples
|
17
|
+
@samples ||= Samples.new(@data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def statistics
|
21
|
+
@statistics ||= Statistics.new(@data)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|